Как настроить несколько условий отбора для одного поля в Построителе отчета?

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

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

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

Давайте проанализируем ситуацию. Предположим, у нас есть иерархия номенклатуры, и нам нужно выгрузить группу «Бумага», но исключить из выгрузки позицию «Аленушка». В терминах запроса это выглядит как:

ГДЕ Номенклатура В ИЕРАРХИИ(&ГруппаБумага) И Номенклатура НЕ РАВНО (&ТоварИсключение)

Стандартная форма настройки ПостроителяОтчета, как правило, ориентирована на работу с уникальными полями. Когда пользователь выбирает поле в списке доступных отборов, оно переносится в рабочую область. Повторный выбор того же поля в интерфейсе часто не приводит к созданию новой строки, что и создает иллюзию невозможности наложения «двойного» фильтра. Это ограничение визуальной оболочки, а не самого программного объекта ПостроительОтчета.

Способ 1: Программное добавление условий в коллекцию Отбор

Рассмотрим ситуацию с точки зрения кода. Объект ПостроительОтчета содержит коллекцию Отбор. Каждый элемент этой коллекции представляет собой отдельное условие. Важно понимать, что программно мы не ограничены в количестве добавлений одного и того же поля. Рассмотрим пример кода, который решает задачу автора темы:


// Создаем объект ПостроительОтчета
Построитель = Новый ПостроительОтчета;
Построитель.Текст = 
"ВЫБРАТЬ
|   Номенклатура.Ссылка КАК Номенклатура
|ИЗ
|   Справочник.Номенклатура КАК Номенклатура";

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

// Добавляем первое условие: Номенклатура в списке (или иерархии)
НовыйОтбор1 = Построитель.Отбор.Добавить("Номенклатура");
НовыйОтбор1.Использование = Истина;
НовыйОтбор1.ВидСравнения = ВидСравнения.ВИерархии;
НовыйОтбор1.Значение = ГруппаБумага;

// Добавляем второе условие на ТО ЖЕ САМОЕ ПОЛЕ: Номенклатура не в списке
НовыйОтбор2 = Построитель.Отбор.Добавить("Номенклатура");
НовыйОтбор2.Использование = Истина;
НовыйОтбор2.ВидСравнения = ВидСравнения.НеВСписке;
НовыйОтбор2.Значение = СписокИсключений;

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

В данном примере мы дважды вызвали метод Добавить("Номенклатура"). Построитель отчета корректно обработает это и создаст в итоговом SQL-запросе секцию ГДЕ, в которой оба условия будут объединены логическим оператором И. Это критически важный момент: в ПостроителеОтчета (в отличие от современной СКД) все строки отбора всегда соединяются по «И».

Особенности реализации в типовых обменах

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


ЭлементОтбора = ПостроительОтчета.Отбор.Найти("Номенклатура");
Если ЭлементОтбора <> Неопределено Тогда
    // Какая-то логика обработки
КонецЕсли;

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


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

Способ 2: Использование предварительно подготовленного списка значений

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

Алгоритм действий будет следующим:

  1. Выполняем отдельный вспомогательный запрос, который выбирает все нужные товары из группы «Бумага», исключая «Аленушку».
  2. Выгружаем результат этого запроса в СписокЗначений.
  3. В ПостроительОтчета передаем только ОДНО условие: Номенклатура В Списке, где значением является наш подготовленный список.

Этот подход более универсален, так как позволяет реализовать сколь угодно сложную логику (включая условия «ИЛИ»), которую ПостроительОтчета в чистом виде не поддерживает.

Различия между Построителем отчета и СКД

Как справедливо отмечено в сообщениях форума, ПостроительОтчета является «прародителем» Системы компоновки данных (СКД). Однако у них есть существенные различия в работе с группами условий:

Поэтому, если вам требуется условие «Номенклатура из Группы А ИЛИ Номенклатура из Группы Б», вам придется либо использовать ВидСравнения.ВСпискеСГруппами, либо прибегать к предварительному формированию списка значений, описанному выше.

Резюме для реализации

Чтобы успешно использовать множественные варианты отбора для одного поля в ПостроителеОтчета, придерживайтесь следующих правил:

  1. Не полагайтесь на стандартный диалог настройки, если он ограничивает добавление дублей. Используйте программное заполнение коллекции Отбор.
  2. Используйте метод Добавить() вместо прямого обращения к свойствам коллекции, чтобы создать несколько экземпляров условий.
  3. Проверьте обработчик результата: убедитесь, что код, считывающий настройки построителя, обходит всю коллекцию в цикле, а не ищет элемент по имени поля.
  4. Помните о логике «И»: все добавленные строки будут сужать выборку. Если вам нужно расширить выборку (логика «ИЛИ»), используйте виды сравнения «В списке» с заранее подготовленным набором данных.

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

← На главную