В практике программирования на платформе 1С:Предприятие часто возникает ситуация, когда при сравнении двух ссылок на один и тот же объект (например, номенклатуру) система возвращает Ложь. На первый взгляд это кажется нелогичным: в отладчике мы видим одинаковые названия, коды и даже внутренние идентификаторы, но стандартный оператор равенства не срабатывает. В этой статье мы подробно разберем, почему так происходит, и рассмотрим надежные способы решения этой задачи.
Прежде чем переходить к коду, давайте проанализируем ситуацию. В 1С ссылка — это не просто строка с названием, а сложный объект, содержащий уникальный идентификатор (GUID). Однако равенство ссылок в коде зависит не только от GUID, но и от контекста, в котором эти ссылки существуют. Рассмотрим основные причины "ложного" несовпадения:
СправочникСсылка, а в другой — СправочникОбъект (полученный через метод ПолучитьОбъект()), то прямое сравнение всегда даст Ложь. Программные типы объектов в памяти абсолютно разные, даже если они указывают на одну запись в базе.COMОбъект. Для 1С локальная ссылка и COM-ссылка — это разные сущности, даже если они представляют один и тот же элемент номенклатуры.Как показало обсуждение, наиболее универсальным способом решения проблемы (особенно при работе с разными контекстами или внешними данными) является сравнение уникальных идентификаторов, приведенных к строковому типу. Рассмотрим пример кода, который позволяет обойти проблему несовпадения типов:
Для Каждого СтрВнеш Из ТаблицаВнешнихДанных Цикл
Для Каждого СтрВнут Из ТаблицаВнутреннихДанных Цикл
// Приводим идентификаторы к строке для гарантированного сравнения
ИД_Внеш = Строка(СтрВнеш.Номенклатура.УникальныйИдентификатор());
ИД_Внут = Строка(СтрВнут.Номенклатура.УникальныйИдентификатор());
Если ИД_Внеш = ИД_Внут Тогда
Сообщить("Номенклатура совпала: " + СтрВнеш.Номенклатура);
// Ваша логика обработки
КонецЕсли;
КонецЦикла;
КонецЦикла;
Важный нюанс: метод УникальныйИдентификатор() доступен только у ссылок. Если в переменной может оказаться объект или неопределенное значение, необходимо добавить проверку типа или использовать функции метаданных.
Если вы столкнулись с тем, что сравнение не работает, первым делом проанализируйте, что именно лежит в ваших переменных. Разберем, как вывести диагностическую информацию в консоль:
Сообщить("Тип внешней номенклатуры: " + ТипЗнч(СтрСтараяТЗВнеш.Номенклатура));
Сообщить("Тип внутренней номенклатуры: " + ТипЗнч(СтрСтараяТЗВнут.Номенклатура));
Сообщить("Значение через XMLСтрока: " + XMLСтрока(СтрСтараяТЗВнеш.Номенклатура));
Использование XMLСтрока() — это отличная альтернатива преобразованию GUID в строку. Этот метод работает быстрее и часто используется для сериализации ссылок. Если значения XMLСтрока совпадают, значит, ссылки указывают на один и тот же объект базы данных.
Сравнение таблиц в цикле (перебор "каждый с каждым") крайне неэффективно при больших объемах данных. Если вам нужно найти совпадения в двух таблицах значений, правильнее использовать временные таблицы в запросе. Запрос автоматически приведет типы к сопоставимому виду и выполнит сравнение на уровне СУБД, что в десятки раз быстрее.
Рассмотрим алгоритм действий:
ТаблицаЗначений, чтобы система понимала, что сравниваются именно ссылки.ВНУТРЕННЕЕ СОЕДИНЕНИЕ по полю Номенклатура.
МенеджерВТ = Новый МенеджерВременных Таблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
Запрос.Текст = "ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Данные ИЗ &ТЗ КАК ТЗ";
Запрос.УстановитьПараметр("ТЗ", ТаблицаНоменклатуры);
Запрос.Выполнить();
// Теперь в запросе можно легко сравнить данные из ВТ с другой таблицей или данными БД
Если ваша задача — "склеить" (суммировать) строки с одинаковой номенклатурой внутри одной таблицы значений, не нужно писать вложенные циклы со сравнениями. В 1С для этого предназначен встроенный высокопроизводительный метод Свернуть(). Проанализируем пример:
// Допустим, в ТЗ есть колонки Номенклатура, Количество, Сумма
// Мы хотим объединить дубли по номенклатуре
ТаблицаТоваров.Свернуть("Номенклатура", "Количество, Сумма");
Этот метод работает на уровне платформы и корректно обрабатывает ссылки одного типа, объединяя строки гораздо быстрее, чем любой ручной перебор с условиями Если ... Тогда.
Для корректного сравнения номенклатуры в 1С придерживайтесь следующих правил:
= не помогает, сравнивайте результаты УникальныйИдентификатор() или XMLСтрока().НайтиСтроки().Следуя этим рекомендациям, вы сможете избежать трудноуловимых ошибок и обеспечите стабильную работу ваших механизмов обработки данных в 1С.