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

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

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

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

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

Существует три рабочих способа: передать таблицу как параметр в серверную процедуру (в этом направлении платформа умеет маршалить таблицу), упаковать её в массив структур или поместить во временное хранилище. Дополнительно таблицу можно сериализовать в строку через ЗначениеВСтрокуВнутр или JSON, если нужен обмен с внешними механизмами.

Выбор способа зависит от направления передачи, объёма данных и того, нужна ли таблица на клиенте как полноценный объект или достаточно прочитать значения. Ниже разобраны все варианты с примерами кода и ограничениями.

Почему таблицу нельзя просто вернуть с сервера

В управляемом приложении клиент и сервер — разные контексты исполнения, между которыми данные передаются сериализацией. Платформа 1С умеет передавать примитивные типы, структуры, массивы, табличные части объектов и ряд других типов, но ТаблицаЗначений в список сериализуемых типов не входит.

Если написать функцию с директивой &НаСервере, которая возвращает ТаблицаЗначений, при вызове с клиента возникнет ошибка вида «Ошибка передачи данных между клиентом и сервером» или «Недопустимый тип значения». Это не баг, а архитектурное ограничение платформы.

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

Способ 1: передача таблицы параметром в серверную процедуру

Если таблица сформирована или загружена на клиенте и её нужно обработать на сервере, передайте её как параметр. Платформа сериализует таблицу при вызове и восстановит на сервере.

&НаКлиенте

Процедура ЗагрузитьНаСервере(Команда)

ТЗ = Новый ТаблицаЗначений;

ТЗ.Колонки.Добавить("Номенклатура");

ТЗ.Колонки.Добавить("Количество");

НоваяСтрока = ТЗ.Добавить();

НоваяСтрока.Номенклатура = "Товар 1";

НоваяСтрока.Количество = 5;

ОбработатьТаблицуНаСервере(ТЗ);

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

&НаСервереБезКонтекста

Процедура ОбработатьТаблицуНаСервере(ТЗ)

Для Каждого Строка Из ТЗ Цикл

// обработка на сервере

КонецЦикла;

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

Обратное направление — вернуть таблицу из серверной функции на клиент — так не работает. Для этого используйте способы ниже.

Способ 2: массив структур — универсальный вариант

Самый распространённый приём: на сервере таблица преобразуется в массив структур, где каждая структура — строка таблицы, а ключи — имена колонок. Массивы и структуры сериализуются без ограничений.

&НаСервереБезКонтекста

Функция ПолучитьДанныеТаблицей()

Запрос = Новый Запрос("ВЫБРАТЬ ПЕРВЫЕ 100 Ссылка, Наименование ИЗ Справочник.Номенклатура");

ТЗ = Запрос.Выполнить().Выгрузить();

Результат = Новый Массив;

Для Каждого Строка Из ТЗ Цикл

Элемент = Новый Структура;

Для Каждого Колонка Из ТЗ.Колонки Цикл

Элемент.Вставить(Колонка.Имя, Строка[Колонка.Имя]);

КонецЦикла;

Результат.Добавить(Элемент);

КонецЦикла;

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

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

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

Ограничения способа: имена колонок должны быть допустимыми идентификаторами (без пробелов и спецсимволов), а значения колонок — сериализуемыми типами. Ссылки на объекты базы передаются нормально, а вот ХранилищеЗначения или картинки потребуют отдельной обработки.

1c
Результат = Новый Массив;
Для Каждого Строка Из ТЗ Цикл
    Элемент = Новый Структура;
    Для Каждого Колонка Из ТЗ.Колонки Цикл
        Элемент.Вставить(Колонка.Имя, Строка[Колонка.Имя]);
    КонецЦикла;
    Результат.Добавить(Элемент);
КонецЦикла;

Способ 3: временное хранилище

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

&НаСервере

Функция ПоместитьТаблицуВХранилище()

ТЗ = СформироватьТаблицу(); // произвольная таблица

Возврат ПоместитьВоВременноеХранилище(ТЗ, УникальныйИдентификаторФормы);

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

Второй параметр — УникальныйИдентификаторФормы — привязывает хранилище к времени жизни формы. Без него данные удалятся при следующем серверном вызове, и попытка получить их по адресу вернёт Неопределено.

На клиенте адрес передаётся в другую форму или используется при следующем серверном вызове через ПолучитьИзВременногоХранилища(Адрес). Само по себе хранилище не решает задачу «увидеть таблицу на клиенте» — это механизм передачи между серверными вызовами.

Способ 4: сериализация в строку

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

  • ЗначениеВСтрокуВнутр(ТЗ) — внутренний формат платформы. На клиенте восстанавливается через ЗначениеИзСтрокиВнутр. Работает быстро, но формат недокументирован и не подходит для обмена с внешними системами.
  • ЗаписьJSON — преобразование массива структур в JSON-строку. Подходит для интеграций, но требует ручной сборки структуры и обратного разбора.

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

Сравнение способов передачи

Параметр процедуры

Клиент → сервер. Просто и быстро, но не работает в обратном направлении.

Массив структур

Сервер → клиент. Универсально, данные сразу доступны на клиенте, но требует кода преобразования.

Временное хранилище

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

Сериализация в строку

Обмен с внешними системами и фоновые задания. Избыточна для обычных форм.

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

На практике чаще всего таблица нужна не как объект, а как данные в табличной части формы. В этом случае передача вообще не требуется: реквизит формы типа ТаблицаЗначений доступен и на клиенте, и на сервере, платформа синхронизирует его автоматически.

Порядок действий
  1. 1
    Создайте реквизит формы типа ТаблицаЗначений и добавьте колонки.
  2. 2
    В серверной процедуре формы (&НаСервере, не БезКонтекста) выполните запрос и выгрузите результат в реквизит: ЗначениеВРеквизитФормы или прямое заполнение.
  3. 3
    На клиенте таблица уже доступна для отображения и редактирования.
  4. 4
    Если данные нужны вне формы — дополнительно упакуйте в массив структур.

Для процедур &НаСервере в контексте формы реквизит доступен напрямую: Объект.Товары.Загрузить(ТЗ) или ЭтаФорма.ТаблицаДанных.Загрузить(ТЗ). В процедурах БезКонтекста доступа к реквизитам формы нет — там и приходится использовать массивы структур или хранилище.

Типичные ошибки и ограничения

Типичные ошибки
01
Возврат ТаблицаЗначений из серверной функции — ошибка сериализации при вызове с клиента.
02
ПоместитьВоВременноеХранилище без УникальныйИдентификаторФормы — данные исчезают после следующего серверного вызова.
03
Имена колонок с пробелами или точками при упаковке в структуру — ошибка «Недопустимое имя ключа структуры».
04
Передача огромных таблиц массивом структур — рост трафика и задержки; для больших объёмов используйте хранилище или постраничную загрузку.
05
Попытка передать несериализуемые значения в колонках (ХранилищеЗначения, COM-объекты) — ошибка передачи данных.

Отдельно стоит упомянуть производительность. Каждый серверный вызов с передачей данных — это сериализация, сетевой трафик и десериализация. Таблица на десятки тысяч строк, упакованная в массив структур, создаст заметную паузу. Если клиенту нужно только показать данные, выводите их в таблицу формы на сервере; если нужна выборка — передавайте отбор и выполняйте запрос повторно там, где это уместно.

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

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

Вызов серверной функции с клиента
Норма

Данные получены без ошибок, массив содержит ожидаемое число элементов

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

Ошибка передачи данных между клиентом и сервером

Адрес временного хранилища
Норма

ПолучитьИзВременногоХранилища возвращает таблицу при повторном вызове

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

Возвращается Неопределено — не передан идентификатор формы

Структуры в массиве
Норма

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

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

Ошибка при вставке ключа или потеря части колонок

FAQ

Можно ли вернуть таблицу значений из серверной функции напрямую?

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

Чем массив структур лучше временного хранилища?

Массив структур сразу доступен на клиенте для обхода и обработки без дополнительных серверных вызовов. Хранилище возвращает только адрес — чтобы получить данные, потребуется ещё один вызов ПолучитьИзВременногоХранилища на сервере.

Почему данные из временного хранилища пропадают?

Чаще всего при помещении не указан второй параметр — УникальныйИдентификаторФормы. Без него хранилище очищается после завершения серверного вызова. Передайте идентификатор формы, и данные будут жить, пока открыта форма.

Передаются ли ссылки на объекты базы в массиве структур?

Да, ссылки сериализуются корректно и на клиенте остаются рабочими ссылками — их можно открывать, сравнивать, получать реквизиты через обращение к серверу. Не передаются несериализуемые типы: ХранилищеЗначения, COM-объекты, потоки.

Как передать очень большую таблицу без потери производительности?

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

Работают ли эти способы в тонком и веб-клиенте?

Да, ограничения сериализации и все описанные способы одинаковы для тонкого, толстого (управляемое приложение) и веб-клиента. В толстом клиенте с обычными формами разделения контекстов нет, и таблицу можно передавать напрямую.

Итог

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

ТаблицаЗначений напрямую между клиентом и сервером не передаётся. Клиент → сервер: параметром процедуры. Сервер → клиент: массив структур или реквизит формы. Между серверными вызовами и формами: временное хранилище с УникальныйИдентификаторФормы. Для больших объёмов избегайте передачи целиком.