Разработка и Конфигурация · 10 мин
Как передать таблицу значений с сервера на клиент в 1С
Как передать таблицу значений с сервера на клиент в 1С: сериализация, ЗначениеВСтрокуВнутр, хранилище значения, типовые ошибки и примеры кода.
Таблица значений в 1С относится к несериализуемым типам: напрямую передать её из серверной процедуры в клиентскую нельзя. При попытке вернуть ТаблицаЗначений из серверного вызова платформа выдаёт ошибку о невозможности передачи данных между клиентом и сервером. Это ограничение архитектуры управляемого приложения, а не ошибка в коде.
Задача решается обходными путями: сериализацией таблицы в строку, преобразованием в массив структур, помещением во временное хранилище или передачей через ЗначениеВСтрокуВнутр. Выбор способа зависит от объёма данных, версии платформы и того, нужна ли таблица на клиенте как полноценный объект или достаточно только её содержимого.
Ниже разобраны рабочие варианты с примерами кода, их ограничения и типовые ошибки, которые приводят к потере данных или падению производительности.
Почему таблицу значений нельзя передать напрямую
В управляемом приложении клиент и сервер — это разные контексты исполнения, между которыми данные передаются по сети в сериализованном виде. Платформа умеет сериализовать примитивные типы (число, строка, дата, булево), ссылки, структуры, массивы и некоторые коллекции. Тип ТаблицаЗначений в этот список не входит вместе с ДеревоЗначений, РезультатЗапроса и рядом других объектов.
При попытке вернуть таблицу из серверной функции возникает ошибка вида «Ошибка передачи данных между клиентом и сервером» или «Недопустимое значение передаваемого параметра». Это поведение одинаково для тонкого, веб- и толстого клиента в управляемом режиме.
Важно понимать: ограничение действует только на границе клиент–сервер. Внутри одного контекста таблица значений передаётся свободно, в том числе между процедурами общего модуля.
Вариант 1. Массив структур — самый простой способ
Если на клиенте нужны только данные таблицы (для отображения, выбора или обработки), наиболее надёжный путь — преобразовать таблицу в массив структур на сервере и вернуть этот массив. Структуры и массивы сериализуются платформой без ограничений, при условии что значения в них — сериализуемых типов.
&НаСервере
Функция ПолучитьДанныеНаСервере()
ТЗ = СформироватьТаблицу(); // ваша таблица значений
Результат = Новый Массив;
Для Каждого СтрокаТЗ Из ТЗ Цикл
Стр = Новый Структура;
Для Каждого Колонка Из ТЗ.Колонки Цикл
Стр.Вставить(Колонка.Имя, СтрокаТЗ[Колонка.Имя]);
КонецЦикла;
Результат.Добавить(Стр);
КонецЦикла;
Возврат Результат;
КонецФункцииНа клиенте массив обходится обычным циклом, значения доступны через точку: Стр.Номенклатура, Стр.Количество. Если данные нужно показать в таблице формы, массив легко загружается в реквизит формы типа «ТаблицаЗначений» через ЗначениеВДанныеФормы или построчным заполнением.
Ограничение способа: структура не хранит описание типов колонок. Если на клиенте требуется именно объект ТаблицаЗначений с типизированными колонками (например, для передачи в другой механизм), потребуется восстанавливать колонки вручную или выбрать другой способ.
Вариант 2. ЗначениеВСтрокуВнутр
Функция ЗначениеВСтрокуВнутр сериализует произвольное значение, включая таблицу значений, во внутреннее строковое представление платформы. Обратное восстановление выполняется через ЗначениеИзСтрокиВнутр. Таким способом таблицу можно передать на клиент как обычную строку.
&НаСервере
Функция ПолучитьТЗСтрокой()
ТЗ = СформироватьТаблицу();
Возврат ЗначениеВСтрокуВнутр(ТЗ);
КонецФункции
&НаКлиенте
Процедура Загрузить(Команда)
СтрокаВнутр = ПолучитьТЗСтрокой();
ТЗ = ЗначениеИзСтрокиВнутр(СтрокаВнутр);
КонецПроцедурыСпособ сохраняет структуру колонок и типы, но имеет существенные минусы. Внутренний формат не документирован и не гарантированно совместим между версиями платформы — при обновлении релиза сохранённые строки могут перестать читаться. Кроме того, ЗначениеИзСтрокиВнутр на клиенте требует права интерактивной работы и в тонком клиенте может быть недоступен в некоторых контекстах; в веб-клиенте этот метод имеет ограничения.
Вариант 3. Временное хранилище
Для больших таблиц удобно не передавать данные в ответе серверного вызова, а поместить таблицу во временное хранилище и вернуть на клиент только адрес. Клиент при необходимости запрашивает данные по этому адресу в отдельном серверном вызове или передаёт адрес в другую форму.
- 1На сервере сформируйте таблицу значений
- 2Вызовите ПоместитьВоВременноеХранилище(ТЗ, УникальныйИдентификаторФормы) и верните адрес
- 3На клиенте передайте адрес в нужную форму или процедуру
- 4В серверном вызове получите таблицу через ПолучитьИзВременногоХранилища(Адрес)
- 5После использования удалите данные из хранилища, если они больше не нужны
Привязка к УникальныйИдентификатор формы важна: хранилище с таким идентификатором живёт, пока жива форма, и не плодит «висячие» данные на сервере. Без привязки данные удаляются по таймауту сеанса, что при массовой работе пользователей увеличивает расход памяти сервера.
Этот вариант стандартно используется при передаче данных между формами: например, подбор товаров в документ, где таблица подобранных позиций передаётся через хранилище, а не через параметры.
Вариант 4. Сериализация через XDTO или JSON
Если данные нужно передать не только на клиент, но и во внешнюю систему, логично сразу сериализовать таблицу в JSON. На сервере формируется массив структур или соответствие, затем используется ЗаписьJSON. На клиенте строка разбирается через ПрочитатьJSON.
Для полного восстановления таблицы значений с типами колонок подходит сериализатор XDTO: функции СериализаторXDTO.ЗаписатьXML и СериализаторXDTO.ПрочитатьXML. Таблица значений имеет фабричный тип XDTO и корректно проходит сериализацию. Минус — громоздкий XML и необходимость аккуратно обрабатывать значения, не входящие в модель XDTO.
Сравнение вариантов
Подходит для отображения и обработки данных на клиенте. Просто и надёжно, но типы колонок теряются
Полное восстановление таблицы с типами. Не подходит для хранения и обмена, зависит от версии платформы
Оптимально для больших объёмов и передачи между формами. Требует управления временем жизни данных
Для обмена с внешними системами и долговременного хранения. Больше кода, но формат стабилен
Частые ошибки при передаче таблицы на клиент
Первая типичная ошибка — попытка вернуть таблицу напрямую и последующий поиск «настройки, которая это разрешит». Такой настройки нет: ограничение архитектурное, и обходить его нужно одним из описанных способов.
Вторая ошибка — размещение несериализуемых значений внутри структур. Если в ячейке таблицы лежит, например, ХранилищеЗначения или объект другого несериализуемого типа, массив структур тоже не пройдёт границу клиент–сервер. Такие значения нужно предварительно преобразовать (например, извлечь данные из хранилища на сервере).
Третья ошибка — передача огромных таблиц на клиент целиком. Десятки тысяч строк через вызов сервера создают заметную нагрузку на сеть и память клиента. Для больших выборок правильнее использовать динамический список, постраничную загрузку или временное хранилище с последующей обработкой на сервере.
Как проверить результат
После реализации передачи проверьте три вещи: полноту данных, типы значений и поведение на целевом клиенте. Полнота проверяется сравнением количества строк на сервере и после восстановления на клиенте. Типы — контрольной проверкой ключевых колонок (даты, ссылки, числа с дробной частью).
Обязательно тестируйте на том типе клиента, который используется в работе: поведение тонкого клиента, веб-клиента и толстого клиента различается, особенно для ЗначениеИзСтрокиВнутр. Также проверьте работу под пользователем с ограниченными правами — часть операций требует прав, которых нет у рядовых пользователей.
Как проверить результат
Совпадает на сервере и на клиенте после восстановления
Строк меньше — потеря данных при преобразовании
Даты, числа и ссылки сохраняют тип после передачи
Все значения стали строками — потеряна типизация
Код выполняется без ошибок
Ошибка вызова ЗначениеИзСтрокиВнутр — замените способ на массив структур или JSON
FAQ
Можно ли передать таблицу значений как параметр в открываемую форму?
Напрямую — нет, параметры формы подчиняются тем же ограничениям сериализации. Стандартный приём: поместить таблицу во временное хранилище и передать в форму адрес хранилища, либо передать массив структур через структуру параметров.
Работает ли ЗначениеВСтрокуВнутр в веб-клиенте?
Запись в строку на сервере работает всегда, а вот восстановление на клиенте в веб-клиенте имеет ограничения и в ряде сценариев недоступно. Если решение должно работать в браузере, надёжнее использовать массив структур или JSON.
Что делать, если в таблице есть колонка с типом ХранилищеЗначения?
Хранилище значений не сериализуется. На сервере извлеките данные методом Получить() и передайте уже извлечённое значение, если оно сериализуемо. Картинки и двоичные данные передавайте отдельно, например через временное хранилище.
Какой способ выбрать для таблицы на 50 000 строк?
Передавать такой объём на клиент целиком не рекомендуется. Используйте временное хранилище с обработкой на сервере, динамический список или постраничную выдачу. Если клиенту нужен только итог — агрегируйте данные на сервере и передавайте свёрнутый результат.
Можно ли передать таблицу с клиента на сервер теми же способами?
Да, ограничение симметрично. С клиента на сервер таблицу передают через массив структур, сериализацию или временное хранилище. На практике чаще всего данные редактируются в реквизите формы типа ТаблицаЗначений, который платформа синхронизирует автоматически.
Что важно запомнить
Таблица значений не передаётся между клиентом и сервером напрямую. Для чтения данных используйте массив структур, для полного восстановления с типами — ЗначениеВСтрокуВнутр или XDTO, для больших объёмов и передачи между формами — временное хранилище. Следите за несериализуемыми значениями внутри колонок и временем жизни данных в хранилище.