Как найти номенклатуру по дополнительному реквизиту в 1С 8.3

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

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

Почему метод НайтиПоРеквизиту не подходит

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

  1. Метод НайтиПоРеквизиту() предназначен исключительно для работы с реквизитами верхнего уровня, созданными в конфигураторе (например, Артикул, Код, Наименование).
  2. Для работы данного метода в метаданных соответствующего реквизита должно быть включено свойство «Индексировать».
  3. Дополнительные реквизиты не являются физическими реквизитами самого справочника. Они хранятся во вложенной табличной части объекта, поэтому поиск по ним через менеджер справочника не поддерживается.

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

В типовых конфигурациях 1С (УТ 11, ERP, КА, БП 3.0 и др.) механизмы БСП (Библиотеки Стандартных Подсистем) разделяют дополнительные свойства на два типа:

  1. Дополнительные реквизиты — хранятся непосредственно в объекте (например, в табличной части ДополнительныеРеквизиты справочника Номенклатура). Они изменяются вместе с объектом и отображаются на его форме.
  2. Дополнительные сведения — хранятся отдельно от объекта в регистре сведений ЗначенияСвойствОбъектов.

Посмотрим на структуру табличной части ДополнительныеРеквизиты справочника Номенклатура. В ней содержатся следующие основные колонки:

– Свойство — ссылка на план видов характеристик ДополнительныеРеквизитыИСведения;
– Значение — значение реквизита (составной тип данных).

Поиск номенклатуры с помощью запроса

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

Рассмотрим частую ошибку разработчиков при написании запроса. Не рекомендуется выбирать данные через вложенную таблицу реквизитов объекта в секции ВЫБРАТЬ (например, Номенклатура.ДополнительныеРеквизиты.(...)), так как это приводит к неоптимальной выборке. Правильный подход — обращаться напрямую к табличной части справочника.

Рассмотрим пример правильного кода для поиска ссылки на номенклатуру:


// 1. Получаем ссылку на сам дополнительный реквизит (свойство)
СвойствоСтарыйКод = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("СтарыйКод");

Если Не ЗначениеЗаполнено(СвойствоСтарыйКод) Тогда
    ВызватьИсключение "Не найдено свойство 'СтарыйКод'!";
КонецЕсли;

// 2. Формируем запрос к табличной части справочника
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |	НоменклатураДоп.Ссылка КАК Номенклатура
    |ИЗ
    |	Справочник.Номенклатура.ДополнительныеРеквизиты КАК НоменклатураДоп
    |ГДЕ
    |	НоменклатураДоп.Свойство = &Свойство
    |	И НоменклатураДоп.Значение = &Значение
    |	И НЕ НоменклатураДоп.Ссылка.ЭтоГруппа";

Запрос.УстановитьПараметр("Свойство", СвойствоСтарыйКод);
Запрос.УстановитьПараметр("Значение", Число(ИскомыйКод)); // Убедитесь в соответствии типа данных

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

Пока Выборка.Следующий() Цикл
    // Работаем со найденной ссылкой
    СсылкаНаНоменклатуру = Выборка.Номенклатура;
КонецЦикла;

Альтернативный вариант: Поиск по Дополнительным сведениям

Если в вашей конфигурации свойство заведено не как дополнительный реквизит, а как дополнительное сведение, данные хранятся в регистре сведений. В этом случае поиск выполняем по регистру ЗначенияСвойствОбъектов.

Разберем по шагам соответствующий запрос:


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

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

РезультатЗапроса = Запрос.Выполнить();

Важные нюансы при работе с дополнительными реквизитами

  1. Типы данных: Поле Значение имеет составной тип. Если реквизит числовой, передавайте в параметр &Значение строго тип Число. Если значение выбирается из списка предустановленных значений, в параметр нужно передавать ссылку на элемент справочника ЗначенияСвойствОбъектов.
  2. Поиск свойства: Использование метода НайтиПоНаименованию() для PVI может быть ненадёжным, если в базе есть свойства с одинаковыми именами для разных наборов. В реальных задачах предпочтительно искать свойство по правильному набору или уникальному имени.
  3. Управление дублями: Всегда используйте ключевое слово ВЫБРАТЬ РАЗЛИЧНЫЕ при запросе к табличным частям, чтобы исключить повторяющиеся ссылки в результатах выборки.
← На главную