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