Как в 1С 8.3 дополнить табличную часть без очистки существующих строк?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При автоматизации заполнения документов в среде 1С:Предприятие 8.3 разработчики часто сталкиваются с задачей переноса данных из одного документа в другой. Типовой сценарий — заполнение табличной части документа (например, Транспортная накладная) данными из документа-основания (например, Заказ поставщику).

Однако использование стандартного метода Загрузить() приводит к тому, что все ранее введенные пользователем строки в табличной части удаляются. Разберем, почему так происходит, какие ошибки часто допускаются при попытке обойти это ограничение и как правильно реализовать добавление новых строк с сохранением уже существующих данных.

Почему метод Загрузить() очищает табличную часть

Проанализируем базовый код, с которого начинаются подобные трудности:


&НаСервере
Процедура ЗаполнитьНаСервере()
    Массив = Объект.ЗаказПоставщику.ЗаказПоставщику.Выгрузить();
    Объект.Товар.Загрузить(Массив);
КонецПроцедуры

Метод платформы Загрузить() у табличной части или коллекции формы (ДанныеФормыКоллекция) всегда полностью перезаписывает содержимое. Он сначала очищает целевую таблицу и только затем помещает в нее переданные строки. Метода вроде «Догрузить» или параметра «НеОчищать» у функции Загрузить() в платформе 1С не существует.

Кроме того, в контексте управляемой формы свойство Объект.Товар является не привычной таблицей значений, а объектом типа ДанныеФормыКоллекция. Соответственно, специфические методы таблицы значений (такие как Свернуть(), Итог() или групповое объединение) к нему напрямую неприменимы.

Типичные ошибки при реализации дозаполнения

Рассмотрим ошибки, из-за которых универсальные алгоритмы из обсуждений могут не работать на практике:

  1. Пропущенные скобки при вызове метода: В коде часто встречается конструкция ТаблицаПриемник.Добавить. В языке 1С метод Добавить() обязательно требует круглых скобок. Попытка обратиться к нему как к свойству приводит к синтаксической ошибке во время исполнения.
  2. Несовпадение имен колонок: Метод ЗаполнитьЗначенияСвойств() сопоставляет реквизиты строго по идентичности их наименований. Если в источнике колонка называется Номенклатура, а в целевом документе — Товар, данные скопированы не будут, а в табличной части появятся пустые строки.
  3. Несовместимость типов данных: Передача коллекции ДанныеФормыКоллекция в процедуры общего назначения, которые жестко ожидают тип ТаблицаЗначений, завершается аварийной остановкой с ошибкой несоответствия типов.

Способ 1. Построчное добавление данных в цикле (рекомендуемый)

Наиболее простое и быстрое решение — обойти строки исходного документа непосредственно на сервере и добавить их в коллекцию формы по одной. Нам не требуется выполнять промежуточную выгрузку данных.

Посмотрим на пример реализации:


&НаСервере
Процедура ЗаполнитьНаСервере()
    
    // Получаем табличную часть документа-источника напрямую через ссылку
    ТаблицаИсточника = Объект.ЗаказПоставщику.ЗаказПоставщику;
    
    Для Каждого СтрокаИсточника Из ТаблицаИсточника Цикл
        НоваяСтрока = Объект.Товар.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаИсточника);
    КонецЦикла;
    
КонецПроцедуры

Если имена колонок в двух документах различаются, метод ЗаполнитьЗначенияСвойств() не сможет их сопоставить автоматически. В такой ситуации разберем явное заполнение конкретных полей:


&НаСервере
Процедура ЗаполнитьНаСервере()
    
    ТаблицаИсточника = Объект.ЗаказПоставщику.ЗаказПоставщику;
    
    Для Каждого СтрокаИсточника Из ТаблицаИсточника Цикл
        НоваяСтрока = Объект.Товар.Добавить();
        
        // Копируем одинаковые по имени реквизиты
        ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаИсточника);
        
        // Явно заполняем реквизиты с разными именами
        НоваяСтрока.Товар = СтрокаИсточника.Номенклатура;
        НоваяСтрока.Количество = СтрокаИсточника.КоличествоУпаковок;
    КонецЦикла;
    
КонецПроцедуры

Способ 2. Получение данных через запрос

Если документов-источников много или требуется предварительная фильтрация, отбор или преобразование колонок, эффективнее использовать объект Запрос. С помощью псевдонимов КАК мы можем сразу сопоставить имена полей источника и приемника.

Рассмотрим этот вариант подробнее:


&НаСервере
Процедура ЗаполнитьНаСервере()
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Заказ.Номенклатура КАК Товар,
        |   Заказ.Количество КАК Количество,
        |   Заказ.Цена КАК Цена,
        |   Заказ.Сумма КАК Сумма
        |ИЗ
        |   Документ.ЗаказПоставщику.ЗаказПоставщику КАК Заказ
        |ГДЕ
        |   Заказ.Ссылка = &Ссылка";
    
    Запрос.УстановитьПараметр("Ссылка", Объект.ЗаказПоставщику);
    Выборка = Запрос.Выполнить().Выбрать();
    
    Пока Выборка.Следующий() Цикл
        НоваяСтрока = Объект.Товар.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрока, Выборка);
    КонецЦикла;
    
КонецПроцедуры

Способ 3. Преобразование коллекции формы в объектную модель

Когда требуется выполнить с табличной частью сложные манипуляции (например, объединить несколько заказов, отсортировать строки или выполнить метод Свернуть() для объединения одинаковых позиций), данные формы временно преобразуют в прикладной объект.

Разберем последовательность действий:


&НаСервере
Процедура ЗаполнитьНаСервере()
    
    // Преобразуем данные формы в реальный ДокументОбъект
    ДокОбъект = РеквизитФормыВЗначение("Объект");
    
    // Получаем строки источника в виде таблицы значений
    ТЗИсточник = Объект.ЗаказПоставщику.ЗаказПоставщику.Выгрузить();
    
    // Дополняем строки в табличную часть документа
    Для Каждого Стр Из ТЗИсточник Цикл
        НоваяСтрока = ДокОбъект.Товар.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрока, Стр);
    КонецЦикла;
    
    // При необходимости группируем дублирующиеся строки
    ДокОбъект.Товар.Свернуть("Товар, Цена", "Количество, Сумма");
    
    // Возвращаем измененный объект обратно в реквизит формы
    ЗначениеВРеквизитФормы(ДокОбъект, "Объект");
    
КонецПроцедуры

Важные нюансы при дозаполнении табличных частей

Чтобы алгоритм работал корректно в рабочих условиях, учтем следующие правила:

  1. Предотвращение дублирования: При повторном нажатии пользователем кнопки «Заполнить» строки добавятся снова. Рекомендуется либо проверять наличие строк по документу-источнику, либо удалять строки, относящиеся к текущему заказу, перед добавлением новых.
  2. Служебные реквизиты: При использовании ЗаполнитьЗначенияСвойств() безопаснее указывать список копируемых полей явным списком через запятую в третьем параметре. Это предотвратит случайную перезапись системных свойств, таких как НомерСтроки или уникальные идентификаторы связей.
← На главную