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