Как правильно передавать дополнительные данные в обмене через Конвертацию данных 3 (EnterpriseData)

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

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

Вариант 1: Использование дополнительных реквизитов (метод «костыля»)

Рассмотрим ситуацию, когда разработчику требуется передать ТаблицуЗначений. Один из способов — это сериализация таблицы в строку и упаковка её в дополнительный реквизит объекта. Этот метод часто называют «костылем», так как он использует механизмы ПВХ (плана видов характеристик) не по прямому назначению, но он является рабочим в условиях ограниченного времени.

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


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

Разберем, что происходит в этом коде. Функция ДатьДопРеквизитНаСервере обеспечивает наличие элемента в плане видов характеристик ДополнительныеРеквизитыИСведения. Если реквизита с таким именем нет, он создается программно. Это позволяет передать строку практически неограниченной длины (благодаря КвалификаторыСтроки(0)).

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

Вариант 2: Использование штатного узла AdditionalInfo (Дополнительные сведения)

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

Выясним преимущества этого метода:

  1. Отсутствие лишних объектов: Вам не нужно создавать записи в справочниках или ПВХ в базе-приемнике.
  2. Прозрачность: Данные передаются внутри XML-структуры обмена в специальном блоке, предназначенном именно для расширения данных.
  3. Типизация: Узел имеет тип AnyType, что позволяет передавать туда не только строки, но и структуры или другие XDTO-объекты.

Посмотрим на пример того, как можно упаковать данные в AdditionalInfo на стороне отправителя:


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

На стороне приемника в обработчике ПослеЗагрузкиДанных мы сможем прочитать это значение и выполнить обратное преобразование. Рассмотрим пример получения данных:


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

Вариант 3: Расширение формата (XSD Extension)

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

Разберем этот процесс по шагам:

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

Этот путь требует глубокого знания КД3, но он гарантирует, что данные будут проверяться на соответствие схеме (валидация) еще на этапе выгрузки, что исключает ошибки чтения в базе-приемнике.

Рекомендации по выбору метода

Проанализируем ситуацию и выберем оптимальный путь решения задачи:

Используйте дополнительные реквизиты (Вариант 1), если:
— Вам нужно, чтобы данные были видны пользователю в интерфейсе карточки объекта после загрузки без дополнительного программирования.
— Вам нужно быстро «пробросить» одно строковое поле без изменения логики загрузки.

Используйте AdditionalInfo (Вариант 2), если:
— Вам нужно передать техническую информацию (таблицы, ключи связи, флаги логики).
— Вы хотите избежать засорения справочников и ПВХ служебными данными.
— Вы стремитесь к универсальности (JSON-строка в AdditionalInfo — стандарт индустрии).

Используйте расширение формата (Вариант 3), если:
— Вы разрабатываете тиражное решение или крупную корпоративную систему.
— Объем передаваемых «дополнительных» данных сопоставим с объемом основных данных объекта.
— Требуется строгая типизация и контроль целостности данных.

В заключение отметим, что хотя методы с использованием ЗначениеВстрокуВнутр и кажутся простыми, они несут риски при обновлении платформы. Мы рекомендуем использовать JSON-сериализацию в сочетании с AdditionalInfo как наиболее сбалансированный и современный способ передачи произвольных данных в 1С.

← На главную