Почему при сравнении значения справочника со строкой в 1С получается ЛОЖЬ и как это исправить

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

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

Причина проблемы: Ссылка vs Строка

Для начала проанализируем ситуацию, описанную в теме. Разработчик пытается выполнить сравнение: Объект.Партнер.ГруппаДоступа = "Брокеры". В этом выражении левая и правая части принадлежат к принципиально разным классам объектов:

  1. Справа находится примитивный тип данных — Строка. Это просто набор символов.
  2. Слева находится объектный тип — СправочникСсылка.ГруппыДоступаПартнеров.

В системе 1С ссылка — это не текст. Внутри базы данных ссылка представляет собой уникальный 128-битный идентификатор (GUID), например, 5b2e3f1a-6d4c-11eb-a2b3-00155d010101. Когда мы пишем условие сравнения, система сравнивает этот сложный идентификатор с текстовой строкой. Естественно, они никогда не будут равны, поэтому результатом всегда будет Ложь.

Ловушка отладчика: что мы видим на самом деле

Почему же в отладчике мы видим именно текст? Рассмотрим механизм работы платформы. Для удобства человека 1С всегда показывает Представление объекта. Если у справочника в свойствах указано, что основным представлением является «Наименование», то везде, где система должна вывести ссылку (в списках, отчетах или окне отладки), она будет показывать текст наименования.

Чтобы убедиться в разнице типов самостоятельно, мы можем воспользоваться функцией ТипЗнч(). Давайте проанализируем следующий пример кода:


// Проверим типы данных в отладчике или через сообщить
ТипСлева = ТипЗнч(Объект.Партнер.ГруппаДоступа); // Вернет Тип("СправочникСсылка.ГруппыДоступаПартнеров")
ТипСправа = ТипЗнч("Брокеры"); // Вернет Тип("Строка")

Если ТипСлева <> ТипСправа Тогда
    Сообщить("Сравнение невозможно: разные типы данных!");
КонецЕсли;

Важный совет: при работе в отладчике всегда обращайте внимание не только на колонку «Значение», но и на колонку «Тип». Это снимет 90% вопросов о том, почему сравнение работает не так, как ожидалось.

Способ 1: Сравнение по наименованию (простой, но опасный)

Самый очевидный способ исправить ошибку — обратиться к строковому реквизиту ссылки. Мы можем сравнить текст с текстом. Для этого используется обращение через точку к свойству Наименование.


Если Объект.Партнер.ГруппаДоступа.Наименование = "Брокеры" Тогда
    // Теперь условие выполнится, так как мы сравниваем Строку со Строкой
КонецЕсли;

Однако давайте разберем, почему опытные разработчики стараются избегать такого подхода:

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

Если группа «Брокеры» является ключевой для логики вашей программы, правильнее всего сделать её предопределенной в конфигураторе. В этом случае мы сможем обращаться к ней напрямую через метаданные, не привязываясь к текстовым строкам.

Рассмотрим, как будет выглядеть правильное сравнение двух ссылок:


ЭталоннаяГруппа = Справочники.ГруппыДоступаПартнеров.Брокеры;
Если Объект.Партнер.ГруппаДоступа = ЭталоннаяГруппа Тогда
    // Это самый надежный и быстрый способ
КонецЕсли;

В данном случае мы сравниваем Ссылка = Ссылка. Система сопоставляет GUID-ы, что происходит мгновенно и гарантирует 100% точность, даже если пользователь изменит название группы в режиме «Предприятие».

Способ 3: Поиск ссылки по наименованию

Бывают ситуации, когда мы не можем создать предопределенный элемент (например, справочник полностью заполняется пользователями). В этом случае, чтобы не обращаться к наименованию в каждой строке кода, мы можем один раз найти ссылку и использовать её для сравнения.


// Найдем ссылку один раз
СсылкаБрокеры = Справочники.ГруппыДоступаПартнеров.НайтиПоНаименованию("Брокеры");

// Проверим, что объект вообще найден
Если Не СсылкаБрокеры.Пустая() Тогда
    // Теперь сравниваем ссылки, а не строки
    Если Объект.Партнер.ГруппаДоступа = СсылкаБрокеры Тогда
        // Логика для брокеров
    КонецЕсли;
КонецЕсли;

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

Способ 4: Принудительное приведение к строке

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


Если Строка(Объект.Партнер.ГруппаДоступа) = "Брокеры" Тогда
    // Ссылка будет преобразована в текст, и сравнение сработает
КонецЕсли;

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

Подведем итоги

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

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

← На главную