При интеграции различных информационных баз 1С через COM-соединение разработчики часто сталкиваются с проблемой: прямое сравнение значений перечислений не работает. Даже если перечисления в обеих базах называются одинаково и имеют идентичный набор значений, обычное условие Если выдает «Ложь». В этой статье мы разберем, почему так происходит, и рассмотрим надежные способы решения этой задачи.
Прежде всего, проанализируем техническую сторону вопроса. Когда мы получаем объект из другой базы через COM-соединение, мы работаем не с самим объектом, а с его COM-прокси. Локальная база ничего не знает о внутренних идентификаторах (UUID) объектов удаленной базы.
Рассмотрим ошибочный пример кода:
// Это не будет работать!
Если Стр.ВидОперации = БазаИсточник.Перечисления.ВидыОпераций.Оплата Тогда
// Код никогда не выполнится
КонецЕсли;
В данном случае БазаИсточник.Перечисления.ВидыОпераций.Оплата возвращает ссылку внутри контекста COM-соединения, а Стр.ВидОперации (если это реквизит из той же COM-базы) также является ссылкой. Однако 1С не умеет корректно сравнивать две ссылки из внешнего источника напрямую через оператор равенства в контексте локального сеанса. А если вы попытаетесь сравнить ссылку из COM-базы с локальной ссылкой вашей текущей базы, результат всегда будет отрицательным, так как они принадлежат разным менеджерам памяти.
Это один из самых эффективных и быстрых способов. Метод XMLString (или XMLСтрока в русской нотации) преобразует значение перечисления в его строковое имя, заданное в конфигураторе. Строки сравнивать гораздо проще и надежнее.
Важно: метод нужно вызывать именно у объекта COM-соединения, а не у глобального контекста локальной базы. Посмотрим на правильный пример:
// Получаем строковое имя значения перечисления из COM-базы
ИмяЗначения = БазаИсточник.XMLString(Стр.ВидОперации);
// Сравниваем со строкой (имя как в Конфигураторе)
Если ИмяЗначения = "ВознаграждениеПлатежногоАгента" Тогда
// Логика обработки
КонецЕсли;
Этот метод хорош тем, что он не зависит от синонимов и языка интерфейса пользователя, так как возвращает именно внутреннее имя объекта метаданных.
Если структуры перечислений в обеих базах полностью идентичны (например, это две базы одной и той же конфигурации), можно использовать индекс значения. Индекс — это порядковый номер значения в списке перечисления (начиная с 0).
Разберем этот метод по шагам:
ИндексCOM = БазаИсточник.Перечисления.ВидыОперацийПоЗарплате.Индекс(Стр.ВидОперации);
ИндексЛокальный = Перечисления.ВидыОперацийПоЗарплате.Индекс(Перечисления.ВидыОперацийПоЗарплате.ВознаграждениеПлатежногоАгента);
Если ИндексCOM = ИндексЛокальный Тогда
// Значения совпадают
КонецЕсли;
Преимущество: очень высокая скорость работы. Недостаток: если в одной из баз порядок значений в перечислении был изменен в Конфигураторе, метод вернет неверный результат.
Если метод XMLString по каким-то причинам недоступен или выдает ошибку, мы можем обратиться к метаданным удаленной базы напрямую. Это более «тяжеловесный» способ, но он дает полный контроль над данными.
Проанализируем пример получения имени:
// 1. Находим индекс значения в COM-базе
ТекИндекс = БазаИсточник.Перечисления.СтавкиНДС.Индекс(Стр.СтавкаНДС);
// 2. Получаем имя через обращение к метаданным по этому индексу
ИмяЗначения = БазаИсточник.Metadata.Enums.СтавкиНДС.EnumValues.Get(ТекИндекс).Name;
Если ИмяЗначения = "НДС10" Тогда
// Обработка
КонецЕсли;
Здесь мы используем англоязычные термины (Metadata, Enums, EnumValues), так как при работе через COM-соединение обращение к свойствам метаданных часто требует латиницы, что повышает стабильность кода.
В платформе 1С существует встроенный объект СравнениеОбъектов. Его редко используют для простых перечислений, но он незаменим при сравнении сложных структур. Суть заключается в том, что объект создается внутри COM-базы и там же производится сопоставление.
Компаратор = БазаИсточник.NewObject("ComparisonOfObjects");
// Дальнейшая логика добавления объектов и их сравнения
Однако для перечислений этот метод избыточен, и мы рекомендуем придерживаться варианта с XMLString.
Выясним, как сделать работу с COM еще стабильнее. Вместо того чтобы постоянно запрашивать метаданные или индексы через «медленное» COM-соединение, лучше всего вынести логику на сторону удаленной базы.
Создайте в базе-источнике общий модуль с экспортной функцией:
Функция ПолучитьДанныеСтроки(ОбъектСсылка) Экспорт
Результат = Новый Структура;
Результат.Вставить("ВидОперацииИмя", XMLСтрока(ОбъектСсылка.ВидОперации));
// Другие реквизиты
Возврат Результат;
КонецФункции
Тогда в вашей основной базе вы вызовете эту функцию один раз и получите структуру с примитивными типами (строками и числами), которые сравниваются мгновенно и без ошибок прокси-объектов. Работа с примитивными типами — это «золотой стандарт» при интеграции через COM.
Подведем итог: если вам нужно быстро сравнить перечисление в COM-соединении, используйте БазаИсточник.XMLString(Значение). Если вы хотите максимальной надежности и производительности — передавайте данные из удаленной базы в виде простых строк или структур через специально написанные экспортные функции.