Как проверить типы реквизитов при работе через OLE или COM-соединение в 1С

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

При интеграции двух информационных баз 1С с использованием COM/OLE-соединения часто возникает необходимость программно анализировать типы реквизитов объектов: как в метаданных конфигурации-источника, так и у фактически полученных данных. При этом разработчики сталкиваются с тем, что стандартные локальные конструкции вроде ТипЗнч() или метод СодержитТип() ведут себя неожиданно: возвращают тип COMОбъект или всегда дают результат Ложь. Разберем детально, почему это происходит и какими способами можно корректно определить типы реквизитов через внешнее соединение.

Причины специфического поведения типов при COM-подключении

Чтобы понять логику работы платформы, проанализируем ключевые особенности маршалинга данных и контекстов исполнения:

  1. Изоляция контекстов исполнения. Локальная информационная база и подключенная через COM база работают в разных адресных пространствах. Локальный объект типа Тип("Строка") не равен объекту типа Строка, созданному в удаленной базе. Из-за этого вызов метода ОписаниеТипов.СодержитТип(Тип("Строка")) вернет Ложь, так как проверяемый тип передан из локального контекста, а не из удаленного.
  2. Особенности передачи примитивных и ссылочных типов. Значения примитивных типов (число, строка, дата, булево) при передаче через COM автоматически преобразуются в стандартные типы OLE (структура VARIANT). Однако объекты метаданных, описания типов, ссылки и сами объекты Тип маршалируются как непрозрачные COMОбъект.
  3. Вызов глобальных функций локальной базы. Если применить локальную функцию ТипЗнч() к объекту метаданных или описанию типа из внешней базы, платформа вернет тип локальной обертки — COMОбъект.

Способ 1. Проверка типов реквизитов в метаданных через функции XML

Рассмотрим наиболее универсальный и надежный подход к определению типов реквизита в метаданных внешней базы — использование функции XMLТип, вызванной в контексте внешнего соединения. Этот метод позволяет получить каноническое строковое имя типа (как для примитивных, так и для ссылочных типов данных).

Разберем по шагам реализацию данного алгоритма:


// Получаем реквизит метаданных из внешней базы
РеквизитМетаданных = СоединениеCOM.Метаданные.Справочники.Номенклатура.Реквизиты.Артикул;
ОписаниеТиповCOM   = РеквизитМетаданных.Тип;

// Получаем массив типов, входящих в описание типов
МассивТиповCOM = ОписаниеТиповCOM.Типы();

Для Индекс = 0 По МассивТиповCOM.Количество() - 1 Цикл
    ТекТипCOM = МассивТиповCOM.Получить(Индекс);
    
    // Вызываем функцию XMLТип строго в контексте внешнего соединения
    ТипXML = СоединениеCOM.XMLТип(ТекТипCOM);
    
    ИмяТипа = ТипXML.ИмяТипа;              // Вернет "string", "decimal", "CatalogRef.Контрагенты" и т.д.
    URIТипа = ТипXML.URIПространстваИмен; // Пространство имен XSD или схемы 1С
КонецЦикла;

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

Способ 2. Проверка через метод СодержитТип с использованием удаленного контекста

Если требуется проверить наличие конкретного типа в описании типов реквизита (например, проверить, может ли реквизит принимать строковое значение), необходимо передавать в метод СодержитТип() объект типа, полученный именно из COM-соединения.

Посмотрим на пример кода:


РеквизитМетаданных = СоединениеCOM.Метаданные.Справочники.Контрагенты.Реквизиты.ИНН;
ОписаниеТиповCOM   = РеквизитМетаданных.Тип;

// Получаем объект типа из контекста COM-соединения
ТипСтрокаCOM = СоединениеCOM.Тип("Строка");

Если ОписаниеТиповCOM.СодержитТип(ТипСтрокаCOM) Тогда
    // Реквизит поддерживает тип "Строка"
КонецЕсли;

Также строковое представление типа из удаленной базы можно получить через метод преобразования строки внешнего соединения:


ИмяТипаСтрокой = СоединениеCOM.String(ТекТипCOM); // Вернет строковое представление, например "Строка" или "Число"

Способ 3. Определение типа непосредственно по значению данных

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

  1. Примитивные типы: так как примитивные типы автоматически преобразуются платформой при передаче через COM, к ним можно применять стандартные локальные функции:
    
    ЗначениеРеквизита = ОбъектCOM.Наименование;
    Если ТипЗнч(ЗначениеРеквизита) = Тип("Строка") Тогда
        // Обработка строкового значения
    КонецЕсли;
    
  2. Ссылочные типы: если реквизит содержит ссылку на справочник или документ, он передается в вызывающую базу как COMОбъект. Чтобы выяснить его конкретный тип, следует запросить метаданные самой ссылки через COM:
    
    ЗначениеСсылки = ОбъектCOM.ОсновнойДоговор;
    Если ЗначениеСсылки <> Неопределено И ЗначениеСсылки <> Null Тогда
        ПолноеИмяТипа = ЗначениеСсылки.Метаданные().ПолноеИмя(); // Вернет, например, "Справочник.ДоговорыКонтрагентов"
    КонецЕсли;
    
  3. Универсальный вызов XMLТипЗнч: для любого значения объекта в COM-базе можно вызвать функцию XMLТипЗнч:
    
    ТипXML = СоединениеCOM.XMLТипЗнч(ОбъектCOM.Реквизит);
    Если ТипXML <> Неопределено Тогда
        ИмяТипа = ТипXML.ИмяТипа;
    КонецЕсли;
    

Важное правило: все операции по анализу типов метаданных (Метаданные(), ОписаниеТипов, Тип(), XMLТип()) должны выполняться в контексте того COM-соединения, из которого эти объекты получены.

← На главную