К статье
Практический материал

Разработка и Конфигурация · 13 мин

Как передать массив с клиента на сервер в 1С

Как передать массив с клиента на сервер в 1С: серверные вызовы, сериализация, ограничения типов, типичные ошибки и проверка результата.

При разработке управляемых форм в 1С почти каждый разработчик сталкивается с ситуацией: на клиенте собран массив значений (выделенные строки таблицы, список ссылок, параметры отбора), а обработать его нужно на сервере — например, записать данные, выполнить запрос или сформировать отчёт. Прямого доступа к клиентским переменным у сервера нет, поэтому массив нужно явно передать через вызов серверной процедуры.

Хорошая новость: массив в 1С является сериализуемым типом, и платформа умеет передавать его между клиентом и сервером «как есть» — без ручного преобразования в строку или XML. Однако есть важные ограничения: типы элементов массива, направление вызова (серверную процедуру с параметрами нельзя вызвать с сервера на клиент), объём передаваемых данных и контекст формы.

Ниже разобраны рабочие способы передачи массива, ограничения платформы, варианты для сложных случаев (структуры, таблицы значений, несериализуемые типы) и типичные ошибки, из-за которых передача ломается.

Как устроена передача данных между клиентом и сервером в 1С

В тонком и веб-клиенте код формы исполняется в двух контекстах: клиентском (директивы &НаКлиенте) и серверном (&НаСервере, &НаСервереБезКонтекста). Между ними существует граница: каждый переход — это сетевой вызов, при котором параметры сериализуются платформой, передаются на сервер и там восстанавливаются.

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

Важно понимать направление вызовов. Клиент может вызвать серверную процедуру с произвольными параметрами. А вот сервер не может «вернуться» на клиент с параметрами — он может только вернуть результат функции. Поэтому вся логика строится по схеме: клиент собирает данные → вызывает сервер → сервер обрабатывает и возвращает результат.

Базовый способ: передать массив параметром серверной процедуры

Самый простой и правильный вариант — объявить в модуле формы серверную процедуру и передать массив как параметр. Клиентская процедура собирает данные и вызывает серверную:

&НаКлиенте

Процедура ОбработатьВыделенное(Команда)

МассивСсылок = Новый Массив;

Для Каждого Строка Из Элементы.СписокТоваров.ВыделенныеСтроки Цикл

МассивСсылок.Добавить(Строка);

КонецЦикла;

ОбработатьНаСервере(МассивСсылок);

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

&НаСервере

Процедура ОбработатьНаСервере(МассивСсылок)

Для Каждого Ссылка Из МассивСсылок Цикл

// работа со ссылками: запросы, запись, проверки

КонецЦикла;

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

Обратите внимание: параметр передаётся по значению в смысле границы клиент–сервер — сервер получает копию массива. Изменения, которые серверная процедура внесёт в массив, на клиент автоматически не вернутся. Если нужен результат — используйте функцию и возвращаемое значение.

Если обработка не требует контекста формы (реквизитов, данных объекта), лучше использовать директиву &НаСервереБезКонтекста. Такой вызов не тащит за собой сериализацию всей формы и работает быстрее, особенно на «тяжёлых» формах.

Порядок действий
  1. 1
    На клиенте сформируйте массив нужных значений (ссылок, строк, структур)
  2. 2
    Объявите серверную процедуру или функцию с параметром типа Массив
  3. 3
    Вызовите её из клиентской процедуры, передав массив
  4. 4
    На сервере обработайте элементы и при необходимости верните результат через функцию
  5. 5
    Проверьте результат на клиенте и обновите интерфейс

Передача массива через серверный общий модуль

Когда логика обработки универсальна и используется из разных форм, массив удобнее передавать в функцию общего модуля. Чтобы модуль был доступен с клиента, в его свойствах должны быть установлены флаги Сервер и Вызов сервера. Флаг «Клиент (управляемое приложение)» для такого модуля не нужен.

&НаКлиенте

Процедура СформироватьДокументы(Команда)

МассивЗаказов = СобратьВыделенныеЗаказы();

Результат = ОбработкаДокументовВызовСервера.СоздатьРеализации(МассивЗаказов);

Если Результат.ЕстьОшибки Тогда

ПоказатьПредупреждение(, Результат.ТекстОшибок);

КонецЕсли;

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

На сервере функция принимает массив и возвращает, например, структуру с результатом:

Функция СоздатьРеализации(МассивЗаказов) Экспорт

Результат = Новый Структура("ЕстьОшибки, ТекстОшибок", Ложь, "");

Для Каждого Заказ Из МассивЗаказов Цикл

// создание документов, контроль ошибок

КонецЦикла;

Возврат Результат;

КонецФункции

Такой подход хорошо тестируется и не привязан к конкретной форме. Ограничение одно: в серверном общем модуле недоступны реквизиты и элементы вызывающей формы — всё нужное передавайте параметрами.

Какие типы можно класть в массив, а какие сломают передачу

Массив сериализуется целиком только если сериализуем каждый его элемент. Платформа корректно переносит между клиентом и сервером примитивные типы (строка, число, дата, булево), ссылки на объекты базы данных, структуры, соответствия, вложенные массивы, списки значений и ряд других коллекций.

Проблемы возникают с несериализуемыми объектами: ТабличныйДокумент, COMОбъект, Запрос с установленными параметрами-объектами, ПостроительОтчета, потоки и подобные. Если такой объект окажется внутри массива или структуры, вызов упадёт с ошибкой сериализации уже на этапе передачи.

Отдельный случай — таблица значений. Она сериализуема, и массив таблиц передать можно, но для форм чаще используют реквизит типа «ТаблицаЗначений» или ДанныеФормыКоллекция, которые на сервере преобразуют в таблицу через РеквизитФормыВЗначение(). Передавать ДанныеФормыКоллекция напрямую параметром нельзя — сначала преобразуйте её.

Тип элементаПередаётсяКомментарий
Строка, Число, Дата, БулевоДаБез ограничений
Ссылки на объекты БДДаПередаётся ссылка, не объект
Структура, СоответствиеДаЕсли сериализуемы все вложенные значения
Массив, СписокЗначенийДаВложенность допустима
ТаблицаЗначенийДаДля форм удобнее реквизит формы
ТабличныйДокумент, COMОбъектНетОшибка сериализации
ДанныеФормыКоллекцияНетСначала преобразовать в таблицу значений

Объём данных и производительность вызова

Каждый серверный вызов — это сетевая передача. Массив из сотни ссылок пролетит незаметно, а массив из сотен тысяч строк с вложенными структурами может ощутимо «подвесить» клиент и канал. Платформа не накладывает жёсткого документированного лимита на размер параметров, но практический предел определяется здравым смыслом: чем больше данных, тем дольше сериализация, передача и десериализация.

Если на клиенте собирается очень большой набор данных, задайтесь вопросом: а нужно ли его гонять? Часто выгоднее передать на сервер не сами данные, а параметры отбора (период, организацию, настройки), а на сервере выполнить запрос и получить всё необходимое прямо из базы. Это и быстрее, и надёжнее.

Второй приём — порционная обработка: клиент передаёт массив частями (например, по несколько тысяч элементов), сервер обрабатывает порцию и возвращает прогресс. Так интерфейс остаётся отзывчивым, а при сбое не теряется вся работа. Для длительных операций в современных версиях платформы стоит рассмотреть фоновые задания с ДлительныеОперации из БСП или штатный механизм ФоновыеЗадания.Выполнить().

Сравнение вариантов

Массив параметром серверной процедуры

Подходит для небольших и средних наборов значений. Ограничение — только сериализуемые типы и умерный объём.

Реквизит формы типа ТаблицаЗначений

Удобен, когда данные уже отображаются в форме и редактируются пользователем. Не требует явной передачи — данные доступны на сервере через контекст формы.

Передача параметров отбора вместо данных

Оптимально для больших объёмов: сервер сам получает данные запросом. Не подходит, если данные существуют только на клиенте.

Фоновое задание с параметрами

Для длительной обработки больших массивов без блокировки интерфейса. Требует обработки результата через ожидание завершения.

Типичные ошибки при передаче массива

Самая частая ошибка — попытка вернуть изменённый массив «через параметр». Разработчик объявляет серверную процедуру, меняет в ней массив и ждёт, что клиент увидит изменения. Не увидит: на клиент вернётся исходная копия. Решение — функция с возвращаемым значением.

Вторая группа ошибок связана с директивами компиляции. Процедура с &НаКлиенте не видна из серверного контекста и наоборот; вызов серверной процедуры из тонкого клиента в модуле обычного приложения или наоборот приводит к ошибкам компиляции. Проверяйте директивы и флаги общих модулей в первую очередь, если вызов «не находится».

Третья типичная ситуация — в массив попадает Неопределено или значение неожиданного типа из-за незаполненных данных формы, и серверный код падает уже при обработке. Добавляйте проверку элементов перед добавлением в массив и защитную проверку на сервере: сервер никогда не должен слепо доверять данным, пришедшим с клиента.

Типичные ошибки
01
Ожидание, что серверная процедура изменит массив «на месте» — изменения не возвращаются, нужна функция с возвращаемым значением
02
Отсутствие флага «Вызов сервера» у общего модуля — модуль недоступен с клиента
03
Помещение в массив несериализуемых объектов (ТабличныйДокумент, Объект документа) — ошибка сериализации при вызове
04
Передача огромного массива одним вызовом вместо отбора на сервере — зависание клиента и рост сетевого трафика
05
Отсутствие проверки элементов массива на сервере — падение обработки на пустых или некорректных значениях

Проверка результата и отладка передачи

Чтобы убедиться, что массив дошёл до сервера корректно, достаточно простых контрольных точек. Первым делом сравните количество элементов на клиенте до вызова и на сервере после получения — расхождение сразу укажет на проблему сериализации или сборки массива.

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

Полезная практика — валидация на входе серверной функции: проверить, что параметр действительно массив (ТипЗнч(Параметр) = Тип("Массив")), что он не пуст, и что элементы имеют ожидаемый тип. Это дешёвая страховка, которая экономит часы разбора странных ошибок в глубине бизнес-логики.

Контрольные точки

Как проверить результат

Количество элементов массива
Норма

На сервере столько же элементов, сколько отправлено с клиента

Тревожный признак

Массив пуст или элементов меньше — ошибка сборки или сериализации

Типы элементов на сервере
Норма

Все элементы ожидаемого типа (ссылки, структуры)

Тревожный признак

Элементы типа Неопределено или строки вместо ссылок

Результат обработки
Норма

Функция вернула структуру с результатом, клиент её получил

Тревожный признак

Вызов завершился исключением, результат не пришёл

FAQ

Можно ли передать массив с сервера на клиент?

Да, но только как возвращаемое значение функции, вызванной клиентом. Инициировать вызов с сервера на клиент с произвольными параметрами нельзя — серверный код не имеет доступа к клиентскому контексту. Стройте логику так, чтобы клиент запрашивал данные и получал массив в ответ.

Что делать, если в массиве нужны сложные данные — несколько полей на элемент?

Используйте массив структур: каждая структура содержит именованные поля с сериализуемыми значениями. Это читабельнее, чем массив массивов, и безопаснее при изменении состава полей. Альтернатива для табличных данных — реквизит формы типа «ТаблицаЗначений».

Почему вызов падает с ошибкой «Ошибка передачи данных между клиентом и сервером»?

Почти всегда причина — несериализуемый тип внутри параметра: табличный документ, COM-объект, объект документа, данные формы. Найдите проблемный элемент, замените его на ссылку или примитивное представление, а объектную работу выполняйте на сервере.

Есть ли ограничение на размер передаваемого массива?

Жёсткого документированного лимита платформа не задаёт, но большие массивы увеличивают время сериализации и сетевую передачу. Практическая граница — десятки тысяч простых элементов. Для больших объёмов передавайте параметры отбора и получайте данные запросом на сервере или используйте порционную обработку.

Чем передача массива отличается от передачи списка значений?

Оба типа сериализуемы и передаются одинаково. Список значений дополнительно хранит представление и пометку каждого элемента, что удобно для интерактивных отборов. Если представления не нужны, массив проще и легче.

Нужно ли что-то настраивать, чтобы передать массив в фоновое задание?

Фоновое задание запускается с сервера, поэтому массив сначала передаётся с клиента на сервер обычным вызовом, а затем сервер передаёт его в ФоновыеЗадания.Выполнить() как элемент массива параметров. Требования к сериализуемости типов сохраняются и на этом шаге.

Итог

Что важно запомнить

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