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