Как правильно искать элементы в справочнике 1С по наименованию внутри группы?

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

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


Род = Справочники.Номенклатура.НайтиПоКоду(5891);
Лом = Справочники.Номенклатура.НайтиПоНаименованию(СтрШихта,,Род);

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

Причины неудачного поиска объектными методами

Выясним, что может пойти не так при использовании методов НайтиПоКоду и НайтиПоНаименованию:

  1. Неверный тип данных при поиске по коду. В 1С реквизит "Код" в подавляющем большинстве случаев является строкой, а не числом. Передача числа 5891 может привести к тому, что переменная Род останется пустой. Правильнее искать по строке с учетом лидирующих нулей (если они есть), например: "00000005891". Всегда проверяйте, найдена ли родительская папка, прежде чем передавать ее параметром в следующий поиск.
  2. Отсутствие рекурсии (глубина поиска). Это важнейший нюанс. Метод НайтиПоНаименованию, когда ему передается параметр родителя, осуществляет поиск элемента исключительно в корне указанной группы. Если искомая номенклатура лежит в подпапке, которая находится внутри папки Род, платформенный метод ее не увидит.
  3. Точное соответствие и лишние символы. В исходном коде пропущен второй параметр (СтрШихта,,Род), который отвечает за точное соответствие. По умолчанию он принимает значение Истина. Это значит, что если в переменной СтрШихта случайно затесался пробел в начале, в конце или между словами стоит два пробела, поиск вернет пустую ссылку.

Почему не работает НайтиПоРеквизиту?

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


// Такой код вызовет ошибку времени выполнения!
Справочник.Номенклатура.НайтиПоРеквизиту("Наименование", СтрШихта, Род);

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

Правильные решения проблемы

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

Решение 1: Использование запроса с условием В ИЕРАРХИИ

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Номенклатура.Ссылка КАК Ссылка
    |ИЗ
    |   Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |   Номенклатура.Наименование = &Наименование
    |   И Номенклатура.Родитель В ИЕРАРХИИ(&Родитель)";

Запрос.УстановитьПараметр("Наименование", СтрШихта);
Запрос.УстановитьПараметр("Родитель", Род);

Результат = Запрос.Выполнить();
Если Не Результат.Пустой() Тогда
    Выборка = Результат.Выбрать();
    Выборка.Следующий();
    НайденнаяСсылка = Выборка.Ссылка;
КонецЕсли;

Решение 2: Поиск по части наименования

Если наименование может незначительно отличаться или содержать лишние пробелы, запрос позволяет использовать оператор ПОДОБНО. Это невозможно реализовать стандартными объектными методами.


// Фрагмент текста запроса:
// ГДЕ Номенклатура.Наименование ПОДОБНО &Наименование

// Установка параметра:
Запрос.УстановитьПараметр("Наименование", "%" + СтрШихта + "%");

Решение 3: Отказ от поиска по наименованию

Искать элементы по наименованию в принципе считается плохой практикой ("вредно для здоровья" кода). Пользователи могут в любой момент изменить название элемента, и ваш код перестанет работать. Разберем более надежные альтернативы:

← На главную