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