Как в КД 2.0 создать несколько документов в приемнике на основании строк табличной части одного документа-источника

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

При настройке обмена данными через Конвертацию данных 2.0 (КД 2.0) часто возникает специфическая задача: необходимо, чтобы один документ из базы-источника (например, «Поступление товаров и услуг») превращался в несколько документов в базе-приемнике. Типичный пример — создание отдельного документа на каждую строку или группу строк табличной части. В этой статье мы подробно разберем, как реализовать такой алгоритм, избежать «схлопывания» документов при загрузке и правильно настроить правила выгрузки.

Разберем механику работы произвольного алгоритма в ПВД

Стандартная выгрузка в КД 2.0 работает по принципу «один объект источника — один объект приемника». Для реализации нашей задачи мы не можем использовать стандартный способ выборки данных. Нам потребуется настроить Правило выгрузки данных (ПВД) с типом «Произвольный алгоритм».

Когда мы выбираем произвольный алгоритм, вся ответственность за выборку данных и передачу их в правила конвертации ложится на нас. Ключевым объектом здесь является коллекция ВыборкаДанных. Проанализируем, как она должна быть заполнена:

  1. Проанализируем данные источника с помощью запроса.
  2. Для каждой строки, которая должна стать отдельным документом, создадим структуру.
  3. Поместим все созданные структуры в массив или таблицу значений и передадим их в ВыборкаДанных.

Рассмотрим пример кода в обработчике «Перед обработкой» правила выгрузки данных. Обратите внимание на важный нюанс: инициализация структуры должна происходить внутри цикла, иначе все элементы массива будут ссылаться на один и тот же объект.


ВыборкаДанных = Новый Массив;

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

Запрос.УстановитьПараметр("Ссылка", СсылкаНаОбъект);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаШапка = РезультатЗапроса.Выбрать();

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

Выясним причину «схлопывания» объектов и настроим уникальность

Часто программисты сталкиваются с тем, что в файл выгружается 10 объектов, а в приемнике создается только один. Выясним причину: это происходит из-за механизмов поиска и кеширования КД 2.0. Если Источник в ПКО не определен (пусто), система не может использовать ГУИД для идентификации. Более того, если у всех 10 документов одинаковый номер и дата, поиск по полям найдет первый созданный документ и будет обновлять его 9 раз.

Чтобы этого избежать, выполним два шага:

  1. Используем КлючВыгружаемыхДанных в обработчике «Перед выгрузкой» ПКО. Это заставит систему считать каждую структуру уникальным объектом еще на этапе выгрузки.
  2. Обеспечим уникальность полей поиска (например, модифицируем номер документа).

В ПКО в обработчике «Перед выгрузкой» напишем следующий код:


// Источник в данном случае — это наша структура из ПВД
Если ТипЗнч(Источник) = Тип("Структура") Тогда
    // Формируем уникальный ключ, чтобы КД не считала объекты дублями
    КлючВыгружаемыхДанных = Строка(Источник.Номер) + "_" + Строка(Источник.ИндексСтроки);
КонецЕсли;

Настройка поиска в базе-приемнике

Проанализируем ситуацию с загрузкой. Даже если выгрузка прошла корректно, при загрузке 1С увидит 10 документов с номером «001» и датой «01.01.2023». Она найдет первый документ и применит к нему данные всех остальных. В итоге мы получим один документ с данными последней строки ТЧ.

Рассмотрим варианты решения:

Вариант А: Модификация номера. В том же обработчике «Перед выгрузкой» ПКО можно изменить номер документа так, чтобы он стал уникальным:

Источник.Номер = Источник.Номер + "/" + Источник.ИндексСтроки;

В этом случае стандартный поиск по номеру и дате отработает корректно, создав разные документы.

Вариант Б: Отключение поиска. Если документы грузятся один раз и не предполагается их обновление, можно отключить все поля поиска в ПКО. Однако это опасный путь, который может привести к неконтролируемому дублированию данных при повторных обменах.

Работа с реквизитами через ВходящиеДанные

Посмотрим на пример настройки Правил конвертации свойств (ПКС). Поскольку источником у нас является структура, а не реальный объект метаданных, рекомендуется в ПКО оставить поле «Источник» пустым. В ПКС для каждого свойства нужно:

Важно: Проверьте, чтобы в ПКО была снята галочка «Искать объект по внутреннему идентификатору», так как у структуры его просто нет.

Проведение документов после загрузки

Проанализируем вопрос проведения. Если необходимо, чтобы созданные документы сразу проводились в приемнике, лучше всего использовать стандартный механизм ПКО. На закладке «Настройки» установите режим записи «Проведение». Если же требуется программная логика, используйте обработчик «После загрузки» в ПКО:


Если Объект.Проведен = Ложь Тогда
    Попытка
        Объект.Записать(РежимЗаписиДокумента.Проведение);
    Исключение
        Сообщить("Не удалось провести документ: " + ОписаниеОшибки());
    КонецПопытки;
КонецЕсли;

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

← На главную