Разработка и Конфигурация · 11 мин
Передача таблицы значений с клиента на сервер и обратно в 1С
Способы передачи таблицы значений между клиентом и сервером в 1С: хранилище значений, адрес во временном хранилище, строка JSON. Примеры кода, ограничения и ошибки.
Таблица значений — один из самых востребованных типов в прикладной разработке 1С, но у неё есть принципиальное ограничение: объект ТаблицаЗначений нельзя напрямую передать между клиентом и сервером в параметрах вызова процедур и функций. В тонком клиенте и веб-клиенте таблица значений существует только на сервере, и попытка вернуть её из серверной процедуры закончится ошибкой платформы.
Обойти ограничение можно несколькими способами: через временное хранилище, через сериализацию в строку (JSON или значение в строку внутреннего формата), через хранилище значений либо через данные формы. Выбор зависит от объёма данных, направления передачи и контекста — обычная это форма, фоновое задание или внешнее соединение.
Почему таблицу значений нельзя передать напрямую
В управляемом приложении клиент и сервер — это разные процессы, а в веб-клиенте вообще разные машины. Платформа передаёт между ними только сериализуемые типы: примитивы, ссылки, структуры, массивы и некоторые универсальные коллекции. Таблица значений в этот список не входит, потому что это сложный объект с колонками, типами, индексами и служебным состоянием.
При попытке вернуть таблицу значений из серверной процедуры с директивой &НаСервере или передать её параметром из клиентского кода платформа выдаст ошибку вида «Ошибка передачи данных между клиентом и сервером» или «Недопустимый тип параметра». Это не баг конфигурации, а архитектурное ограничение, и лечится оно только сменой способа передачи.
Передача через временное хранилище
Самый универсальный и рекомендуемый способ — поместить таблицу во временное хранилище на сервере, а клиенту вернуть только адрес (строку). Клиент передаёт этот адрес в следующий серверный вызов, и там таблица извлекается обратно методом ПолучитьИзВременногоХранилища.
&НаСервере
Функция СформироватьТаблицуНаСервере()
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Номенклатура");
ТЗ.Колонки.Добавить("Количество");
// ... заполнение таблицы ...
Возврат ПоместитьВоВременноеХранилище(ТЗ, УникальныйИдентификаторФормы);
КонецФункции
&НаКлиенте
Процедура ЗагрузитьДанные(Команда)
Адрес = СформироватьТаблицуНаСервере();
ОбработатьТаблицуНаСервере(Адрес);
КонецПроцедуры
&НаСервере
Процедура ОбработатьТаблицуНаСервере(Адрес)
ТЗ = ПолучитьИзВременногоХранилища(Адрес);
// работа с таблицей
КонецПроцедуры
Второй параметр ПоместитьВоВременноеХранилище — уникальный идентификатор формы. Он важен: данные, помещённые с привязкой к форме, живут, пока открыта форма, и удаляются при её закрытии. Если передать Неопределено, значение хранится до конца сеанса и создаёт риск утечки памяти на сервере при массовых вызовах.
Передача таблицы с клиента на сервер
Обратное направление — когда таблица собрана на клиенте (например, загружена из файла Excel через расширение работы с файлами) и её нужно обработать на сервере. Здесь временное хранилище тоже работает: на клиенте таблицу значений создать нельзя, но можно сформировать массив структур и передать его, либо использовать ПоместитьВоВременноеХранилище на клиенте для двоичных данных файла.
Типовой сценарий загрузки из файла выглядит так: клиент читает файл, формирует массив структур (структуры сериализуются свободно) и передаёт его параметром в серверную процедуру. На сервере массив преобразуется в таблицу значений, если это нужно для запроса или проведения документа.
&НаКлиенте
Функция СобратьДанные()
Данные = Новый Массив;
Строка = Новый Структура("Номенклатура, Количество", Товар, 10);
Данные.Добавить(Строка);
Возврат Данные;
КонецФункции
&НаСервере
Функция МассивВТаблицу(Данные)
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Номенклатура");
ТЗ.Колонки.Добавить("Количество");
Для Каждого Элемент Из Данные Цикл
ЗаполнитьЗначенияСвойств(ТЗ.Добавить(), Элемент);
КонецЦикла;
Возврат ТЗ;
КонецФункции
У этого подхода есть ограничение: структура не может содержать вложенных таблиц значений и мутабельных объектов — только примитивы, ссылки, массивы и другие структуры. Если в исходных данных есть составные типы, их нужно привести к простым перед отправкой.
Сериализация через JSON и ЗначениеВСтрокуВнутр
Когда нужно передать таблицу через HTTP-сервис, внешнее соединение или сохранить её между сеансами, используют сериализацию в строку. Встроенный вариант — функции ЗначениеВСтрокуВнутр и ЗначениеИзСтрокиВнутр, которые преобразуют таблицу во внутренний формат платформы. Он сохраняет типы колонок точно, но читается только самой 1С.
// На сервере: таблица -> строка
СтрокаТЗ = ЗначениеВСтрокуВнутр(ТЗ);
// Обратно
ТЗ = ЗначениеИзСтрокиВнутр(СтрокаТЗ);
Для обмена с внешними системами подходит JSON. Таблицу преобразуют в массив структур и записывают через ЗаписьJSON. Ссылки при этом сериализуются как строки представления, поэтому для восстановления ссылок потребуется отдельно передавать уникальные идентификаторы или использовать СериализаторXDTO.
Сравнение способов передачи
Лучший выбор внутри одной формы и сеанса. Полная точность типов, минимум кода. Не подходит для обмена между сеансами и внешними системами.
Простая передача параметром клиент-сервер. Требует ручной сборки и разборки, типы колонок теряются до примитивов и ссылок.
Точная сериализация в строку, работает между сеансами 1С. Не читается внешними системами, строка объёмная.
Стандарт для интеграций и HTTP-сервисов. Требует отдельной обработки ссылок и дат, типы восстанавливаются вручную.
Таблица значений как реквизит формы
Если таблица нужна для отображения и редактирования в форме, передавать её вообще не требуется. Добавьте реквизит формы типа «ТаблицаЗначений» с нужными колонками — платформа автоматически синхронизирует его между клиентом и сервером при каждом вызове. Серверная процедура заполняет реквизит, и на клиенте данные появляются сразу после возврата из вызова.
&НаСервере
Процедура ЗаполнитьНаСервере()
ТаблицаТоваров.Очистить(); // реквизит формы
Запрос = Новый Запрос("ВЫБРАТЬ ...");
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Строка = ТаблицаТоваров.Добавить();
ЗаполнитьЗначенияСвойств(Строка, Выборка);
КонецЦикла;
КонецПроцедуры
Учтите, что реквизит формы передаётся между клиентом и сервером целиком при каждом серверном вызове. При таблицах в десятки тысяч строк это заметно замедляет работу формы. В таких случаях лучше использовать динамический список или передавать данные порциями.
Проверка результата и типичные ошибки
После внедрения передачи проверьте полный цикл: таблица заполнена на одной стороне, принята на другой, количество строк и типы колонок совпадают. Особое внимание уделите пустым таблицам и таблицам без колонок — некоторые способы сериализации теряют структуру пустой таблицы, и на приёмной стороне нужно пересоздавать колонки явно.
Как проверить результат
Совпадает с исходной таблицей
Строк меньше или таблица пустая — потеря при сериализации
Ссылки остались ссылками, даты — датами
Всё превратилось в строки — типы потеряны при JSON-сериализации
ПолучитьИзВременногоХранилища возвращает таблицу
Возвращается Неопределено — адрес устарел или хранилище очищено
Серверные вызовы отрабатывают без видимой паузы
Форма подвисает — таблица слишком велика для реквизита формы
Выбор способа под задачу
Для обычной формы, где таблица заполняется на сервере и показывается пользователю, выбирайте реквизит формы — это самый простой и надёжный путь. Для промежуточных вычислений, когда таблица нужна только на сервере в нескольких последовательных вызовах, — временное хранилище с привязкой к форме.
Для загрузки данных из файла на клиенте — массив структур параметром. Для обмена с внешними системами и HTTP-сервисами — JSON с явной передачей идентификаторов ссылок. Для передачи между сеансами 1С (например, из фонового задания через регистр или файл) — ЗначениеВСтрокуВнутр или хранилище значений в базе данных.
Как выбрать действие
Частые вопросы
Можно ли вернуть таблицу значений из серверной функции напрямую?
Нет. Тип ТаблицаЗначений не сериализуется для передачи клиенту, платформа выдаст ошибку. Верните адрес временного хранилища, массив структур или заполните реквизит формы.
Сколько живёт адрес временного хранилища?
Если при помещении указан уникальный идентификатор формы — до закрытия формы. Если идентификатор не указан — до конца сеанса. После удаления данных ПолучитьИзВременногоХранилища вернёт Неопределено.
Как передать таблицу из фонового задания в форму?
В фоновом задании поместите результат во временное хранилище, а адрес сохраните через параметры задания или верните из метода ОжидатьЗавершениеВыполнения. Форма по адресу извлечёт таблицу серверным вызовом. Для длительного хранения сохраните таблицу в регистре сведений через хранилище значений.
Почему после передачи через JSON даты стали строками?
JSON не имеет типа «дата», и платформа записывает даты строкой. На приёмной стороне преобразуйте строки обратно в даты вручную или используйте ЗначениеВСтрокуВнутр, если обе стороны — 1С.
Можно ли передать таблицу значений в толстом клиенте обычного приложения?
Да, в обычном приложении ограничение отсутствует — таблица значений передаётся между клиентом и сервером напрямую. Описанные приёмы нужны для управляемых форм, тонкого и веб-клиента.
Что быстрее: временное хранилище или массив структур?
Для крупных таблиц эффективнее временное хранилище: по сети передаётся только короткий адрес, а сама таблица остаётся на сервере. Массив структур при каждом вызове сериализуется и передаётся целиком, что на больших объёмах заметно медленнее.
Что важно запомнить
Таблица значений напрямую между клиентом и сервером не передаётся. Для форм используйте реквизит формы, для серверной обработки — временное хранилище с идентификатором формы, для клиентских данных — массив структур, для интеграций — JSON или ЗначениеВСтрокуВнутр. Следите за объёмом данных и временем жизни хранилища.