Как перенести данные табличной части, которых нет в формате обмена Конвертации данных 3.0?

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

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

В этой статье мы подробно разберем, как обойти это ограничение. Мы научимся использовать встроенный «багажник» формата в виде свойства AdditionalInfo, разберем двухэтапный процесс загрузки данных в БСП (Библиотеке Стандартных Подсистем) и рассмотрим изящный лайфхак автоматического заполнения табличных частей.

Понимание архитектуры КД 3.0: почему нельзя просто заполнить ТЧ «на лету»

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

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

Поэтому наша главная задача — красиво передать неформатные данные с первого этапа на второй.

---

Шаг 1. Отправка данных из источника (Выгрузка)

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

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


// Создаем массив структур, в который поместим строки нашей нетиповой ТЧ
МассивСтрокТЧ = Новый Массив;

Для Каждого СтрокаТЧ Из ДанныеИБ.НомераКиЗ Цикл
    СтруктураСтроки = Новый Структура;
    СтруктураСтроки.Вставить("НомерКиЗ", СтрокаТЧ.НомерКиЗ);
    СтруктураСтроки.Вставить("НоменклатураКод", СтрокаТЧ.Номенклатура.Код);
    
    МассивСтрокТЧ.Добавить(СтруктураСтроки);
КонецЦикла;

// Инициализируем структуру AdditionalInfo в объекте формата
ДополнительнаяИнформация = Новый Структура;
ДополнительнаяИнформация.Вставить("ТаблицаКиЗ", МассивСтрокТЧ);

// Помещаем структуру в XDTO-данные для отправки
ДанныеXDTO.Вставить("AdditionalInfo", ДополнительнаяИнформация);

Важное примечание: Передавать ссылки напрямую через AdditionalInfo не рекомендуется, так как в базе-приемнике ссылки источника превратятся в «битые». Передавайте уникальные идентификаторы (UID), коды или ИНН/КПП для последующего поиска в приемнике.

---

Шаг 2. Прием и временное сохранение данных (Первый этап загрузки)

При загрузке в базу-приемник первым делом отрабатывает обработчик ПриКонвертацииДанныхXDTO. Физического документа в базе еще нет, но нам нужно перехватить переданный массив и положить его во временный «карман» объекта.

Этим карманом выступает свойство ПолученныеДанные.ДополнительныеСвойства. Пропишем там следующий алгоритм:


// Проверяем наличие заполненного AdditionalInfo во входящих данных
Если ДанныеXDTO.Свойство("AdditionalInfo") И ТипЗнч(ДанныеXDTO.AdditionalInfo) = Тип("Структура") Тогда
    
    // Проверяем, пришла ли наша кастомная таблица
    Если ДанныеXDTO.AdditionalInfo.Свойство("ТаблицаКиЗ") Тогда
        // Перекладываем данные в ДополнительныеСвойства объекта-контейнера
        ПолученныеДанные.ДополнительныеСвойства.Вставить("ВременнаяТаблицаКиЗ", ДанныеXDTO.AdditionalInfo.ТаблицаКиЗ);
    КонецЕсли;
    
    // Если нужно передать другие реквизиты шапки, которых нет в формате:
    Если ДанныеXDTO.AdditionalInfo.Свойство("НетиповойРеквизитШапки") Тогда
         ПолученныеДанные.ДополнительныеСвойства.Вставить("НетиповойРеквизитШапки", ДанныеXDTO.AdditionalInfo.НетиповойРеквизитШапки);
    КонецЕсли;
    
КонецЕсли;

---

Шаг 3. Заполнение табличной части перед записью (Второй этап загрузки)

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

Сделать это нужно в обработчике ПКО ПередЗаписьюПолученныхДанных. Проанализируем пример кода:


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

// 2. Определяем объект для заполнения.
// Если документ уже был в ИБ, БСП передает его в параметре ДанныеИБ.
// Но безопаснее и правильнее заполнять ТЧ именно у ПолученныеДанные, 
// так как БСП сама синхронизирует эти свойства перед непосредственной записью.
ДокументОбъект = ПолученныеДанные;

// Очищаем существующую табличную часть в приемнике перед перезаполнением
ДокументОбъект.НомераКиЗ.Очистить();

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

---

Секретный лайфхак: Автоматическое заполнение ТЧ через совпадение имен

Существует малоизвестный встроенный механизм в БСП, который позволяет значительно сократить объем кода на стороне приемника. Если структура колонок табличной части в источнике совпадает со структурой колонок ТЧ в приемнике, вам не обязательно вручную обходить строки в обработчике ПередЗаписьюПолученныхДанных.

Достаточно в обработчике ПриКонвертацииДанныхXDTO поместить массив структур в ПолученныеДанные.ДополнительныеСвойства под ключом, имя которого в точности совпадает с именем табличной части объекта конфигурации-приемника.

Посмотрим на пример упрощенного кода в ПриКонвертацииДанныхXDTO:


// Имя ключа "НомераКиЗ" в точности соответствует имени табличной части документа в приемнике
Если ДанныеXDTO.AdditionalInfo.Свойство("ТаблицаКиЗ") Тогда
    ПолученныеДанные.ДополнительныеСвойства.Вставить("НомераКиЗ", ДанныеXDTO.AdditionalInfo.ТаблицаКиЗ);
КонецЕсли;

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

---

Важная деталь: Почему AdditionalInfo пропадает при переносе документов?

Иногда разработчики сталкиваются со следующей проблемой: при переносе справочника «Контрагенты» напрямую, заполненное AdditionalInfo отрабатывает отлично. Но если переносится документ, содержащий реквизит «Контрагент», то в процедуре ПриКонвертацииДанныхXDTO для этого контрагента поле AdditionalInfo оказывается пустым.

Выясним причину этого поведения. Согласно концепции EnterpriseData, при выгрузке документа все его ссылочные реквизиты (справочники) выгружаются не как полноценные объекты, а как ключевые свойства (например: УИД, Код, Наименование, ИНН) для быстрой идентификации. Ссылочный объект в составе документа не выгружается целиком, поэтому и его AdditionalInfo игнорируется.

Решение этой проблемы:

  1. Выполнять предварительную синхронизацию справочников (выгружать справочники отдельно в полном объеме, а затем переносить документы).
  2. Если данные нужны «здесь и сейчас», передавайте необходимые свойства контрагента непосредственно в AdditionalInfo самого документа, а при загрузке документа находите контрагента в базе и дозаполняйте его реквизиты.

---

Заключение

Мы подробно разобрали универсальную методику обхода ограничений формата EnterpriseData в Конвертации данных 3.0. Использование связки AdditionalInfo на стороне источника и ДополнительныеСвойства на стороне приемника позволяет реализовать интеграцию любой сложности без необходимости постоянного изменения XDTO-пакетов обмена. Используйте эти приемы в своих проектах, чтобы сделать обмен данными гибким и надежным!

← На главную