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

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

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

Способ 1: Проверка через дерево метаданных

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


// Предположим, COMСоединение уже установлено
// COMДокумент — это ссылка на объект в удаленной базе

Если COMДокумент.Метаданные().Реквизиты.Найти("Валюта") <> Неопределено Тогда
    Сообщить("Реквизит 'Валюта' существует");
Иначе
    Сообщить("Реквизит 'Валюта' отсутствует");
КонецЕсли;

Разберем этот пример. Мы вызываем метод Метаданные() у полученного через COM-соединение объекта. Это возвращает объект описания метаданных из удаленной базы. Далее мы обращаемся к коллекции Реквизиты и используем стандартный метод Найти().

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

Способ 2: Использование вспомогательной структуры (Оптимальный метод)

Рассмотрим более изящный и быстрый способ, который основан на использовании метода ЗаполнитьЗначенияСвойств. Этот метод универсален и работает даже с COM-объектами. Основная идея заключается в создании локальной структуры с ключом, имя которого совпадает с искомым реквизитом, и уникальным начальным значением.

Проанализируем готовую функцию, которую можно использовать в своих разработках:


&НаСервере
Функция ЕстьРеквизитCOMОбъекта(COMОбъект, ИмяРеквизита) Экспорт
    // Создаем уникальный маркер, которого точно не может быть в значении реквизита
    Ключ = Новый УникальныйИдентификатор;
    
    // Создаем структуру с искомым именем и нашим маркером
    Структура = Новый Структура(ИмяРеквизита, Ключ);
    
    // Пытаемся заполнить структуру из COM-объекта
    ЗаполнитьЗначенияСвойств(Структура, COMОбъект);
    
    // Если значение в структуре изменилось, значит реквизит существует и был прочитан
    Возврат Структура[ИмяРеквизита] <> Ключ;
КонецФункции

Выясним причину, почему этот метод считается предпочтительным. Во-первых, он работает быстрее, чем полный разбор метаданных. Во-вторых, он одинаково успешно находит как обычные, так и стандартные реквизиты. Нам не нужно знать, к какой коллекции относится поле — ЗаполнитьЗначенияСвойств просто ищет совпадение по имени свойства объекта.

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


// Где COMСоединение — объект связи с базой
COMКлюч = COMСоединение.NewObject("УникальныйИдентификатор");
COMСтруктура = COMСоединение.NewObject("Структура");
COMСтруктура.Вставить(ИмяРеквизита, COMКлюч);
COMСоединение.ЗаполнитьЗначенияСвойств(COMСтруктура, COMОбъект);

Однако в большинстве современных сценариев на платформе 8.3 достаточно локальной структуры, как показано в первом примере этого раздела.

Способ 3: Обработка через исключения (Try-Catch)

Если нам нужно не просто проверить наличие, а сразу получить значение реквизита, если он есть, можно применить блок Попытка...Исключение. Рассмотрим этот вариант:


ЗначениеРеквизита = Неопределено;
РеквизитСуществует = Истина;

Попытка
    ЗначениеРеквизита = COMОбъект.Валюта;
Исключение
    РеквизитСуществует = Ложь;
КонецПопытки;

Этот метод является самым быстрым при условии, что реквизит существует в 99% случаев. Если же реквизит отсутствует часто, то генерация исключения в 1С — процедура довольно медленная, и лучше вернуться к способу со структурой.

Сравнение методов и рекомендации

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

  1. Проверка метаданных — используем только тогда, когда нам нужно получить дополнительные свойства реквизита (тип, синоним, подсказку), а не просто факт его наличия.
  2. Метод со структурой — универсальный «золотой стандарт». Рекомендуется для массовых проверок в циклах. Позволяет избежать лишних обращений к дереву объектов метаданных удаленной базы.
  3. Попытка-Исключение — используем при разовых обращениях, когда код должен быть максимально коротким и понятным, а вероятность отсутствия реквизита минимальна.

Также важно помнить о различиях между V83.COMConnector и V83.Application. При использовании COMConnector взаимодействие происходит значительно быстрее, так как не инициализируется графическая оболочка удаленной базы. Все вышеперечисленные методы будут работать в обоих случаях, но для серверного кода всегда выбирайте COMConnector.

В завершение подчеркнем: при работе через COM всегда старайтесь минимизировать количество вызовов методов объекта. Если вам нужно проверить десять реквизитов, лучше создать одну структуру с десятью ключами и вызвать ЗаполнитьЗначенияСвойств один раз, чем делать это в десять подходов.

← На главную