Как в COM-соединении сравнить реквизит типа перечисление

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

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

Почему прямое сравнение не работает?

Прежде всего, проанализируем техническую сторону вопроса. Когда мы получаем объект из другой базы через COM-соединение, мы работаем не с самим объектом, а с его COM-прокси. Локальная база ничего не знает о внутренних идентификаторах (UUID) объектов удаленной базы.

Рассмотрим ошибочный пример кода:


// Это не будет работать!
Если Стр.ВидОперации = БазаИсточник.Перечисления.ВидыОпераций.Оплата Тогда
    // Код никогда не выполнится
КонецЕсли;

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

Способ 1: Использование метода XMLString

Это один из самых эффективных и быстрых способов. Метод XMLString (или XMLСтрока в русской нотации) преобразует значение перечисления в его строковое имя, заданное в конфигураторе. Строки сравнивать гораздо проще и надежнее.

Важно: метод нужно вызывать именно у объекта COM-соединения, а не у глобального контекста локальной базы. Посмотрим на правильный пример:


// Получаем строковое имя значения перечисления из COM-базы
ИмяЗначения = БазаИсточник.XMLString(Стр.ВидОперации);

// Сравниваем со строкой (имя как в Конфигураторе)
Если ИмяЗначения = "ВознаграждениеПлатежногоАгента" Тогда
    // Логика обработки
КонецЕсли;

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

Способ 2: Сравнение по порядковому номеру (индексу)

Если структуры перечислений в обеих базах полностью идентичны (например, это две базы одной и той же конфигурации), можно использовать индекс значения. Индекс — это порядковый номер значения в списке перечисления (начиная с 0).

Разберем этот метод по шагам:

  1. Получаем индекс значения из COM-базы.
  2. Сравниваем его с индексом аналогичного значения в локальной базе.

ИндексCOM = БазаИсточник.Перечисления.ВидыОперацийПоЗарплате.Индекс(Стр.ВидОперации);
ИндексЛокальный = Перечисления.ВидыОперацийПоЗарплате.Индекс(Перечисления.ВидыОперацийПоЗарплате.ВознаграждениеПлатежногоАгента);

Если ИндексCOM = ИндексЛокальный Тогда
    // Значения совпадают
КонецЕсли;

Преимущество: очень высокая скорость работы. Недостаток: если в одной из баз порядок значений в перечислении был изменен в Конфигураторе, метод вернет неверный результат.

Способ 3: Получение имени через метаданные

Если метод XMLString по каким-то причинам недоступен или выдает ошибку, мы можем обратиться к метаданным удаленной базы напрямую. Это более «тяжеловесный» способ, но он дает полный контроль над данными.

Проанализируем пример получения имени:


// 1. Находим индекс значения в COM-базе
ТекИндекс = БазаИсточник.Перечисления.СтавкиНДС.Индекс(Стр.СтавкаНДС);

// 2. Получаем имя через обращение к метаданным по этому индексу
ИмяЗначения = БазаИсточник.Metadata.Enums.СтавкиНДС.EnumValues.Get(ТекИндекс).Name;

Если ИмяЗначения = "НДС10" Тогда
    // Обработка
КонецЕсли;

Здесь мы используем англоязычные термины (Metadata, Enums, EnumValues), так как при работе через COM-соединение обращение к свойствам метаданных часто требует латиницы, что повышает стабильность кода.

Способ 4: Механизм «СравнениеОбъектов»

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


Компаратор = БазаИсточник.NewObject("ComparisonOfObjects");
// Дальнейшая логика добавления объектов и их сравнения

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

Рекомендации по архитектуре

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

Создайте в базе-источнике общий модуль с экспортной функцией:


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

Тогда в вашей основной базе вы вызовете эту функцию один раз и получите структуру с примитивными типами (строками и числами), которые сравниваются мгновенно и без ошибок прокси-объектов. Работа с примитивными типами — это «золотой стандарт» при интеграции через COM.

Резюме

Подведем итог: если вам нужно быстро сравнить перечисление в COM-соединении, используйте БазаИсточник.XMLString(Значение). Если вы хотите максимальной надежности и производительности — передавайте данные из удаленной базы в виде простых строк или структур через специально написанные экспортные функции.

← На главную