Как правильно передать массив с клиента на сервер в 1С:Предприятие 8?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке управляемого приложения на платформе 1С:Предприятие 8 начинающие программисты часто сталкиваются с фундаментальной ошибкой проектирования: попыткой вызвать клиентский метод из серверного контекста. В этой статье мы подробно разберем, почему возникает ошибка «процедура или функция не обнаружена», изучим базовые правила клиент-серверного взаимодействия и рассмотрим оптимальные способы передачи массивов и других данных с клиента на сервер.

Выясняем причину: золотое правило архитектуры 1С

Для начала проанализируем ситуацию, описанную в исходной теме форума. Разработчик создает на клиенте массив в функции ПередачаМассива(), а затем пытается запустить эту функцию из серверной процедуры СКлиентаНаСервере(). В ответ платформа выдает ошибку о том, что вызываемый метод не обнаружен. Почему так происходит?

В управляемом приложении 1С строго разграничены контексты выполнения кода. Главный архитектурный постулат звучит так:

Клиент «видит» сервер и может вызывать его методы, но Сервер НЕ «видит» клиента и никогда не может инициировать вызов клиентских процедур или функций.

Когда вы выполняете код на сервере (процедура с директивой компиляции &НаСервере или &НаСервереБезКонтекста), компьютер (сервер приложений 1С) ничего не знает о запущенном на клиентском компьютере сеансе отображения формы. Он не может обратиться к модулю формы на клиенте, вызвать оттуда функцию или считать значения клиентских переменных напрямую. Именно поэтому попытка запустить клиентский метод с сервера всегда приводит к ошибке компиляции.

Правильный шаблон передачи данных (Клиент -> Сервер)

Чтобы успешно передать массив с клиента на сервер, мы должны полностью поменять логику взаимодействия. Нам нужно сделать инициатором вызова клиента. Алгоритм действий выглядит следующим образом:

  1. Создаем массив в клиентской процедуре (на клиенте).
  2. Заполняем этот массив необходимыми значениями.
  3. Вызываем серверную процедуру, передавая наш массив в качестве её параметра.

Рассмотрим подробнее, как должен выглядеть рабочий и синтаксически верный код в модуле управляемой формы:


&НаКлиенте
Процедура ВыполнитьПередачуДанных(Команда)

    // Шаг 1. Создаем массив на клиенте
    МассивДанных = Новый Массив;
    
    // Шаг 2. Заполняем его значениями
    МассивДанных.Добавить("Первое значение");
    МассивДанных.Добавить("Второе значение");
    МассивДанных.Добавить("Третье значение");
    
    // Шаг 3. Вызываем серверный метод и передаем массив параметром
    ОбработатьДанныеНаСервере(МассивДанных);

КонецПроцедуры

&НаСервереБезКонтекста
Процедура ОбработатьДанныеНаСервере(Знач МассивДанных)

    // Сервер принял массив и может выполнять с ним любые действия
    Для Каждого Элемент Из МассивДанных Цикл
        // Например, запишем информацию в журнал регистрации или обработаем данные
        ЗаписьЖурналаРегистрации("ПередачаМассива",,,, Элемент);
    КонецЦикла;

КонецПроцедуры

Контекстный и внеконтекстный вызовы: оптимизируем нагрузку

Обратите внимание на директивы компиляции серверных методов. Платформа 1С предлагает нам два ключевых варианта работы с сервером из модуля формы:

Использование ключевого слова Знач

Посмотрим на объявление серверной процедуры в нашем примере: Процедура ОбработатьДанныеНаСервере(Знач МассивДанных). Использование ключевого слова Знач здесь очень важно.

По умолчанию параметры в 1С передаются по ссылке. При вызове сервера это означает, что платформа отправит массив на сервер, выполнит процедуру, а затем сериализует измененный (или неизмененный) массив обратно и вернет его на клиент. Если вам не нужно возвращать измененный массив обратно на клиентский компьютер, обязательно пишите ключевое слово Знач. Это блокирует обратную передачу данных по сети, экономя системные ресурсы.

Ограничения на типы данных при передаче

Важно помнить, что клиент и сервер общаются между собой посредством сериализации данных (перевода объектов 1С в поток байтов XML/JSON и обратно). Из-за этого накладываются жесткие ограничения на типы данных, которые можно передавать в параметрах между клиентом и сервером:

  1. Вы можете свободно передавать примитивные типы данных (строки, числа, булевы значения, даты).
  2. Допускается передача ссылочных типов данных (например, ссылки на справочники СправочникСсылка.Номенклатура или документы).
  3. Вы можете передавать универсальные коллекции, поддерживающие сериализацию (такие как Массив, Структура, Соответствие).
  4. Критическое ограничение: Вы не можете передать напрямую объекты базы данных (например, СправочникОбъект или ДокументОбъект), а также типы данных, которые существуют исключительно на сервере (такие как ТаблицаЗначений, ДеревоЗначений, Запрос).

Если вам необходимо передать таблицу данных с клиента на сервер, напрямую передать объект ТаблицаЗначений не получится. Нам придется обойти это ограничение, преобразовав таблицу в массив структур на клиенте, передав этот массив на сервер, и затем собрав таблицу значений обратно на сервере.

Альтернативный вариант: Использование временного хранилища

Если ваш массив содержит огромное количество элементов (десятки или сотни тысяч строк), передача его напрямую через параметры метода может замедлить работу интерфейса. Для работы с большими массивами данных или тяжелыми файлами в 1С предусмотрен специальный механизм — Временное хранилище.

Разберем по шагам, как передать массив через временное хранилище:


&НаКлиенте
Процедура ПередатьБольшойМассив(Команда)

    // 1. Создаем и заполняем тяжелый массив
    БольшойМассив = Новый Массив;
    Для Счетчик = 1 По 50000 Цикл
        БольшойМассив.Добавить("Строка данных № " + Формат(Счетчик, "ЧГ=0"));
    КонецЦикла;
    
    // 2. Помещаем массив во временное хранилище.
    // Привязываем его к уникальному идентификатору текущей формы,
    // чтобы платформа автоматически очистила память после закрытия формы.
    АдресХранилища = ПоместитьВоВременноеХранилище(БольшойМассив, ЭтаФорма.УникальныйИдентификатор);
    
    // 3. Передаем на сервер только короткую строку-адрес
    ОбработатьХранилищеНаСервере(АдресХранилища);

КонецПроцедуры

&НаСервереБезКонтекста
Процедура ОбработатьХранилищеНаСервере(Знач АдресХранилища)

    // 4. Извлекаем массив из хранилища на сервере
    МассивНаСервере = ПолучитьИзВременногоХранилища(АдресХранилища);
    
    // Выполняем серверные алгоритмы обработки
    Если МассивНаСервере <> Неопределено Тогда
        // Обрабатываем полученные данные...
        ОбщееКоличество = МассивНаСервере.Количество();
        ЗаписьЖурналаРегистрации("Успех",,,, "Успешно получено элементов: " + ОбщееКоличество);
    КонецЕсли;

КонецПроцедуры

Этот способ является наиболее профессиональным при передаче больших массивов информации, двоичных данных, картинок или файлов, поскольку минимизирует сетевой трафик во время выполнения вызова и бережет оперативную память системы.

← На главную