Как сделать выгрузку одного объекта в несколько в Конвертации данных 2.1

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

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

В этом материале мы подробнее рассмотрим, как правильно организовать выгрузку «один в несколько» в конфигурации 1С:Конвертация данных 2.1, разберем частые ошибки начинающих разработчиков и проанализируем два основных рабочих подхода.

В чем заключается проблема и распространенные ошибки

Рассмотрим типичную ошибку при вызове функции ВыгрузитьПоПравилу(). Разработчики часто пытаются разместить цикл выгрузки в обработчике «Перед выгрузкой» конкретного Правила конвертации свойств (ПКС) — например, для свойства Код.

Проанализируем, почему этот подход не работает:

  1. Назначение ПКС: Правило конвертации свойства отвечает за получение значения лишь одного поля конкретного объекта. Оно не управляет созданием и записью всего XML-узла элемента.
  2. Нарушение структуры XML: Вызов функции ВыгрузитьПоПравилу() внутри обработчика ПКС приводит к попытке сформировать полный узел элемента прямо в процессе записи атрибута другого элемента, что ломает структуру файла обмена.
  3. Зацикливание: Вызов правила из самого себя внутри свойства может привести к бесконечной рекурсии и аварийному завершению работы выгрузки.

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

Способ 1. Использование обработчика «Перед выгрузкой» в ПКО

Этот способ подходит, если исходный объект попадает на выгрузку штатным путем (например, зарегистрирован в плане обмена или переносится по умолчанию в составе выборки).

Разберем алгоритм по шагам:

  1. Откроем нужное ПКО (например, ПКО Номенклатура).
  2. Перейдем в обработчик события «Перед выгрузкой».
  3. Напишем цикл по табличной части объекта-источника.
  4. Для каждой строки сформируем структуру ВходящиеДанные и передадим ее в функцию ВыгрузитьПоПравилу().
  5. В конце обработчика обязательно установим флаг Отказ = Истина;, чтобы предотвратить стандартную выгрузку самого родительского объекта-источника.

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


Если Источник.КодиОбміну.Количество() > 0 Тогда

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

КонецЕсли;

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

Способ 2. Использование ПВД с произвольным алгоритмом

Более правильным с точки зрения архитектуры КД 2.1 является вынос логики разделения объекта в Правило выгрузки данных (ПВД). Это позволяет разделить выборку данных и их непосредственную конвертацию.

Выполним следующие настройки:

  1. Создадим новое ПВД для справочника Номенклатура.
  2. Установим параметр Способ выборки данных в значение Произвольный алгоритм.
  3. В обработчике ПВД «Перед обработкой» напишем запрос, который разворачивает строки табличной части исходного справочника.
  4. В цикле по результату запроса вызовем процедуру ВыгрузитьПоПравилу().

Рассмотрим пример кода в обработчике «Перед обработкой» ПВД:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Номенклатура.Ссылка КАК Ссылка,
    |	Номенклатура.Наименование КАК Наименование,
    |	ТЧ.КодиОбміну КАК Код
    |ИЗ
    |	Справочник.Номенклатура.КодиОбміну КАК ТЧ
    |	ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
    |		ПО ТЧ.Ссылка = Номенклатура.Ссылка";

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

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

Прием данных из структуры ВходящиеДанные в ПКО

Чтобы база-приемник корректно прочитала реквизиты, переданные через структуру ВходящиеДанные, необходимо настроить ПКС в правиле конвертации объектов:

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

Важные технические нюансы и кэширование

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

В Конвертации данных 2.1 работает встроенный механизм кэширования выгруженных объектов. Если в процедуру ВыгрузитьПоПравилу() в качестве источника несколько раз передается ссылка на один и тот же объект, система считает, что элемент уже обработан, и пропускает повторные вызовы.

Чтобы избежать этой проблемы, используем следующие приемы:

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

← На главную