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