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

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

В процессе разработки на платформе 1С:Предприятие программисты часто сталкиваются с ситуацией, когда метод НайтиПоКоду возвращает пустую ссылку, хотя элемент с таким номером визуально существует в справочнике. Типичный пример: вы пытаетесь найти код "413", но система требует "000000413". Разберем по шагам, почему это происходит и какие существуют наиболее эффективные способы решения этой задачи.

Анализируем причину проблемы: Особенности строковых кодов

В 1С:Предприятии код справочника чаще всего имеет тип Строка. Если для справочника включена автонумерация, система автоматически дополняет короткие числа ведущими нулями до полной длины кода, указанной в конфигураторе (например, до 9 символов). С точки зрения базы данных и встроенного языка, строки "413" и "000000413" — это совершенно разные значения.

Метод НайтиПоКоду выполняет поиск на точное соответствие. Он не «догадывается», что вы имели в виду число, если тип кода определен как строка. Важно понимать, что второй параметр метода (ПоискПоПолномуКоду) предназначен исключительно для иерархических справочников, чтобы искать элемент с учетом кодов родителей (например, "Группа1/000000413"). Он никак не влияет на игнорирование ведущих нулей или поиск по части строки.

Решение 1: Дополнение строки нулями вручную

Самый простой и быстрый способ, который часто встречается в старых конфигурациях — это использование функции Прав для «наращивания» нулей слева. Рассмотрим пример:


БдТекст = "413";
ДлинаКода = 9; // Допустим, мы знаем длину заранее
КодДляПоиска = Прав("000000000" + БдТекст, ДлинаКода);
БД = Справочники.СписокБаз.НайтиПоКоду(КодДляПоиска);

Плюсы: Простота реализации.
Минусы: Жестко заданная длина кода. Если в будущем администратор изменит длину кода в конфигураторе, этот алгоритм перестанет работать корректно.

Решение 2: Универсальное дополнение нулями через метаданные

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


БдТекст = "413";
ДлинаКода = Метаданные.Справочники.СписокБаз.ДлинаКода;

// Формируем строку из нулей нужной длины
СтрокаМаска = "";
Для Сч = 1 По ДлинаКода Цикл
    СтрокаМаска = СтрокаМаска + "0";
КонецЦикла;

КодДляПоиска = Прав(СтрокаМаска + БдТекст, ДлинаКода);
БД = Справочники.СписокБаз.НайтиПоКоду(КодДляПоиска);

Решение 3: Использование функции Формат (Рекомендуемый способ)

Вместо циклов и манипуляций со строками, в 1С предусмотрен мощный инструмент форматирования. Функция Формат позволяет автоматически добавить ведущие нули, преобразуя число в строку нужной длины. Проанализируем этот подход:


БдТекст = "413";
ДлинаКода = Метаданные.Справочники.СписокБаз.ДлинаКода;

// Параметр ЧВН (Четко Ведущие Нули) автоматически заполнит пустые позиции
// Параметр ЧГ=0 убирает группировку разрядов (чтобы не было пробелов в коде)
ПараметрыФорматирования = "ЧЦ=" + ДлинаКода + "; ЧВН=; ЧГ=0";
КодДляПоиска = Формат(Число(БдТекст), ПараметрыФорматирования);

Элемент = Справочники.СписокБаз.НайтиПоКоду(КодДляПоиска);

Этот метод считается наиболее правильным с точки зрения культуры программирования в 1С, так как он компактен и использует встроенные механизмы платформы.

Решение 4: Поиск через запрос (Оператор ПОДОБНО)

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	СписокБаз.Ссылка КАК Ссылка
    |ИЗ
    |	Справочник.СписокБаз КАК СписокБаз
    |ГДЕ
    |	СписокБаз.Код ПОДОБНО ""%"" + &ЧастьКода";

Запрос.УстановитьПараметр("ЧастьКода", "413");
РезультатЗапроса = Запрос.Выполнить();

Внимание: Использование конструкции ПОДОБНО "%413" (с процентом в начале) приводит к тому, что СУБД не может использовать индекс по полю Код. Это заставляет систему сканировать всю таблицу справочника целиком. На больших справочниках (десятки и сотни тысяч записей) такой поиск будет работать крайне медленно. Также есть риск найти "лишние" элементы, например, вместо "000000413" запрос может вернуть "000004130", если условие поиска составлено неверно.

Решение 5: Использование функций БСП

Если вы работаете в современной конфигурации, где подключена Библиотека Стандартных Подсистем (БСП), рекомендуем использовать готовые функции. Это упрощает код и делает его понятным для других разработчиков. Посмотрим на пример использования общего модуля ПрефиксацияОбъектовКлиентСервер:


БдТекст = "413";
ДлинаКода = Метаданные.Справочники.СписокБаз.ДлинаКода;

// Используем стандартную функцию БСП
КодДляПоиска = ПрефиксацияОбъектовКлиентСервер.ДополнитьСтрокуНулями(БдТекст, ДлинаКода);
Элемент = Справочники.СписокБаз.НайтиПоКоду(КодДляПоиска);

Почему 1С вообще использует ведущие нули?

Выясним причину такого поведения системы. Ведущие нули необходимы для правильной сортировки строковых данных. В строках сортировка идет посимвольно (лексикографически). Если бы нулей не было, порядок кодов был бы таким:

Добавление нулей превращает их в 001, 002, 010, 011, что позволяет базе данных выстраивать список в привычном нам числовом порядке. Именно поэтому при поиске строкового кода всегда важно приводить искомое значение к каноническому виду со всеми нулями.

Итоги и рекомендации

  1. Всегда проверяйте тип кода в конфигураторе. Если тип Строка — ищите полное соответствие с нулями.
  2. Избегайте поиска через ПОДОБНО "%..." в запросах из-за низкой скорости работы.
  3. Используйте функцию Формат или ПрефиксацияОбъектовКлиентСервер.ДополнитьСтрокуНулями для подготовки кода к поиску.
  4. Получайте длину кода динамически через Метаданные, чтобы ваш код не «сломался» при обновлении конфигурации.
← На главную