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