При интеграции двух информационных баз 1С с использованием технологии COM-соединения программисты часто сталкиваются с фундаментальным ограничением: в удаленной базе недоступны многие глобальные функции встроенного языка, такие как ТипЗнч(), Тип() или Вопрос(). Это происходит потому, что объект COM-соединения предоставляет доступ только к методам глобального контекста, которые помечены как доступные для внешнего соединения, и к экспортируемым методам модулей, но не является полноценным интерпретатором всех функций «на лету».
Разберем ситуацию: у нас есть переменная, полученная из внешней базы, имеющая тип COMОбъект. Нам нужно понять, является ли эта ссылка, например, «Справочником Номенклатура» или «Документом Реализация товаров и услуг». Рассмотрим по шагам наиболее эффективные и надежные способы решения этой задачи, проанализируем их плюсы и минусы.
Проанализируем самый прямой способ, который предлагает сама платформа. Объекты метаданных в 1С доступны через COM-соединение. Если у нас есть ссылка на объект во внешней базе (СсылкаВКOM), мы можем обратиться к её свойству Метаданные(). Это позволит нам сравнить её с объектами метаданных самой внешней базы.
Рассмотрим пример кода для проверки принадлежности к конкретному справочнику:
// Предположим, Соединение — это установленное COM-соединение
// СсылкаВКOM — объект, тип которого нужно проверить
МетаданныеОбъекта = СсылкаВКOM.Метаданные();
Если Соединение.Метаданные.Справочники.Номенклатура = МетаданныеОбъекта Тогда
// Это справочник Номенклатура
КонецЕсли;
Важный нюанс: Обращение к метаданным через COM — это достаточно «дорогая» и медленная операция. Если вам нужно обрабатывать тысячи ссылок в цикле, постоянное обращение к СсылкаВКOM.Метаданные() существенно замедлит работу обработки. В таких случаях лучше использовать получение полного имени метаданных.
Вместо сравнения объектов метаданных (которые являются сложными ссылочными типами COM), мы можем использовать строковое представление. Строки передаются между базами без искажений и сравниваются гораздо быстрее. Для сопоставления фактических данных и выявления расхождений после интеграции применяется автоматическая сверка проводок в базах 1С через COM-соединение. Выясним, как это реализовать:
ПолноеИмя = СсылкаВКOM.Метаданные().FullName(); // Вернет, например, "Catalog.Номенклатура"
Если ПолноеИмя = "Catalog.Номенклатура" Тогда
// Действие
КонецЕсли;
Обратите внимание, что метод FullName() возвращает имя на английском языке (или системном), что делает код более универсальным и независимым от языка интерфейса пользователя.
Если нам необходимо получить именно значение типа Тип удаленной базы для дальнейшего использования в методах вроде СодержитТип(), мы можем пойти на хитрость. Создадим объект ОписаниеТипов во внешней базе и извлечем из него нужный нам тип. Посмотрим на этот пример:
// Получаем тип "СправочникСсылка.Контрагенты" внешней базы
МассивТипов = Соединение.NewObject("Массив");
МассивТипов.Добавить("СправочникСсылка.Контрагенты");
ОписаниеТиповКонтрагента = Соединение.NewObject("ОписаниеТипов", МассивТипов);
ТипКонтрагентВнешний = ОписаниеТиповКонтрагента.Типы().Получить(0);
// Теперь мы можем использовать метод СодержитТип для проверки
Если ОписаниеТиповКонтрагента.СодержитТип(Соединение.ТипЗнч(СсылкаВКOM)) Тогда
// ОШИБКА: ТипЗнч не сработает!
КонецЕсли;
Внимание: Даже имея объект типа, мы не сможем вызвать ТипЗнч() напрямую у соединения. Поэтому метод с ОписаниеТипов чаще всего используется для инициализации реквизитов или сравнения типов, полученных через XMLТипЗнч.
Проанализируем один из самых быстрых и «продвинутых» способов — использование функций XML-сериализации. В 1С есть функции, которые работают с типами на уровне XDTO. Метод XMLТипЗнч() доступен через COM-соединение и возвращает описание типа в формате XML.
Попытка
ДанныеТипаXML = Соединение.XMLТипЗнч(СсылкаВКOM);
ИмяТипа = ДанныеТипаXML.TypeName; // Например, "CatalogRef.Номенклатура"
// Для сравнения с локальным типом:
Если ИмяТипа = "CatalogRef.Контрагенты" Тогда
// Это ссылка на контрагента
КонецЕсли;
Исключение
// Обработка объектов, не поддерживающих XML-сериализацию
КонецПопытки;
Этот метод хорош тем, что он не требует обращения к «тяжелому» дереву метаданных объекта при каждом вызове, а работает с описанием типа напрямую через сериализатор. При организации постоянного взаимодействия баз на основе таких правил обмена настраивается автоматический регулярный обмен данными между базами 1С.
Если нам крайне необходимо выполнить встроенную функцию ТипЗнч() или Тип() именно на стороне внешней базы, мы можем воспользоваться методом Вычислить() (или Eval) самого объекта соединения. Этот метод выполняет произвольный код во внешней базе и возвращает результат.
// Передаем ссылку обратно во внешнюю базу через параметр (если возможно)
// Либо формируем строку кода:
НужныйТип = Соединение.Вычислить("Тип(""СправочникСсылка.Валюты"")");
// Теперь проверим тип нашей ссылки
Если Соединение.XMLТипЗнч(СсылкаВКOM).TypeName = Соединение.XMLТип(НужныйТип).TypeName Тогда
// Типы совпадают
КонецЕсли;
Часто возникает затык при проверке: а не является ли значение из COM-базы Неопределено? Прямое сравнение Если Ссылка = Неопределено может не сработать, так как Неопределено в вашей базе и Неопределено в COM-базе — это разные объекты для системы маршалинга.
Рекомендуется использовать такой прием:
String() или XMLString().
// При установке соединения
ПустоеЗначениеCOM = Соединение.Undefined;
// При проверке
Если СсылкаВКOM = ПустоеЗначениеCOM Тогда
// Это Неопределено
КонецЕсли;
// Либо через строку
Если Соединение.String(СсылкаВКOM) = "" Тогда
// Скорее всего, это пустое значение или Неопределено
КонецЕсли;
Для качественной работы с типами через COM-соединение мы рекомендуем использовать сочетание XML-сериализации (XMLТипЗнч) и кэширования имен метаданных. Это обеспечит максимальную производительность. Если же задача разовая (например, в интерактивной обработке), использование Ссылка.Метаданные().FullName() будет самым простым и читаемым вариантом для программиста.
Помните, что каждый вызов через точку в COM-объекте (например, Объект.Метаданные.СтандартныеРеквизиты.Ссылка.Тип) — это отдельный сетевой или межпроцессный запрос, который кратно увеличивает время выполнения вашего кода. Старайтесь получать нужные данные за один вызов или кэшируйте их на стороне основной базы.