При настройке обмена данными между конфигурациями 1С с использованием универсального формата EnterpriseData часто возникает задача передачи дополнительных сведений, которые не предусмотрены в типовой схеме обмена. Основная дилемма, с которой мы сталкиваемся как разработчики: изменить пакет XDTO (что усложнит дальнейшее обновление типовой конфигурации) или найти способ передать данные через существующие механизмы.
В этой статье мы подробно разберем, как передать собственные данные (в том числе значения в табличных частях документов) без «порчи» типового пакета XDTO. Мы рассмотрим использование коллекции AdditionalInfo, сериализацию данных и работу с событиями менеджера обмена.
Изменение типового пакета (например, EnterpriseData_1_17_2) влечет за собой ряд проблем:
Поэтому наиболее рациональным подходом является использование механизмов расширения, заложенных в самом формате EnterpriseData.
Формат EnterpriseData содержит специальное свойство AdditionalInfo (Дополнительная информация), которое представляет собой коллекцию пар «Ключ-Значение». Это штатный механизм для передачи произвольных данных.
Однако, как было замечено в обсуждении, AdditionalInfo находится в «шапке» объекта XDTO. Это создает сложность, если нам необходимо передать значение, привязанное к конкретной строке табличной части. Стандартная схема не позволяет вложить AdditionalInfo внутрь строки табличной части.
Разберем алгоритм решения этой проблемы.
Поскольку мы не можем добавить поле в структуру строки XDTO, мы должны передать данные табличной части «свернутыми» в шапке. Для этого мы будем использовать сериализацию.
Нам необходимо воспользоваться событием отправки данных. В модуле МенеджерОбменаЧерезУниверсальныйФормат (или в соответствующем модуле расширения для обмена) найдем процедуру, отвечающую за отправку нашего документа. Обычно это обработчик ПКО_ИмяОбъекта_ПриОтправкеДанных.
Алгоритм действий:
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 текущего пакета.
Теперь нам нужно извлечь эти данные при загрузке. Используем событие ПКО_ИмяОбъекта_ПриКонвертацииДанныхXDTO (или ПослеЗагрузкиДанных, в зависимости от того, когда доступен объект).
В событии ПриКонвертацииДанныхXDTO у нас есть доступ к входящему пакету ДанныеXDTO и к формируемому ПолученныеДанные (объект базы данных, еще не записанный).
Процедура ПКО_РеализацияТоваровУслуг_ПриКонвертацииДанныхXDTO(ДанныеXDTO, ПолученныеДанные, Свойства)
// Ищем наши данные в AdditionalInfo
СтрокаJSON = "";
Для Каждого ЭлементСписка Из ДанныеXDTO.AdditionalInfo Цикл
Если ЭлементСписка.Свойство = "CustomData_GoodsCoef" Тогда
СтрокаJSON = ЭлементСписка.Значение;
Прервать;
КонецЕсли;
КонецЦикла;
Если Не ПустаяСтрока(СтрокаJSON) Тогда
// Десериализуем
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
ДопДанныеТЧ = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
// Распределяем данные по строкам ТЧ объекта
// ПолученныеДанные - это уже объект документа (ДокументОбъект)
Для Каждого СтрокаТЧ Из ПолученныеДанные.Товары Цикл
// Ищем значение по ключу (НомерСтроки)
// При чтении JSON ключи соответствия могут стать строками, поэтому приводим типы
КлючПоиска = Строка(СтрокаТЧ.НомерСтроки);
// В структуре после JSON ключи - строки
Если ДопДанныеТЧ.Свойство(КлючПоиска) Тогда
ЗначениеКоэффициента = ДопДанныеТЧ[КлючПоиска];
СтрокаТЧ.МойКоэффициент = ЗначениеКоэффициента;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Если работа с XDTO-фабрикой кажется слишком сложной или в старых версиях БСП нет удобного доступа к AdditionalInfo, можно использовать «народный» метод: сериализацию в текстовое поле, которое уже есть в схеме.
Чаще всего для этого используют реквизит Комментарий. Логика следующая:
#TECH_DATA:{...JSON...}.Этот метод работает, но он менее надежен («грязный» способ), так как поле комментария имеет ограничение по длине, и пользователь может случайно его изменить, если редактирование происходит не в момент обмена.
В схеме EnterpriseData существует свойство AdditionalProperties (Дополнительные реквизиты). Если ваша конфигурация поддерживает БСП-подсистему «Свойства», то дополнительные реквизиты выгружаются штатно.
Мы можем использовать это программно:
Однако, для табличных частей этот метод также требует доработки, так как AdditionalProperties обычно привязаны к шапке документа.
Для передачи данных табличной части без изменения схемы XDTO наиболее робастным (надежным) способом является сериализация данных строк в JSON и передача получившейся строки через штатную коллекцию AdditionalInfo.
Этот подход позволяет:
Не забывайте проверять типы данных при чтении JSON (числа, даты, строки), так как при сериализации типизация 1С может быть упрощена до форматов JSON.