Как правильно отобрать и найти элементы справочника по реквизиту в 1С 7.7?

Программист 1С v7.7 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

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

Анализ основных причин проблемы

Рассмотрим типичный фрагмент кода, в котором допущены сразу две распространенные ошибки:


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

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

  1. Несоответствие типов данных: Реквизит Номенклатура в подчиненных справочниках или регистрах обычно имеет ссылочный тип Справочник.Номенклатура. Если передать в качестве второго параметра метода НайтиПоРеквизиту() строку с наименованием (Источник.Наименование), платформа попытается найти точное строковое совпадение. Так как тип реквизита — справочник, а тип поискового значения — строка, совпадение никогда не будет найдено.
  2. Сброс контекста методом ВыбратьЭлементы(): Вызов ВыбратьЭлементы() начинает полный последовательный обход элементов всего справочника с начала, полностью сбрасывая текущую позицию, найденную методом НайтиПоРеквизиту(). Этот метод не выполняет фильтрацию по предыдущему поиску.

Способ 1. Выборка всех записей по реквизиту

Если перед нами стоит задача выбрать все элементы справочника, у которых значение реквизита равно заданному объекту, необходимо использовать специализированный метод ВыбратьЭлементыПоРеквизиту(). Сначала найдем искомую ссылку на номенклатуру, а затем выполним по ней отбор:


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

Способ 2. Поиск одиночного элемента по реквизиту

Если требуется найти только один (первый попавшийся) элемент справочника, удовлетворяющий условию, используем метод НайтиПоРеквизиту() с корректной передачей ссылки на объект:


СпрНом = СоздатьОбъект("Справочник.Номенклатура");
Если СпрНом.НайтиПоНаименованию(Источник.Наименование, 0, 1) = 1 Тогда
    СсылкаНоменклатура = СпрНом.ТекущийЭлемент();
    
    СпрФТ = СоздатьОбъект("Справочник.ФильтрыТовары");
    Если СпрФТ.НайтиПоРеквизиту("Номенклатура", СсылкаНоменклатура, 1) = 1 Тогда
        Сообщить("Найден элемент: " + СпрФТ.ТекущийЭлемент());
        Сообщить("Фильтр: " + СпрФТ.Фильтр);
    Иначе
        Сообщить("Элемент в справочнике ФильтрыТовары не найден.");
    КонецЕсли;
КонецЕсли;

Важные требования к структуре метаданных

Для корректной работы методов НайтиПоРеквизиту() и ВыбратьЭлементыПоРеквизиту() необходимо соблюдение правил конфигуратора:

  1. Флаг «Сортировка»: У реквизита справочника в конфигураторе (на вкладке «Дополнительные») обязательно должен быть установлен признак «Сортировка» (отбор по реквизиту). Если этот флаг отсутствует, платформа выдаст ошибку времени выполнения.
  2. Ограничение на периодичность: Поиск и выборка по реквизиту не поддерживаются для периодических реквизитов справочника.

Альтернативный вариант: Использование объекта «Запрос»

Если у реквизита в конфигурации не установлен флаг «Сортировка» и менять метаданные нельзя, оптимальным решением является использование встроенного механизма запросов 1С 7.7:


Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса = 
"//{{ЗАПРОС(ВыборкаПоРеквизиту)
|ТекущийЭлемент = Справочник.ФильтрыТовары.ТекущийЭлемент;
|Номенклатура = Справочник.ФильтрыТовары.Номенклатура;
|Фильтр = Справочник.ФильтрыТовары.Фильтр;
|Группировка ТекущийЭлемент без групп;
|Условие(Номенклатура = ИскомаяНоменклатура);
|"//}}ЗАПРОС
;

Если Запрос.Выполнить(ТекстЗапроса) = 1 Тогда
    Пока Запрос.Группировка(1) = 1 Цикл
        Сообщить("Элемент: " + Запрос.ТекущийЭлемент);
        Сообщить("Фильтр: " + Запрос.Фильтр);
    КонецЦикла;
КонецЕсли;

Такой подход гарантирует корректную фильтрацию данных независимо от настроек индексации реквизита в конфигураторе.

← На главную