Как перенести настройки компоновки данных из ХранилищаЗначения через COM-соединение?

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

При межсистемной интеграции через COM-соединение разработчики нередко сталкиваются с необходимостью перенести документы или служебные настройки, содержащие реквизиты типа ХранилищеЗначения. Характерный пример — перенос документа «Пересчет товаров» в конфигурации «1С:Управление торговлей», где реквизит ОтборПересчета хранит в себе настройки системы компоновки данных (СКД).

Попытка передать такой объект напрямую через COM или вызвать стандартную функцию Base64Строка() приводит к ошибкам. Разберем по шагам, почему возникают сложности и как правильно организовать передачу данных.

Выясним причину ограничений COM-соединения и функций сериализации

Проанализируем природу используемых объектов и возникающие ошибки:

  1. Изоляция сред исполнения: Прикладные объекты компоновки (такие как НастройкиКомпоновкиДанных или элементы коллекций) создаются в контексте одного COM-сервера. Их нельзя передать «как есть» в контекст базы-приемника в виде ссылочных объектов памяти. Передача возможна только через универсальные типы (строка, число, массив простых типов) либо сериализованный XML-поток.
  2. Несовместимость типов в Base64Строка: Функция Base64Строка() платформы 1С предназначена исключительно для типа ДвоичныеДанные. Если передать в нее реквизит типа ХранилищеЗначения, система выдаст ошибку несоответствия типов.
  3. Проблема идентификаторов (UUID) при неидентичных базах: Сериализация хранилища вместе с его внутренними данными сохраняет внутренние ссылки на объекты метаданных и элементы справочников. При десериализации в другой информационной базе идентификаторы могут отсутствовать, что приведет к появлению «битых» ссылок с представлением «Объект не найден».

Способ 1. Быстрая сериализация через XMLСтрока и XMLЗначение

Если конфигурации базы-источника и базы-приемника полностью идентичны по структуре, а переносимые настройки содержат только общие предопределенные элементы или перенос выполняется между узлами РИБ / резервной копией, проще всего использовать прямую строковую сериализацию хранилища.

Объект ХранилищеЗначения поддерживает штатную сериализацию в XML. Рассмотрим код выгрузки и загрузки:


// В базе-источнике формируем XML-строку из реквизита
СтрокаСериализации = XMLСтрока(ДокументИсточник.ОтборПересчета);

// Передаем строку через COM-соединение в базу-приемник и восстанавливаем хранилище:
ХранилищеПриемник = XMLЗначение(Тип("ХранилищеЗначения"), СтрокаСериализации);

// Получаем объект настроек для дальнейшей работы или сразу записываем в документ
ДокументПриемник.ОтборПересчета = ХранилищеПриемник;

Функция XMLСтрока() преобразует хранилище в строку формата Base64, содержащую бинарный дамп объекта. В базе-приемнике функция XMLЗначение() воссоздает полноценный объект ХранилищеЗначения.

Способ 2. Сериализация настроек через СериализаторXDTO

Более гибкий и прозрачный подход — извлечь из хранилища именно прикладной объект (НастройкиКомпоновкиДанных) и сериализовать его через встроенный объект СериализаторXDTO. Это исключает передачу лишних заголовков самого хранилища и дает возможность работать с XML-текстом напрямую.

Разберем реализацию выгрузки и загрузки по шагам:


// Шаг 1. В базе-источнике извлекаем настройки из хранилища
НастройкиСКД = ДокументИсточник.ОтборПересчета.Получить();

Если НастройкиСКД <> Неопределено Тогда
    ЗаписьXML = Новый ЗаписьXML;
    ЗаписьXML.УстановитьСтроку();
    
    // Сериализуем объект настроек компоновки в XML
    СериализаторXDTO.ЗаписатьXML(ЗаписьXML, НастройкиСКД);
    XMLТекстНастроек = ЗаписьXML.Закрыть();
КонецЕсли;

// Шаг 2. Передаем XMLТекстНастроек по COM в базу-приемник и восстанавливаем объект
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(XMLТекстНастроек);

НастройкиПриемник = СериализаторXDTO.ПрочитатьXML(ЧтениеXML, Тип("НастройкиКомпоновкиДанных"));
ЧтениеXML.Закрыть();

// Шаг 3. Упаковываем восстановленные настройки в ХранилищеЗначения документа
ДокументПриемник.ОтборПересчета = Новый ХранилищеЗначения(НастройкиПриемник, Новый СжатиеДанных(9));

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

Как обработать ссылки, если базы не совпадают

Посмотрим на частую ситуацию: базы работают автономно, и элементы справочников (например, Номенклатура, Склады, СегментыНоменклатуры) имеют разные уникальные идентификаторы (UUID). Если перенести фильтр напрямую, правые значения отборов окажутся невалидными.

В этом случае после восстановления объекта НастройкиКомпоновкиДанных в базе-приемнике требуется выполнить программный обход дерева отборов:

  1. Рекурсивный обход элементов: Коллекция НастройкиПриемник.Отбор.Элементы содержит как конкретные отборы (ЭлементОтбораКомпоновкиДанных), так и вложенные группы (ГруппаЭлементовОтбораКомпоновкиДанных). При анализе необходимо обойти все дочерние группы.
  2. Сопоставление значений: Свойство ПравоеЗначение содержит значение фильтра. Если это ссылка, выполняем поиск дубля в базе-приемнике по ключевым полям (код, артикул, наименование).
  3. Обработка списков: Если вид сравнения отбора предполагает работу со списком (например, ВидСравненияКомпоновкиДанных.ВСписке), правым значением выступает СписокЗначений. Необходимо обойти каждый его элемент и переназначить поле Значение на найденную ссылку базы-приемника.
  4. Проверка метаданных: Поле ЛевоеЗначение имеет тип ПолеКомпоновкиДанных. Если перенос идет между разными релизами конфигураций и поле отбора отсутствует в схеме базы-приемника, такой элемент отбора следует отключить (Элемент.Использование = Ложь), чтобы избежать аварийного завершения документа при расчетах.

После сопоставления скорректированный объект настроек помещается в конструктор Новый ХранилищеЗначения() с максимальной степенью сжатия для экономии места в информационной базе.

← На главную