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

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

При интеграции различных информационных баз на платформе «1С:Предприятие 8.3» через COM-соединение программисты часто сталкиваются с проблемой: стандартные методы сравнения объектов, которые работают внутри одной базы, перестают функционировать при обращении к внешней базе. Одной из самых частых задач является определение значения реквизита с типом ПеречислениеСсылка. Попытка прямого сравнения вроде Док.НалогообложениеНДС = trade.Перечисления.ТипыНалогообложенияНДС.ПродажаОблагаетсяНДС часто возвращает «Ложь», даже если значения визуально совпадают. Это происходит из-за особенностей передачи ссылочных типов через COM-интерфейс.

В данной статье мы подробно разберем, почему возникают сложности при работе с перечислениями через COM, и рассмотрим несколько надежных способов решения этой задачи, включая использование XML-сериализации, индексов и метаданных.

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

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

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

Способ №1: Использование метода XMLString (Золотой стандарт)

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

Проанализируем пример кода для этого метода:


// Предположим, trade — это установленное COM-соединение
Док = trade.Документы.ПриобретениеТоваровУслуг.НайтиПоНомеру("111");

// Получаем строковое имя перечисления через метод XMLString внешней базы
ИмяЗначения = trade.XMLString(Док.НалогообложениеНДС);

Если ИмяЗначения = "ПродажаОблагаетсяНДС" Тогда
    // Выполняем действие для облагаемых операций
    Сообщить("Документ облагается НДС");
ИначеЕсли ИмяЗначения = "ПродажаНеОблагаетсяНДС" Тогда
    // Действие для операций без НДС
    Сообщить("Продажа не облагается НДС");
КонецЕсли;

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

Способ №2: Сравнение через Индекс

Посмотрим на альтернативный вариант — использование индекса значения перечисления. В 1С порядок значений перечисления в конфигураторе строго определен. Метод Индекс() позволяет получить порядковый номер значения (начиная с 0).

Посмотрим на пример реализации:


// Получаем индекс текущего значения реквизита документа
ИндексЗначения = trade.Перечисления.ТипыНалогообложенияНДС.Индекс(Док.НалогообложениеНДС);

// Сравниваем с индексом нужного нам значения
Если ИндексЗначения = trade.Перечисления.ТипыНалогообложенияНДС.Индекс(trade.Перечисления.ТипыНалогообложенияНДС.ПродажаОблагаетсяНДС) Тогда
    // Логика обработки
КонецЕсли;

Этот способ надежен, так как оперирует числами, которые передаются через COM без искажений. Однако он менее нагляден при чтении кода, чем строковые идентификаторы.

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

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

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

  1. Сначала получаем индекс значения перечисления.
  2. Обращаемся к метаданным этого перечисления во внешней базе.
  3. Извлекаем свойство Name у конкретного значения по полученному индексу.

Индекс = trade.Перечисления.ТипыНалогообложенияНДС.Индекс(Док.НалогообложениеНДС);
ИмяЗначения = trade.Metadata.Enums.ТипыНалогообложенияНДС.EnumValues.Get(Индекс).Name;

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

Способ №4: Корректное получение Синонима (Представления)

Иногда задача состоит не в программном сравнении, а в выводе значения для пользователя (например, в лог-файл или отчет). Как мы уже выяснили, обычная функция Строка() не сработает. Чтобы получить синоним (представление), нужно вызвать метод String() самого COM-объекта.

Проанализируем ситуацию:


// Правильный способ получения представления значения из внешней базы
Представление = trade.String(Док.НалогообложениеНДС);
Сообщить("Текущее налогообложение: " + Представление); 
// Выведет, например: "Закупка облагается НДС"

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

Обработка пустых значений

Частая ошибка при работе через COM — неправильная проверка на пустое значение перечисления. Сравнение с Неопределено или Null может не сработать. Правильнее всего сравнивать с «Пустой ссылкой» конкретного типа перечисления внешней базы.


Если Док.НалогообложениеНДС = trade.Перечисления.ТипыНалогообложенияНДС.ПустаяСсылка() Тогда
    Сообщить("Значение перечисления не заполнено!");
КонецЕсли;

Оптимизация производительности (Кеширование)

При работе с COM-соединением важно помнить, что каждое обращение «через точку» (например, trade.Перечисления.Имя.Значение) — это отдельный вызов удаленной процедуры (RPC). Если вы обрабатываете тысячи документов в цикле, такие вызовы могут катастрофически замедлить работу программы.

Рекомендуем оптимизировать код следующим образом:

  1. До начала цикла получите нужные вам эталонные значения перечислений и сохраните их в локальные переменные.
  2. Внутри цикла сравнивайте реквизиты документов с этими переменными.

Пример оптимизированного кода:


// Кэшируем значения перед циклом
ндсОблагается = trade.Перечисления.ТипыНалогообложенияНДС.ПродажаОблагаетсяНДС;
ндсНеОблагается = trade.Перечисления.ТипыНалогообложенияНДС.ПродажаНеОблагаетсяНДС;

Выборка = trade.Документы.ПриобретениеТоваровУслуг.Выбрать(ДатаНач, ДатаКон);

Пока Выборка.Следующий() Цикл
    // Сравнение ссылок внутри одного COM-сеанса обычно работает корректно
    Если Выборка.НалогообложениеНДС = ндсОблагается Тогда
        // Быстрая обработка
    КонецЕсли;
КонецЦикла;

Выбор между V83.Application и V83.COMConnector

В завершение разберем технический момент выбора интерфейса подключения. В примерах выше часто используется V83.Application. Этот объект запускает полноценную копию 1С, что требует значительных ресурсов сервера или клиентской машины.

Если ваша задача — только чтение и запись данных без взаимодействия с экранными формами внешней базы, настоятельно рекомендуем использовать V83.COMConnector. Он работает гораздо быстрее, потребляет меньше памяти и лучше подходит для серверных сценариев. Методика работы с перечислениями, описанная выше (XMLString, Индекс, String), полностью идентична для обоих типов подключения.

Таким образом, мы выяснили, что наиболее универсальным и производительным способом определения значения перечисления через COM является метод XMLString, а для вывода текстовых сообщений — метод trade.String(). Придерживаясь этих правил, вы обеспечите стабильную и быструю работу ваших интеграционных механизмов.

← На главную