Почему при сравнении двух одинаковых элементов справочника в 1С получается Ложь и как это исправить

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

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

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

В чем кроется причина: ссылка против представления

Первое и самое важное, что нам необходимо усвоить: платформа 1С никогда не сравнивает ссылочные типы (справочники, документы, бизнес-процессы) по их наименованию, коду или любому другому видимому реквизиту. Сравнение всегда происходит по Уникальному Идентификатору (GUID). Это скрытое 128-битное число, которое присваивается записи в момент ее создания в базе данных.

Рассмотрим ситуацию. В справочнике «ЕдиницыИзмерения» могут существовать две разные записи с наименованием «шт». В пользовательском интерфейсе и в отладчике они обе будут отображаться как «шт», так как по умолчанию 1С выводит в колонку «Значение» так называемое Представление ссылки. Но внутри базы данных это два разных объекта с разными идентификаторами. Именно поэтому выражение Ссылка1 = Ссылка2 вернет Ложь.

Проблема подчиненных справочников

Проанализируем типичную структуру метаданных. Справочник ЕдиницыИзмерения во многих типовых конфигурациях является подчиненным справочнику Номенклатура. Это означает, что для каждого товара (например, «Болт» и «Гайка») создается свой собственный набор единиц измерения. Даже если у обоих товаров единица измерения называется «шт», это будут две разные физические записи в таблице базы данных. Каждая из них «знает» своего владельца, и их ссылки никогда не будут равны друг другу.

Посмотрим на пример кода, который может привести к ошибке:


// Опасный способ получения ссылки
ЕдИзмТовара1 = Справочники.ЕдиницыИзмерения.НайтиПоНаименованию("шт");
ЕдИзмТовара2 = Справочники.ЕдиницыИзмерения.НайтиПоНаименованию("шт");

Если ЕдИзмТовара1 = ЕдИзмТовара2 Тогда
    // Этот блок может не выполниться, если в базе несколько "шт"
    Сообщить("Единицы одинаковы");
Иначе
    // Мы попадем сюда, если метод НайтиПоНаименованию вернул разные элементы
    Сообщить("Единицы разные, хотя называются одинаково");
КонецЕсли;

Методы диагностики в отладчике

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

  1. Проверка через Уникальный Идентификатор. Добавим в табло выражения для обеих переменных, используя метод УникальныйИдентификатор().
    Переменная1.УникальныйИдентификатор()
    Переменная2.УникальныйИдентификатор()
    Если значения (длинные строки с дефисами) различаются хотя бы в одном символе — перед нами разные объекты.
  2. Проверка Владельца. Если справочник подчиненный, обязательно проверим, кому принадлежат эти единицы:
    Переменная1.Владелец
    Переменная2.Владелец
    Разные владельцы — гарантированно разные ссылки на единицы измерения.
  3. Использование системной функции ЗначениеВСтрокуВнутр. Это один из самых наглядных способов. Данная функция выводит полное внутреннее представление объекта, включая его тип и внутренний ID.
    ЗначениеВСтрокуВнутр(Переменная1)
    Разница будет видна мгновенно.

Разбор ошибки с поиском по GUID

Иногда разработчики пытаются программно «подставить» нужный идентификатор, используя конструкцию Новый УникальныйИдентификатор(СтрокаGUID). Рассмотрим, почему это может не сработать. Если мы создаем идентификатор вручную, а затем пытаемся получить ссылку методом Справочники.ЕдиницыИзмерения.ПолучитьСсылку(НашУИ), 1С создаст объект ссылки. Однако, если элемента с таким GUID физически не существует в базе данных, мы получим «битую» ссылку (Объект не найден). При сравнении такой «пустышки» с реальным элементом результат всегда будет Ложь.

Как правильно решать проблему в коде

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

1. Поиск с учетом владельца

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


// Правильный поиск в подчиненном справочнике
СсылкаНаЕдиницу = Справочники.ЕдиницыИзмерения.НайтиПоНаименованию("шт", Истина, СсылкаНаТовар);

2. Использование классификаторов

Если ваша логика не привязана к конкретному товару, а требует проверки на соответствие общемировым стандартам (например, проверка, что это именно «штуки»), используйте КлассификаторЕдиницИзмерения (ОКЕИ). Ссылки на элементы классификатора обычно одинаковы для всей базы.

3. Проверка на пустые значения

Прежде чем сравнивать ссылки, убедитесь, что обе они не являются пустыми. Сравнение Справочники.Номенклатура.ПустаяСсылка() с чем-либо также может запутать при отладке, если не обращать внимание на типы данных.

Резюме

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

← На главную