Как вывести на форму отбор компоновщика настроек, полученный через COM-соединение?

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

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

Рассмотрим ситуацию: мы успешно установили соединение, создали объект КомпоновщикНастроекКомпоновкиДанных в контексте COM, инициализировали его схемой, но при попытке назначить этот объект реквизиту формы получаем ошибку или пустую коллекцию. Проанализируем, почему это происходит и как решить задачу правильно.

Почему прямая передача COM-объекта на форму не работает?

Разберем основные причины технического ограничения, с которыми столкнулись участники обсуждения. Во-первых, для платформы 1С:Предприятие типы данных внутри текущей сессии и типы данных, полученные через COMОбъект, — это абсолютно разные сущности. Даже если в обеих базах используется одна и та же конфигурация, объект КомпоновщикНастроек из внешней базы для текущей базы является «вещью в себе».

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

Решение проблемы через XML-сериализацию

Единственным надежным способом передачи сложных структур данных, таких как настройки компоновки, является их преобразование в промежуточный формат, понятный обеим сторонам. Идеально для этого подходит XML-сериализация. Нам необходимо превратить настройки компоновщика в COM-базе в строку XML, передать эту строку в нашу базу и восстановить из нее локальный объект.

Шаг 1: Подготовка настроек на стороне COM-соединения

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


// В контексте текущей базы, где БазаЕРП - это установленное COM-соединение
НастройкиДляПередачи = БазаЕРП.КомпоновщикНастроек.Настройки;
СтрокаXML = БазаЕРП.XMLString(НастройкиДляПередачи);
// Или более универсальный способ через СериализаторXDTO
ЗаписьXML = БазаЕРП.NewObject("ЗаписьXML");
ЗаписьXML.SetString();
БазаЕРП.XDTOSerializer.WriteXML(ЗаписьXML, НастройкиДляПередачи);
СтрокаXML = ЗаписьXML.Close();

В этом фрагменте мы получаем объект настроек из COM и превращаем его в обычную текстовую строку. Строка без проблем передается с сервера на клиент и обратно.

Шаг 2: Инициализация локального компоновщика

Просто загрузить XML в пустой компоновщик недостаточно. Чтобы на форме отобразились доступные поля, виды сравнения и заголовки, компоновщик в вашей текущей базе обязательно должен быть инициализирован ИсточникомДоступныхНастроек. Это критически важный момент: если у вас в текущей базе нет схемы (СКД), аналогичной той, что в удаленной базе, редактор отбора будет пустым.

Рассмотрим, как подготовить локальный компоновщик:


// Создаем локальный компоновщик (реквизит формы с типом КомпоновщикНастроекКомпоновкиДанных)
// Допустим, у нас есть макет "ОсновнаяСхемаКомпоновкиДанных" в текущей обработке
СхемаСКД = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
ИсточникДоступныхНастроек = Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаСКД);
ЭтотОбъект.КомпоновщикНастроек.Инициализировать(ИсточникДоступныхНастроек);

Шаг 3: Десериализация и загрузка настроек

Теперь, когда у нас есть текстовая строка XML из внешней базы и инициализированный локальный компоновщик, выполним «сборку» данных. Выясним, как правильно прочитать XML и применить настройки:


ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(СтрокаXML);
// Важно использовать локальный СериализаторXDTO
НовыеНастройки = СериализаторXDTO.ПрочитатьXML(ЧтениеXML, Тип("НастройкиКомпоновкиДанных"));
ЭтотОбъект.КомпоновщикНастроек.ЗагрузитьНастройки(НовыеНастройки);

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

Проблема сопоставления типов данных

Проанализируем ситуацию, которая часто возникает при передаче отборов: наличие ссылочных типов. Если в базе ERP в отборе выбрана конкретная валюта USD, то в XML будет записана ссылка (обычно это GUID и тип). При десериализации в текущей базе система попытается найти объект с таким же уникальным идентификатором.

Важные нюансы сопоставления:

  1. Идентичность метаданных: Если структуры баз различаются, тип СправочникСсылка.Валюты может называться иначе или иметь другой внутренний идентификатор. В этом случае значение отбора превратится в «Объект не найден».
  2. Синхронизация данных: Даже если типы совпадают, объект с конкретным GUID может отсутствовать в текущей базе.

Для решения этой проблемы можно использовать один из двух подходов. Первый — предварительная синхронизация справочников. Второй — программный обход коллекции КомпоновщикНастроек.Настройки.Отбор.Элементы после загрузки и замена «битых» ссылок на актуальные локальные значения или представления.

Ручной обход элементов отбора (альтернативный метод)

Если по каким-то причинам XML-сериализация целиком вам не подходит, можно рассмотреть вариант ручного копирования элементов. Посмотрим на пример того, как можно обойти коллекцию COM-объектов:


// ЭлементыОтбораCOM - это коллекция из БазаЕРП
Для Каждого ЭлементCOM Из ЭлементыОтбораCOM Цикл
    ЛокальныйЭлемент = ЭтотОбъект.КомпоновщикНастроек.Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    ЛокальныйЭлемент.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(ЭлементCOM.ЛевоеЗначение);
    ЛокальныйЭлемент.ВидСравнения = ВидСравненияКомпоновкиДанных[БазаЕРП.String(ЭлементCOM.ВидСравнения)];
    // Здесь потребуется логика приведения типов для ПравогоЗначения
    ЛокальныйЭлемент.Использование = ЭлементCOM.Использование;
КонецЦикла;

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

Подведем итоги

Мы выяснили, что напрямую вывести Отбор из COM-соединения на форму невозможно из-за ограничений платформы на передачу контекстных объектов. Однако, используя XML-сериализацию настроек через XDTOSerializer и предварительную инициализацию локального КомпоновщикаНастроек правильной схемой компоновки, мы можем добиться полной визуальной идентичности и возможности редактирования внешних отборов.

Помните, что залог успеха в этом процессе — наличие идентичной (по именам полей) схемы компоновки данных в обеих базах и корректная обработка ссылочных типов данных при переносе настроек.

← На главную