Почему метод НайтиПоНаименованию в 1С 7.7 не находит элемент и как правильно настроить параметры поиска?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

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

Причина проблемы: значения параметров по умолчанию

Проанализируем синтаксис встроенного метода справочника в 1С 7.7:

НайтиПоНаименованию(<Наименование>, <Режим>, <ФлагПоиска>)

Рассмотрим назначение каждого параметра подробнее:

  1. <Наименование> — строковое выражение, содержащее искомое название элемента.
  2. <Режим> — необязательный числовой параметр:
    • 1 (значение по умолчанию) — поиск осуществляется только внутри текущего родителя (установленной группы). Если родитель явно не задан методом ИспользоватьРодителя(), поиск будет производиться исключительно в корне справочника среди элементов первого уровня. Элементы, вложенные в любые папки и подпапки, найдены не будут.
    • 0 — поиск выполняется по всей иерархии справочника, независимо от вложенности и групп.
  3. <ФлагПоиска> — необязательный числовой параметр:
    • 0 (значение по умолчанию) — поиск по начальным символам наименования.
    • 1 — поиск строго по точному совпадению всей строки.

Таким образом, при вызове метода только с одним параметром Спр.НайтиПоНаименованию(СтрокаПоиска) платформа ищет элемент исключительно в корне справочника. Если товар лежит в любой группе номенклатуры, метод возвращает 0.

Корректная реализация поиска по наименованию

Чтобы найти элемент в иерархическом справочнике по всей базе, необходимо явно передать второй параметр со значением 0. Также для исключения случайных совпадений по первым буквам рекомендуется устанавливать третий параметр в значение 1 (точное соответствие).

Посмотрим на пример правильного кода:


СпрНом = СоздатьОбъект("Справочник.Номенклатура");
ИскомоеНазвание = СокрЛП(Таб.ТовНаим);

// 0 - поиск по всему справочнику, 1 - точное совпадение
Если СпрНом.НайтиПоНаименованию(ИскомоеНазвание, 0, 1) = 1 Тогда
    // После успешного позиционирования обращение к реквизитам выполняется напрямую
    Таб.СтавкаНДС = СпрНом.СтавкаНДС;
Иначе
    Сообщить("Номенклатура не найдена: " + ИскомоеНазвание, "!");
КонецЕсли;

Обратите внимание: после успешного выполнения поиска объект справочника уже спозиционирован на найденной записи. Конструкция Спр.ТекущийЭлемент().СтавкаНДС является избыточной — правильнее и быстрее обращаться к реквизитам напрямую через переменную объекта: Спр.СтавкаНДС.

Дополнительные причины, почему элемент может не находиться

Если поиск с параметром 0 по-прежнему возвращает неудачу, проверим следующие нюансы строковых данных:

  1. Неразрывные пробелы и спецсимволы: При загрузке данных из внешних файлов (Excel, TXT, XML) в строки часто попадают неразрывные пробелы с кодом 160. Стандартная функция СокрЛП удаляет только обычные пробелы (код 32). Для очистки выполним предварительную замену: СтрЗаменить(ИскомаяСтрока, Симв(160), " ").
  2. Краткое и полное наименование: Метод НайтиПоНаименованию ищет только по стандартному реквизиту Наименование. Если из внешнего источника передается длинное описание, в конфигурациях 1С 7.7 оно обычно хранится в отдельном реквизите ПолнНаименование. Для поиска по дополнительным реквизитам используется метод НайтиПоРеквизиту.
  3. Смешанная раскладка букв: Визуально одинаковые символы кириллицы и латиницы (например, буквы «С», «О», «Р», «А», «Х») имеют разные коды, из-за чего точное строковое сравнение завершится с ошибкой.

Альтернативные варианты поиска данных

Рассмотрим другие проверенные способы сопоставления номенклатуры в 1С 7.7 в зависимости от стоящей задачи:

  1. Поиск по дополнительному реквизиту (артикул, полное наименование):
    Если требуется найти элемент по реквизиту, у которого в метаданных включена сортировка или отбор, применим метод НайтиПоРеквизиту:
    
    СпрНом = СоздатьОбъект("Справочник.Номенклатура");
    // 0 - поиск по всему справочнику
    Если СпрНом.НайтиПоРеквизиту("Артикул", ИскомыйАртикул, 0) = 1 Тогда
        Таб.СтавкаНДС = СпрНом.СтавкаНДС;
    КонецЕсли;
    
  2. Использование объекта «Запрос» для выборки без групп:
    Если необходимо исключить группы или помеченные на удаление элементы, используем запрос:
    
    Запрос = СоздатьОбъект("Запрос");
    ТекстЗапроса = 
    "//{{ЗАПРОС(ПоискТовара)
    |Товар = Справочник.Номенклатура.ТекущийЭлемент;
    |Ставка = Справочник.Номенклатура.СтавкаНДС;
    |Группировка Товар без групп;
    |Условие(Товар.Наименование = ИскомоеНазвание);
    |"//}}ЗАПРОС
    ;
    
    Если Запрос.Выполнить(ТекстЗапроса) = 1 Тогда
        Если Запрос.Группировка(1) = 1 Тогда
            Таб.СтавкаНДС = Запрос.Ставка;
        КонецЕсли;
    КонецЕсли;
    
  3. Кэширование справочника в Таблицу Значений (для массовой обработки):
    При построчной загрузке больших файлов регулярный вызов метода НайтиПоНаименованию внутри цикла замедляет работу из-за постоянных обращений к базе. Для ускорения выгрузим весь справочник в память один раз перед циклом:
    
    ТЗНоменклатура = СоздатьОбъект("ТаблицаЗначений");
    СпрНом = СоздатьОбъект("Справочник.Номенклатура");
    СпрНом.ВыгрузитьТаблицу(ТЗНоменклатура);
    
    // Внутри цикла загрузки строк:
    НомСтроки = 0;
    Если ТЗНоменклатура.НайтиЗначение(ИскомоеНазвание, НомСтроки, "Наименование") = 1 Тогда
        ТЗНоменклатура.ПолучитьСтрокуПоНомеру(НомСтроки);
        Таб.СтавкаНДС = ТЗНоменклатура.СтавкаНДС;
    КонецЕсли;
    
← На главную