Как исправить ошибку «Неверно указан реквизит» при поиске номенклатуры в 1С

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

В процессе разработки на платформе 1С:Предприятие 8 часто возникает задача поиска элементов справочника по дополнительным полям, таким как артикул, штрихкод или внутренний идентификатор из другой системы. Метод НайтиПоРеквизиту кажется самым простым решением, однако при его использовании программисты часто сталкиваются с системной ошибкой: «Неверно указан реквизит». В этой статье мы подробно разберем, почему возникает эта проблема, и как правильно реализовать поиск номенклатуры, чтобы код работал быстро и без ошибок.

Разбор типичной ситуации и анализ кода

Рассмотрим ситуацию, с которой столкнулся автор темы. Имеется таблица значений, загруженная из внешнего источника (например, Excel), содержащая артикулы. Задача состоит в том, чтобы найти соответствующие ссылки в справочнике Номенклатура и заполнить ими табличную часть документа.

Типичный (но не самый оптимальный) код выглядит следующим образом:


Для Каждого СтрокаТЗ Из ТаблицаЗначенийИзЭксель Цикл
    // Пытаемся найти номенклатуру по строковому артикулу
    Артикул1С = Справочники.Номенклатура.НайтиПоРеквизиту("Артикул1С", СтрокаТЗ.Артикул1С);
    
    Если Не Артикул1С.Пустая() Тогда
        НовСтрока = Объект.ПозицииНоменклатуры.Добавить();
        НовСтрока.Номенклатура = Артикул1С;
        // Заполнение остальных данных...
    Иначе
        Сообщить("Элемент с артикулом " + СтрокаТЗ.Артикул1С + " не найден!");
    КонецЕсли;
КонецЦикла;

Если при выполнении этого кода система выдает ошибку «Неверно указан реквизит», значит, не соблюдено одно из технических требований платформы к использованию данного метода. Выясним причины по порядку.

Причина 1: Отсутствие индексирования реквизита

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

Что нужно проверить:

  1. Откройте Конфигуратор.
  2. Найдите справочник Номенклатура и перейдите на закладку Данные.
  3. Найдите реквизит Артикул1С и откройте его свойства.
  4. Найдите свойство Индексировать. Если там установлено значение «Не индексировать», метод работать не будет.
  5. Установите значение Индексировать или Индексировать с дополнительным упорядочиванием.

После изменения метаданных необходимо обновить конфигурацию базы данных. Только после этого метод начнет «видеть» реквизит.

Причина 2: Строка неограниченной длины

Проанализируем тип данных реквизита. В системе 1С невозможно проиндексировать поля типа Строка с неограниченной длиной. Если при создании реквизита Артикул1С вы не указали конкретную длину (например, 11 или 25 символов), а оставили ее нулевой (неограниченной), то индексирование будет недоступно, и метод НайтиПоРеквизиту работать не сможет по определению.

Решение: Всегда задавайте разумную фиксированную длину для строковых идентификаторов, которые планируется использовать для поиска.

Причина 3: Ошибки в написании имени реквизита

Метод чувствителен к точному написанию Имени реквизита (не путать с Синонимом). Проанализируем возможные проблемы:

Совет: Всегда копируйте имя реквизита напрямую из поля «Имя» в окне свойств объекта в Конфигураторе.

Причина 4: Несоответствие типов данных

Метод НайтиПоРеквизиту требует строгого соответствия типов. Если в метаданных реквизит Артикул1С определен как Строка, то и второй параметр метода (значение поиска) должен быть строкой.

Рассмотрим подробнее проблему загрузки из Excel. Числовые артикулы (например, 000123) часто загружаются как числа (123). При поиске строки «000123» по значению 123 система не найдет соответствие. Для поиска позиций с автоматическим приведением типов можно использовать инструмент поиска по всем дополнительным реквизитам номенклатуры.

Выясним, как привести данные к нужному виду:


// Пример приведения числа к строке с ведущими нулями
ЗначениеПоиска = СокрЛП(СтрокаТЗ.Артикул1С);
// Если нужно дополнить нулями до 11 символов
Пока СтрДлина(ЗначениеПоиска) < 11 Цикл
    ЗначениеПоиска = "0" + ЗначениеПоиска;
КонецЦикла;

Результат = Справочники.Номенклатура.НайтиПоРеквизиту("Артикул1С", ЗначениеПоиска);

Профессиональный подход: использование запросов

Использование метода НайтиПоРеквизиту внутри цикла (как в сообщении 7 форума) является плохой практикой (антипаттерном). Каждая итерация цикла порождает отдельный запрос к базе данных. Если в вашем файле 1000 строк, система сделает 1000 микро-запросов, что значительно замедлит работу.

Рассмотрим, как правильно выполнить поиск через объект Запрос. Это решение универсально: оно работает быстрее, не требует обязательного индексирования (хотя индекс все равно желателен для скорости) и позволяет избежать ошибки «Неверно указан реквизит».


// 1. Соберем все искомые артикулы в массив
МассивАртикулов = ТаблицаЗначенийИзЭксель.ВыгрузитьКолонку("Артикул1С");

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

Запрос.УстановитьПараметр("МассивАртикулов", МассивАртикулов);

// 3. Выполним поиск одним махом
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

// 4. Для удобства можно выгрузить результат в соответствие или индексированную таблицу
ТаблицаРезультатов = РезультатЗапроса.Выгрузить();
ТаблицаРезультатов.Индексы.Добавить("Артикул1С");

// Теперь в цикле по исходным данным ищем ссылку в ТаблицаРезультатов
Для Каждого СтрокаТЗ Из ТаблицаЗначенийИзЭксель Цикл
    ПараметрыПоиска = Новый Структура("Артикул1С", СтрокаТЗ.Артикул1С);
    НайденныеСтроки = ТаблицаРезультатов.НайтиСтроки(ПараметрыПоиска);
    
    Если НайденныеСтроки.Количество() > 0 Тогда
        // Ссылка найдена!
        СсылкаНоменклатура = НайденныеСтроки[0].Ссылка;
    КонецЕсли;
КонецЦикла;

Заключение

Мы проанализировали основные причины сбоев при программном поиске номенклатуры. Подведем итоги:

  1. Если вы используете НайтиПоРеквизиту, обязательно проверьте флаг Индексировать в свойствах реквизита.
  2. Убедитесь, что тип передаваемого значения в коде полностью совпадает с типом реквизита в метаданных (особенно внимательно со строками и числами).
  3. Для массовой обработки данных всегда отдавайте предпочтение запросам — это надежнее, быстрее и избавляет от многих ограничений платформенных методов поиска.

Соблюдение этих простых правил сделает вашу разработку более стабильной и профессиональной.

← На главную