Разработчики 1С часто сталкиваются с ситуацией, когда данные, подготовленные на сервере в объекте типа ТаблицаЗначений, необходимо передать на сторону клиента. Однако при попытке сделать это напрямую через временное хранилище или как возвращаемое значение функции, программист получает Неопределено. Разберем, почему это происходит и какими способами можно решить эту задачу в управляемом приложении.
Основная причина кроется в архитектуре управляемого приложения. Объект типа ТаблицаЗначений является исключительно серверным. Он предназначен для быстрой обработки данных в памяти сервера и не может существовать в контексте тонкого или веб-клиента. Когда мы используем функцию ПолучитьИзВременногоХранилища на клиенте, платформа автоматически проверяет тип извлекаемого объекта. Если тип объекта недоступен на клиенте (как в случае с ТаблицаЗначений), система не вызывает ошибку, а просто возвращает Неопределено. Это защитный механизм, предотвращающий передачу тяжелых серверных объектов в клиентский сеанс.
Это самый популярный и универсальный метод. Суть заключается в том, что мы обходим ограничение, преобразуя каждую строку таблицы в Структура, а все структуры собираем в Массив. Эти типы данных прекрасно сериализуются и доступны на клиенте.
Рассмотрим пример реализации на сервере:
&НаСервере
Функция ПолучитьДанныеВМассиве()
ТЗ = Новый ТаблицаЗначений;
// Допустим, мы заполнили ТЗ данными
МассивРезультат = Новый Массив;
Колонки = ТЗ.Колонки;
Для Каждого СтрокаТЗ Из ТЗ Цикл
СтруктураСтроки = Новый Структура;
Для Каждого Колонка Из Колонки Цикл
СтруктураСтроки.Вставить(Колонка.Имя, СтрокаТЗ[Колонка.Имя]);
КонецЦикла;
МассивРезультат.Добавить(СтруктураСтроки);
КонецЦикла;
Возврат МассивРезультат;
КонецФункции
Если в вашей конфигурации используется Библиотека Стандартных Подсистем (БСП), можно воспользоваться готовой функцией, которая сделает это быстрее: ОбщегоНазначения.ТаблицаЗначенийВМассив(ТЗ).
Если данные таблицы значений предназначены для отображения пользователю или должны быть доступны в контексте формы, лучше всего использовать реквизиты формы с типом ТаблицаЗначений. На стороне клиента такой реквизит представлен типом ДанныеФормыКоллекция, который доступен и там, и там.
Для передачи данных проанализируем использование встроенных методов ЗначениеВДанныеФормы и ДанныеФормыВЗначение. Посмотрим на алгоритм:
СписокОплат) и добавим в него нужные колонки.
&НаСервере
Процедура ЗаполнитьТаблицуНаФорме()
// Создаем серверный объект ТЗ
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Сумма");
ТЗ.Колонки.Добавить("Контрагент");
// Заполняем данными...
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.Сумма = 100;
// Копируем данные из ТЗ в реквизит формы "СписокОплат"
ЗначениеВДанныеФормы(ТЗ, Объект.СписокОплат);
КонецПроцедуры
После выполнения этой процедуры на сервере, данные в Объект.СписокОплат станут доступны на клиенте автоматически в рамках контекста формы.
Бывают ситуации, когда структура таблицы заранее неизвестна и мы не можем создать реквизиты в конфигураторе. В этом случае мы можем создать программно реквизиты формы и элементы интерфейса. Рассмотрим этот подход:
На сервере мы проанализируем колонки нашей таблицы значений, динамически добавим их в реквизиты формы через ИзменитьРеквизиты, а затем создадим элементы формы (поля таблицы), чтобы пользователь мог их видеть. Это более сложный, но гибкий путь для построения динамических отчетов или обработок.
Проанализируем альтернативный вариант: передачу данных через сериализацию. Если данных очень много, передача огромного массива структур может замедлить работу. В таких случаях можно упаковать таблицу в строку JSON на сервере и передать эту строку на клиент.
Преимущества этого метода:
При работе с временным хранилищем всегда обращайте внимание на второй параметр функции ПоместитьВоВременноеХранилище(Данные, ИдентификаторФормы). Если вы не укажете УникальныйИдентификатор формы, данные будут удалены сразу после завершения серверного вызова, и клиент не успеет их прочитать.
Также стоит помнить, что излишняя передача данных на клиент — это плохая практика для управляемого приложения. Всегда задавайте себе вопрос: "Действительно ли мне нужна вся таблица на клиенте?". Часто эффективнее выполнить всю обработку данных &НаСервереБезКонтекста и вернуть на клиент только итоговый результат или статус завершения операции.