Как перенести строки табличной части одного документа в отдельные новые документы в Конвертации данных 2.1?

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

При настройке обмена данными между конфигурациями 1С с помощью инструмента «Конвертация данных 2.1» (КД 2.1) разработчики часто сталкиваются со стандартными сценариями переноса «один в один» или «один ко многим». Однако бывают специфические задачи, когда структура метаданных в базах-источниках и приемниках принципиально отличается. Типичный пример — необходимость преобразовать каждую строку табличной части (ТЧ) одного исходного документа в отдельный полноценный документ в базе-приемнике. Например, когда документ «Пересортица товаров» в конфигурации «Розница» должен превратиться в несколько документов «Комплектация номенклатуры» в «Бухгалтерии предприятия».

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

Архитектура решения: как это работает?

Для реализации этой схемы обмена нам нужно спроектировать и настроить три ключевых компонента в правилах конвертации:

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

Рассмотрим реализацию каждого шага подробно.

Шаг 1. Создание и настройка ПКО для документа-приемника

Первым делом подготовим правило, которое будет непосредственно отвечать за создание документа «Комплектация номенклатуры» в базе-приемнике. Назовем это ПКО, например, КомплектацияНоменклатуры.

Поскольку у нас нет прямого физического документа-источника (мы конструируем его программно из строки таблицы), настроим ПКО следующим образом:

  1. В поле «Источник» оставляем значение пустым.
  2. В поле «Приемник» выбираем тип ДокументСсылка.КомплектацияНоменклатуры.

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

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

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

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

КоллекцияОбъектов = ВходящиеДанные.Комплектующие;

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

Шаг 2. Разработка ПВД и обход табличной части

Теперь нам нужно определить место, откуда будет запускаться выгрузка. Если сам исходный документ «Пересортица товаров» переносить в базу-приемник не требуется (а нужны только созданные на его основе комплектации), идеальным решением будет написать логику в ПВД (Правиле выгрузки данных) для пересортицы.

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

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

Рассмотрим пример реализации кода в обработчике «Перед выгрузкой» ПВД:


// Проверяем, что объект не помечен на удаление
Если Не Объект.ПометкаУдаления Тогда
    
    ИндексСтроки = 0;
    
    Для Каждого СтрокаТЧ Из Объект.Товары Цикл
        
        // Создаем структуру, которая заменит нам объект-источник
        ВходящиеДанные = Новый Структура;
        ВходящиеДанные.Вставить("Дата", Объект.Дата);
        ВходящиеДанные.Вставить("Организация", Объект.Организация);
        ВходящиеДанные.Вставить("Склад", Объект.Склад);
        
        // Заполняем реквизиты комплекта (шапка создаваемой Комплектации)
        // Например, при пересортице оприходуемый товар становится готовым комплектом
        ВходящиеДанные.Вставить("Номенклатура", СтрокаТЧ.НоменклатураОприходование);
        ВходящиеДанные.Вставить("Количество", СтрокаТЧ.КоличествоОприходование);
        
        // Формируем таблицу комплектующих (списываемый товар пойдет в ТЧ)
        ТЗКомплектующие = Новый ТаблицаЗначений;
        ТЗКомплектующие.Колонки.Добавить("Номенклатура");
        ТЗКомплектующие.Колонки.Добавить("Количество");
        
        НоваяСтрока = ТЗКомплектующие.Добавить();
        НоваяСтрока.Номенклатура = СтрокаТЧ.НоменклатураСписание;
        НоваяСтрока.Количество = СтрокаТЧ.КоличествоСписание;
        
        // Передаем таблицу в структуру под именем, которое ожидает ПКГС
        ВходящиеДанные.Вставить("Комплектующие", ТЗКомплектующие);
        
        // --- СИНХРОНИЗАЦИЯ И ЗАЩИТА ОТ ДУБЛИРОВАНИЯ ---
        // Генерируем уникальный детерминированный GUID для каждой комплектации.
        // За основу берем GUID исходного документа "Пересортица" и модифицируем его хвостовую часть.
        ИсходныйУИД = Строка(Объект.Ссылка.УникальныйИдентификатор());
        УникальныйИдентификаторСтроки = Лев(ИсходныйУИД, 24) + Формат(ИндексСтроки, "ЧЦ=12; ЧРГ=; ЧГ=0");
        
        ВходящиеДанные.Вставить("ИдентификаторОбъекта", УникальныйИдентификаторСтроки);
        
        // Вызываем программную выгрузку по нашему настроенному ПКО
        ВыгрузитьПоПравилу(,, ВходящиеДанные,, "КомплектацияНоменклатуры");
        
        ИндексСтроки = ИндексСтроки + 1;
        
    КонецЦикла;
    
КонецЕсли;

// Обязательно отменяем стандартную выгрузку самого документа "Пересортица товаров",
// так как вместо него мы уже выгрузили созданные комплектации
Отказ = Истина; 

Шаг 3. Решение проблемы уникальной идентификации и защиты от дублей

Если запустить обмен в таком виде, документы успешно создадутся в базе-приемнике. Однако при повторной выгрузке тех же самых данных система создаст точно такие же документы заново, проигнорировав уже существующие. Это происходит потому, что у ПКО отсутствует физический объект-источник, и стандартный механизм поиска по уникальному идентификатору 1С (GUID) не может сопоставить объекты.

Для решения этой проблемы мы применили в коде выше детерминированную генерацию GUID. Мы взяли GUID исходного документа-пересортицы (он всегда статичен) длиной 36 символов, отрезали последние 12 символов и заменили их на индекс строки табличной части, дополненный нулями. Таким образом, для первой строки документа с UUID e1c2d3f4-b5a6-7c8d-9e0f-112233445566 мы получим UUID e1c2d3f4-b5a6-7c8d-9e0f-000000000000, для второй — e1c2d3f4-b5a6-7c8d-9e0f-000000000001 и так далее. Эти идентификаторы никогда не изменятся при повторных обменах, что гарантирует стабильную связь.

Теперь настроим правила поиска в ПКО КомплектацияНоменклатуры, чтобы база-приемник умела обрабатывать эти идентификаторы:

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

ГУИД = "";
Если Не ПараметрыОбъекта = Неопределено Тогда
    ПараметрыОбъекта.Sвойство("ИдентификаторОбъекта", ГУИД);
КонецЕсли;

Если ЗначениеЗаполнено(ГУИД) Тогда
    // Пытаемся получить ссылку в базе-приемнике по нашему детерминированному GUID
    СсылкаНаДокумент = Документы.КомплектацияНоменклатуры.ПолучитьСсылку(Новый УникальныйИдентификатор(ГУИД));
    
    // Передаем эту ссылку механизму КД. 
    // Если документ с таким GUID уже есть в базе — КД найдет его и обновит.
    // Если его еще нет — КД автоматически создаст новый пустой документ именно с этим GUID, а затем заполнит его реквизиты.
    СсылкаНаОбъект = СсылкаНаДокумент;
    ПрекратитьПоиск = Истина;
КонецЕсли;

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

Резюме

Мы подробно разобрали сложный сценарий трансформации структуры данных при обмене через «Конвертацию данных 2.1». Использование программного выгрузки через ВыгрузитьПоПравилу() в сочетании с передачей параметров через ВходящиеДанные дает разработчику полную свободу действий. А генерация предсказуемых уникальных идентификаторов на основе исходных объектов позволяет сохранить ссылочную целостность баз данных и защитить систему от дублей. Применяйте эти паттерны в своих правилах обмена для решения нестандартных интеграционных задач любой сложности!

← На главную