Как добавить свой реквизит в файл выгрузки универсального формата обмена через расширение?

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

При настройке обмена данными между конфигурациями, например, «Бухгалтерия предприятия» и «ERP», часто возникает задача передать дополнительный реквизит, добавленный в основной конфигурации. В ряде случаев для переноса данных между не полностью идентичными конфигурациями может потребоваться адаптивная выгрузка и загрузка данных XML (подойдёт обработка выгрузки и загрузки XML с измененной структурой), но стандартный механизм универсального формата обмена (EnterpriseData) также требует доработки. Чтобы не снимать конфигурацию с поддержки, все изменения вносятся через расширение.

Рассмотрим ситуацию: в справочник Номенклатура добавлен новый реквизит МойРеквизит. Мы создали расширение, добавили в него свой XDTO-пакет, прописали обработчики для добавления реквизита в правила конвертации и для его заполнения при выгрузке. Отладчик показывает, что код выполняется, но в итоговом XML-файле обмена нашего реквизита нет. Выясним, в чем причина и как это исправить.

Анализ первоначальной попытки и ее ключевая ошибка

Давайте проанализируем, какие шаги были предприняты и где могла закрасться ошибка. Автор вопроса выполнил практически все необходимые действия:

  1. В основной конфигурации в справочник Номенклатура добавлен реквизит МойРеквизит.
  2. В расширении создан новый XDTO-пакет (например, EnterpriseData_1_16_2_ext) с уникальным пространством имен (http://v8.1c.ru/edi/edi_stnd/EnterpriseDataExt/1.16).
  3. В новом пакете настроен импорт основного пространства имен формата (http://v8.1c.ru/edi/edi_stnd/EnterpriseData/1.16).
  4. Программно зарегистрировано расширение формата в модуле ОбменДаннымиПереопределяемый.
  5. Добавлены обработчики для изменения правил конвертации и заполнения данных при отправке.

Код для регистрации расширения формата выглядит корректно:


&После("ПриПолученииДоступныхРасширенийФормата")
Процедура Расш1_ПриПолученииДоступныхРасширенийФормата(РасширенияФормата)
    РасширенияФормата.Вставить("http://v8.1c.ru/edi/edi_stnd/EnterpriseDataExt/1.16" , "1.16");
КонецПроцедуры

И код для модификации правил обмена тоже:


&ИзменениеИКонтроль("ДобавитьПКО_Справочник_Номенклатура_Отправка")
#Вставка
ПространствоИмен = "http://v8.1c.ru/edi/edi_stnd/EnterpriseDataExt/1.16";
ОбменДаннымиXDTOСервер.ИнициализироватьРасширениеПравилаКонвертацииОбъекта(ПравилоКонвертации, ПространствоИмен);
ДобавитьПКС(СвойстваШапки, "МойРеквизит", "МойРеквизит",,, ПространствоИмен);
#КонецВставки

Проблема кроется в настройке самого XDTO-пакета. Автор создал в нем тип объекта КлючевыеСвойстваНоменклатура для добавления реквизита. Этого недостаточно. Чтобы система поняла, как "приклеить" ваш новый реквизит к стандартному объекту, нужно расширить сам тип объекта Справочник.Номенклатура, а не только его ключевые свойства. Чтобы убедиться, что структура пакета описана верно, можно использовать инструменты, позволяющие выполнить проверку валидности файла XML на соответствие схеме XSD.

Ключевая ошибка: в расширяющем XDTO-пакете не был создан тип для самого объекта Справочник.Номенклатура и, что самое важное, у него не был указан базовый тип из основного пакета. Без этого платформа не может связать стандартную структуру объекта с вашими дополнениями.

Правильная настройка расширения формата через XDTO-пакет

Разберем по шагам, как корректно настроить расширение формата.

Шаг 1. Создание и настройка XDTO-пакета в расширении

В дереве объектов расширения создайте новый XDTO-пакет, например, EnterpriseData_1_16_2_ext. Укажите для него уникальное пространство имен, например, http://v8.1c.ru/edi/edi_stnd/EnterpriseDataExt/1.16.

Шаг 2. Импорт основного пространства имен

В свойствах созданного пакета перейдите на вкладку «Директивы импорта» и добавьте пространство имен основного формата, который вы расширяете. Например, http://v8.1c.ru/edi/edi_stnd/EnterpriseData/1.16. Это позволит вам ссылаться на типы данных из стандартного пакета.

Шаг 3. Создание расширяющего типа объекта

Это самый важный шаг. В своем пакете создайте новый «Тип объекта».

  1. Задайте ему имя. Логично назвать его так же, как и стандартный тип, например, СправочникОбъект.Номенклатура.
  2. В свойстве Базовый тип укажите полный тип объекта из основного пакета, который вы расширяете. Для этого нажмите кнопку выбора, в открывшемся окне найдите стандартный пакет (например, EnterpriseData_1_16_2) и выберите в нем нужный тип (например, СправочникОбъект.Номенклатура).
  3. Теперь в созданный вами тип объекта добавьте новое свойство — МойРеквизит, указав для него нужный тип данных (например, string из пространства имен http://www.w3.org/2001/XMLSchema).

Если ваша задача подразумевает более сложные изменения, такие как универсальный механизм добавления табличных частей, принцип расширения типов XDTO останется схожим, но потребует описания коллекций.

Шаг 4. Программная доработка правил и обработчиков

Код, приведенный автором, практически верен. Вы регистрируете расширение формата и добавляете новое свойство (ПКС) в правило конвертации объекта (ПКО).

Остается заполнить данными это свойство при выгрузке. Для этого используется обработчик события ПриОтправкеДанных.


&После("ПКО_Справочник_Номенклатура_Отправка_ПриОтправкеДанных")
Процедура Расш1_ПКО_Справочник_Номенклатура_Отправка_ПриОтправкеДанных(ДанныеИБ, ДанныеXDTO, КомпонентыОбмена, СтекВыгрузки)
    // Добавляем значение нашего реквизита напрямую в объект XDTO
    ДанныеXDTO.Вставить("МойРеквизит", ДанныеИБ.МойРеквизит);
КонецПроцедуры

После выполнения этих шагов новый реквизит должен корректно появиться в файле выгрузки в структуре объекта "Номенклатура".

Альтернативный и более простой способ: `AdditionalInfo` (Дополнительные сведения)

Существует и другой, более простой путь, который не требует создания и настройки XDTO-пакетов. Универсальный формат обмена предусматривает специальную коллекцию ДополнительныеСведения (в XML это будет `AdditionalInfo`) почти для каждого объекта. Она предназначена для передачи произвольных данных, не описанных в основной структуре. В некоторых случаях полезно реализовать заполнение значения данных дополнительных сведений объекта из источника в приемник для синхронизации этих свойств.

Как это работает?

Вместо всей работы с XDTO-пакетами, вам достаточно в обработчике ПриОтправкеДанных добавить нужные данные в эту коллекцию.


&После("ПКО_Справочник_Номенклатура_Отправка_ПриОтправкеДанных")
Процедура Расш1_ПКО_Справочник_Номенклатура_Отправка_ПриОтправкеДанных(ДанныеИБ, ДанныеXDTO, КомпонентыОбмена, СтекВыгрузки)
    // Проверяем, есть ли уже узел "ДополнительныеСведения"
    Если ДанныеXDTO.Свойства().Получить("ДополнительныеСведения") = Неопределено Тогда
        // Если нет, создаем его
        Фабрика = КомпонентыОбмена.ФабрикаXDTO;
        ТипДополнительныеСведения = Фабрика.Тип("http://v8.1c.ru/edi/edi_stnd/EnterpriseData/1.16", "ArrayOfAdditionalInfo");
        ДанныеXDTO.ДополнительныеСведения = Фабрика.Создать(ТипДополнительныеСведения);
    КонецЕсли;

    // Создаем новую запись для нашего реквизита
    ТипЗаписи = Фабрика.Тип("http://v8.1c.ru/edi/edi_stnd/EnterpriseData/1.16", "AdditionalInfo");
    НоваяЗапись = Фабрика.Создать(ТипЗаписи);
    НоваяЗапись.Имя = "МойРеквизит";
    НоваяЗапись.Значение = ДанныеИБ.МойРеквизит;
    
    // Добавляем запись в коллекцию
    ДанныеXDTO.ДополнительныеСведения.Добавить(НоваяЗапись);
КонецПроцедуры

На принимающей стороне останется только прочитать эту коллекцию и обработать данные.

Преимущества:

Ключевой недостаток:

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

Выводы

Выбор способа зависит от задачи:

  1. Если ваш новый реквизит необходим в принимающей базе только для самого элемента справочника и не требуется при обработке документов, — смело используйте AdditionalInfo. Это быстро и просто.
  2. Если же реквизит должен быть доступен всегда, в том числе при обмене документами, необходимо реализовывать полноценное расширение формата через XDTO-пакет — для этого есть доработанные правила EnterpriseData для обмена нетиповыми реквизитами.

При работе с обменами важно не только передать данные, но и обеспечить их целостность. Так, исправление правил обмена EnterpriseData позволяет избежать появления "битых ссылок" в справочниках. А для повышения стабильности системы в высоконагруженных базах рекомендуется оптимизация типовых обменов EnterpriseData, включая использование асинхронных механизмов.

← На главную