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