Почему метод Найти для Построитель.Отбор возвращает Неопределено и как это исправить?

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

При работе с механизмом ПостроительОтчета или ПостроительЗапроса в платформе «1С:Предприятие» разработчики часто сталкиваются с неожиданным поведением коллекции отборов. Наиболее типичный сценарий: в отладчике мы отчетливо видим, что отбор по определенному полю (например, по номенклатуре или складу) установлен и активен, но вызов метода Построитель.Отбор.Найти("Номенклатура") упорно возвращает значение Неопределено.

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

Выясняем причину: анатомия элемента отбора

Для начала проанализируем, как устроена коллекция отборов построителя. Каждый элемент этой коллекции (тип ЭлементОтбора) обладает несколькими ключевыми строковыми свойствами, которые важно различать:

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

Проблема кроется в разнице между интерактивным добавлением отборов пользователем и их программной инициализацией.

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

Поскольку свойство Имя у созданного элемента пустое, метод Построитель.Отбор.Найти("Номенклатура") физически не может сопоставить переданную строку поиска со значением свойства Имя и возвращает нам Неопределено. Это поведение является стандартным для платформы «1С:Предприятие» и сохраняется при использовании методов импорта/экспорта настроек (таких как ПолучитьНастройки() и УстановитьНастройки()).

Рассмотрим по шагам два надежных способа решения этой проблемы в зависимости от контекста вашей задачи.

Способ 1. Универсальный поиск перебором коллекции (для интерактивных отборов)

Если в вашем решении пользователи имеют возможность самостоятельно добавлять, изменять и удалять фильтры в табличном поле на форме, мы не можем гарантировать заполнение свойства Имя. В этом случае наиболее надежным и отказоустойчивым решением будет ручной обход коллекции отборов с проверкой свойства ПутьКДанным.

Давайте разберем пример кода, реализующий этот подход:


// Инициализируем переменную для хранения найденного элемента
ИскомыйОтбор = Неопределено;

// Перебираем всю коллекцию элементов отбора построителя
Для Каждого ЭлементОтбора Из ПостроительОтчета.Отбор Цикл
    // Проверяем соответствие пути к данным искомому полю
    Если ЭлементОтбора.ПутьКДанным = "Номенклатура" Тогда
        ИскомыйОтбор = ЭлементОтбора;
        Прервать; // Цель достигнута, досрочно выходим из цикла
    КонецЕсли;
КонецЦикла;

// Проверяем результат поиска
Если ИскомыйОтбор <> Неопределено Тогда
    // Элемент успешно найден, выполняем необходимые действия
    ИскомыйОтбор.Использование = Истина;
    ИскомыйОтбор.ВидСравнения = ВидСравнения.ВГруппе;
    Сообщить("Отбор по номенклатуре успешно найден и активирован!");
Иначе
    Сообщить("Отбор по номенклатуре не задан в настройках построителя.");
КонецЕсли;

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

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

Если вы настраиваете отборы построителя из кода программы, очень важно избегать частой ошибки, когда методу добавления передается только путь к данным.

Например, при вызове конструкции Построитель.Отбор.Добавить("Номенклатура") имя элемента может не заполниться автоматически, что в дальнейшем приведет к невозможности использования метода Найти().

Для предотвращения этой проблемы обратимся к синтаксису метода Добавить():

Добавить(<ПутьКДанным>, <Имя>, <Представление>)

Чтобы в дальнейшем мы могли без проблем находить элемент методом Найти(), нам необходимо в обязательном порядке передавать второй параметр — уникальное имя элемента в коллекции. Проанализируем правильный пример программной инициализации:


// Программное добавление отбора с явным указанием имени элемента
ИмяПоля = "Номенклатура";
НовыйОтбор = ПостроительОтчета.Отбор.Добавить(ИмяПоля, ИмяПоля);

// Теперь элемент гарантированно имеет заполненное свойство "Имя"
// Мы можем мгновенно обращаться к нему стандартным методом:
ЭлементНоменклатура = ПостроительОтчета.Отбор.Найти("Номенклатура");

Если ЭлементНоменклатура <> Неопределено Тогда
    ЭлементНоменклатура.Значение = Справочники.Номенклатура.НайтиПоРеквизиту("Артикул", "Samsung-01");
    ЭлементНоменклатура.Использование = Истина;
КонецЕсли;

Передавая имя поля во второй параметр метода Добавить(), мы создаем жесткую связку, которая позволяет использовать лаконичный и быстрый метод Найти() без необходимости написания циклов обхода.

Дополнительные рекомендации по работе с построителем

Стоит упомянуть еще один важный аспект работы с построителями отчетов и запросов. Если в исходном тексте запроса поля отборов определены в необязательных фигурных скобках (например, {ГДЕ Номенклатура.*}), то они будут доступны в коллекции отборов только в том случае, если эти поля добавлены в список доступных полей построителя.

Если вы динамически меняете текст запроса построителя в коде, рекомендуется принудительно вызывать метод ЗаполнитьНастройки() для обновления состава доступных полей и корректной инициализации структуры отборов:


// Обновляем текст запроса построителя
ПостроительОтчета.Текст = ПолучитьНовыйТекстЗапроса();

// Принудительно обновляем состав доступных полей и отборов
ПостроительОтчета.ЗаполнитьНастройки();

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

← На главную