Почему метод НайтиПоРеквизиту не находит штрихкод номенклатуры в 1С

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

Одной из самых распространенных и в то же время загадочных проблем при разработке в 1С является ситуация, когда программный поиск объекта по реквизиту возвращает пустую ссылку, хотя визуально данные в базе присутствуют. Особенно часто это происходит при работе со строковыми идентификаторами, такими как штрихкоды. Разберем детально причины этой проблемы на примере конфигурации 1С:Управление торговлей 10.3 и методов платформы 1С:Предприятие 8.

1. Проверка структуры хранения данных

Прежде чем приступать к отладке кода, проанализируем, где именно хранятся данные. В типовой конфигурации УТ 10.3 штрихкоды по умолчанию не являются реквизитами справочника Номенклатура. Они хранятся в независимом регистре сведений Штрихкоды. Если в вашей базе поиск идет через Справочники.Номенклатура.НайтиПоРеквизиту("Штрихкод", ...), это означает одно из двух:

  1. В конфигурацию были внесены изменения, и в справочник Номенклатура вручную добавлен новый реквизит Штрихкод.
  2. Вы пытаетесь найти данные по реквизиту, которого не существует в стандартной поставке, что приведет к ошибке или возврату пустой ссылки.

Важно: Если реквизит добавлен вручную, убедитесь, что у него установлено свойство Индексировать. Без индекса метод НайтиПоРеквизиту может работать некорректно или крайне медленно на больших объемах данных.

2. Проблема фиксированной длины строки и лишних пробелов

Выясним причину, связанную с типами данных. В 1С строковые реквизиты могут иметь фиксированную или переменную длину. Если для реквизита Штрихкод установлена фиксированная длина (например, 13 символов), система всегда будет дополнять значение пробелами справа до указанного лимита.

Рассмотрим пример. В базе хранится штрихкод "65672891851 " (с двумя пробелами в конце). Если вы ищете строку "65672891851", поиск не даст результата, так как для метода НайтиПоРеквизиту требуется полное совпадение строки.

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


НайденнаяНоменклатура = Справочники.Номенклатура.НайтиПоРеквизиту("Штрихкод", СокрЛП(СтрТчНом.Штрихкод));
Если Не НайденнаяНоменклатура.Пустая() Тогда
    СтрТчНом.Номенклатура1с = НайденнаяНоменклатура;
КонецЕсли;

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

3. Невидимые символы и кодировки

Часто при импорте данных из внешних файлов (Excel, CSV) в строку попадают невидимые символы. Самый "коварный" из них — неразрывный пробел (код символа 160). Стандартная функция СокрЛП удаляет только обычные пробелы (код 32). Если в конце штрихкода стоит неразрывный пробел, визуально в карточке товара он не виден, но поиск по обычной строке его не найдет.

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


// Возьмите ссылку на номенклатуру, которая точно имеет этот штрихкод
ОбъектИзБазы = Справочники.Номенклатура.НайтиПоКоду("00001");
ШтрихкодВБазе = ОбъектИзБазы.Штрихкод;
ИскомыйШтрихкод = СокрЛП(СтрТчНом.Штрихкод);

// Сравните длину строк
Длина1 = СтрДлина(ШтрихкодВБазе);
Длина2 = СтрДлина(ИскомыйШтрихкод);

// Проверьте коды каждого символа, если длины не совпадают
Для Номер = 1 По СтрДлина(ШтрихкодВБазе) Цикл
    Сообщить("Символ №" + Номер + ": Код " + КодСимвола(ШтрихкодВБазе, Номер));
КонецЦикла;

4. Ошибка в проверке результата поиска

Обратите внимание на проверку результата в исходном сообщении автора темы: Если НайденнаяНоменклатура <> Неопределено. Это классическая ошибка начинающего разработчика. Методы поиска в 1С (такие как НайтиПоРеквизиту, НайтиПоКоду, НайтиПоНаименованию) никогда не возвращают Неопределено. Они возвращают Пустую ссылку соответствующего типа.

Правильная проверка должна выглядеть так:


НайденнаяНоменклатура = Справочники.Номенклатура.НайтиПоРеквизиту("Штрихкод", НужныйШтрихкод);
Если Не НайденнаяНоменклатура.Пустая() Тогда
    // Объект найден
КонецЕсли;

5. Альтернативный и более надежный метод: Запрос

Разберем, почему использование запросов предпочтительнее метода НайтиПоРеквизиту. Запрос позволяет гибко работать со строками и не зависеть от индексации одного конкретного поля (хотя индексация все равно важна для производительности). Кроме того, если штрихкоды хранятся в регистре сведений (как это сделано в типовой УТ 10.3), запрос становится единственным верным решением.

Посмотрим на пример запроса для поиска номенклатуры по штрихкоду из регистра сведений:


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

Запрос.УстановитьПараметр("Штрихкод", СокрЛП(ИскомоеЗначение));

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

6. Специфика форматов (EAN-13 и UPC-A)

Выясним еще одну деталь: штрихкоды формата EAN-13 состоят из 13 цифр. Однако штрихкоды типа UPC-A содержат 12 цифр. При записи в базу 1С часто автоматически дополняет 12-значный код ведущим нулем, превращая его в EAN-13. Если вы ищете "65672891851" (11 или 12 знаков), а в базе хранится "065672891851", прямое сравнение через НайтиПоРеквизиту выдаст ложь.

Рекомендации для стабильной работы поиска:

Проанализировав все вышеперечисленные шаги, мы можем сделать вывод: наиболее частой причиной неудачи является несоответствие типов или наличие скрытых пробелов в строках фиксированной длины. Тщательная проверка через отладчик и использование запросов помогут избежать подобных проблем в будущем.

← На главную