Как при выгрузке через универсальный формат (EnterpriseData) добавить свои данные без изменения схемы XDTO?

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

При настройке обмена данными между конфигурациями 1С с использованием универсального формата EnterpriseData часто возникает задача передачи дополнительных сведений, которые не предусмотрены в типовой схеме обмена. Основная дилемма, с которой мы сталкиваемся как разработчики: изменить пакет XDTO (что усложнит дальнейшее обновление типовой конфигурации) или найти способ передать данные через существующие механизмы.

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

Почему не стоит менять схему XDTO?

Изменение типового пакета (например, EnterpriseData_1_17_2) влечет за собой ряд проблем:

  1. При обновлении конфигурации придется отслеживать изменения в пакетах XDTO и вручную переносить свои правки.
  2. Необходимо обновлять схему как на стороне источника, так и на стороне приемника.
  3. Создание собственных версий формата требует регистрации их в менеджере обмена, что увеличивает объем кода поддержки.

Поэтому наиболее рациональным подходом является использование механизмов расширения, заложенных в самом формате EnterpriseData.

Решение 1: Использование коллекции AdditionalInfo

Формат EnterpriseData содержит специальное свойство AdditionalInfo (Дополнительная информация), которое представляет собой коллекцию пар «Ключ-Значение». Это штатный механизм для передачи произвольных данных.

Однако, как было замечено в обсуждении, AdditionalInfo находится в «шапке» объекта XDTO. Это создает сложность, если нам необходимо передать значение, привязанное к конкретной строке табличной части. Стандартная схема не позволяет вложить AdditionalInfo внутрь строки табличной части.

Разберем алгоритм решения этой проблемы.

Шаг 1. Подготовка данных на стороне отправителя

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

Нам необходимо воспользоваться событием отправки данных. В модуле МенеджерОбменаЧерезУниверсальныйФормат (или в соответствующем модуле расширения для обмена) найдем процедуру, отвечающую за отправку нашего документа. Обычно это обработчик ПКО_ИмяОбъекта_ПриОтправкеДанных.

Алгоритм действий:

  1. Формируем структуру соответствия, где ключом будет уникальный идентификатор строки (например, НомерСтроки или КлючСтроки), а значением — наши передаваемые данные.
  2. Сериализуем эту структуру в строку (например, в JSON).
  3. Помещаем полученную строку в AdditionalInfo объекта XDTO.

Рассмотрим пример кода для события отправки:


Процедура ПКО_РеализацияТоваровУслуг_ПриОтправкеДанных(ДанныеXDTO, ДанныеИБ, Свойства)
    
    // 1. Собираем данные из табличной части
    ДопДанныеТЧ = Новый Соответствие;
    
    Для Каждого СтрокаТЧ Из ДанныеИБ.Товары Цикл
        // Предположим, нужно передать нестандартное числовое поле "МойКоэффициент"
        Если ЗначениеЗаполнено(СтрокаТЧ.МойКоэффициент) Тогда
            // Используем НомерСтроки как ключ связи
            ДопДанныеТЧ.Вставить(СтрокаТЧ.НомерСтроки, СтрокаТЧ.МойКоэффициент);
        КонецЕсли;
    КонецЦикла;
    
    Если ДопДанныеТЧ.Количество() > 0 Тогда
        
        // 2. Сериализуем в JSON
        ЗаписьJSON = Новый ЗаписьJSON;
        ЗаписьJSON.УстановитьСтроку();
        ЗаписатьJSON(ЗаписьJSON, ДопДанныеТЧ);
        СтрокаJSON = ЗаписьJSON.Закрыть();
        
        // 3. Добавляем в AdditionalInfo
        // В ДанныеXDTO есть свойство AdditionalInfo, которое является списком XDTO
        
        // Создаем новый элемент для AdditionalInfo
        // Структура зависит от версии пакета, обычно это Тип "КлючевоеСвойство"
        // где есть поля "Свойство" и "Значение"
        
        СвойствоXDTO = Свойства.КомпонентыОбмена.ФабрикаXDTO.Создать(
            Свойства.КомпонентыОбмена.ФабрикаXDTO.Тип("http://v8.1c.ru/edi/edi_stnd/EnterpriseData/1.17", "КлючевоеСвойство"));
            
        СвойствоXDTO.Свойство = "CustomData_GoodsCoef"; // Наш уникальный ID
        СвойствоXDTO.Значение = СтрокаJSON;
        
        ДанныеXDTO.AdditionalInfo.Добавить(СвойствоXDTO);
        
    КонецЕсли;

КонецПроцедуры

Важный нюанс: Обратите внимание на пространство имен (URI) пакета XDTO. В примере указана версия 1.17, но в вашей конфигурации она может отличаться (1.10, 1.16 и т.д.). Получить правильный URI можно динамически из фабрики XDTO текущего пакета.

Шаг 2. Обработка данных на стороне получателя

Теперь нам нужно извлечь эти данные при загрузке. Используем событие ПКО_ИмяОбъекта_ПриКонвертацииДанныхXDTO (или ПослеЗагрузкиДанных, в зависимости от того, когда доступен объект).

В событии ПриКонвертацииДанныхXDTO у нас есть доступ к входящему пакету ДанныеXDTO и к формируемому ПолученныеДанные (объект базы данных, еще не записанный).


Процедура ПКО_РеализацияТоваровУслуг_ПриКонвертацииДанныхXDTO(ДанныеXDTO, ПолученныеДанные, Свойства)
    
    // Ищем наши данные в AdditionalInfo
    СтрокаJSON = "";
    Для Каждого ЭлементСписка Из ДанныеXDTO.AdditionalInfo Цикл
        Если ЭлементСписка.Свойство = "CustomData_GoodsCoef" Тогда
            СтрокаJSON = ЭлементСписка.Значение;
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
    Если Не ПустаяСтрока(СтрокаJSON) Тогда
        
        // Десериализуем
        ЧтениеJSON = Новый ЧтениеJSON;
        ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
        ДопДанныеТЧ = ПрочитатьJSON(ЧтениеJSON);
        ЧтениеJSON.Закрыть();
        
        // Распределяем данные по строкам ТЧ объекта
        // ПолученныеДанные - это уже объект документа (ДокументОбъект)
        
        Для Каждого СтрокаТЧ Из ПолученныеДанные.Товары Цикл
            
            // Ищем значение по ключу (НомерСтроки)
            // При чтении JSON ключи соответствия могут стать строками, поэтому приводим типы
            КлючПоиска = Строка(СтрокаТЧ.НомерСтроки); 
            
            // В структуре после JSON ключи - строки
            Если ДопДанныеТЧ.Свойство(КлючПоиска) Тогда
                ЗначениеКоэффициента = ДопДанныеТЧ[КлючПоиска];
                СтрокаТЧ.МойКоэффициент = ЗначениеКоэффициента;
            КонецЕсли;
            
        КонецЦикла;
        
    КонецЕсли;

КонецПроцедуры

Решение 2: Использование поля «Комментарий» (Workaround)

Если работа с XDTO-фабрикой кажется слишком сложной или в старых версиях БСП нет удобного доступа к AdditionalInfo, можно использовать «народный» метод: сериализацию в текстовое поле, которое уже есть в схеме.

Чаще всего для этого используют реквизит Комментарий. Логика следующая:

  1. В комментарий добавляется спец-тег, например #TECH_DATA:{...JSON...}.
  2. При выгрузке мы дописываем этот блок в конец комментария.
  3. При загрузке мы парсим комментарий, извлекаем блок, десериализуем его и удаляем из текста комментария, чтобы пользователь видел чистый текст.

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

Решение 3: Дополнительные реквизиты (ПВХ)

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

Мы можем использовать это программно:

  1. Перед выгрузкой программно добавить в коллекцию дополнительных реквизитов объекта нужное значение (даже если такого доп. реквизита нет в базе как элемента ПВХ, главное — соблюсти структуру).
  2. В этом случае 1С сама упакует это в XML.
  3. На стороне приемника перехватить чтение доп. реквизитов и переложить значение в нужную колонку табличной части.

Однако, для табличных частей этот метод также требует доработки, так как AdditionalProperties обычно привязаны к шапке документа.

Резюме

Для передачи данных табличной части без изменения схемы XDTO наиболее робастным (надежным) способом является сериализация данных строк в JSON и передача получившейся строки через штатную коллекцию AdditionalInfo.

Этот подход позволяет:

Не забывайте проверять типы данных при чтении JSON (числа, даты, строки), так как при сериализации типизация 1С может быть упрощена до форматов JSON.

← На главную