Почему не работает программно добавленный отбор в отчете 1С и как правильно его настроить?

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

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

Причина неработоспособности программного отбора

Проанализируем типовую ошибку, возникающую при попытке добавить отбор:


Реквизит.ДоступныеПоля.Добавить("Ссылка", Истина);
Реквизит.Текст =
    "ВЫБРАТЬ
    |    Контрагенты.Ссылка КАК Контрагенты
    |ИЗ
    |    Справочник.Контрагенты КАК Контрагенты
    |{ГДЕ
    |    Контрагенты.Ссылка}";
Реквизит.ЗаполнитьНастройки();
Реквизит.Отбор.Добавить("Ссылка", "Контрагенты", "Контрагенты");

Выясним основные причины, из-за которых этот код не работает:

  1. Сброс настроек методом ЗаполнитьНастройки(): метод ЗаполнитьНастройки() заново инициализирует коллекцию доступных полей и отборов на основе текста запроса. Если вызывать ДоступныеПоля.Добавить() до вызова ЗаполнитьНастройки(), добавленные вручную поля стираются. Добавление элементов в коллекцию Отбор должно выполняться строго после заполнения настроек.
  2. Отсутствие связи Построителя с основным кодом отчета: создание реквизита на форме и настройка в нем полей отбора лишь формируют интерфейсные элементы. Если сам алгоритм формирования отчета использует отдельный объект Запрос и собственный макет, настройки из объекта ПостроительОтчета в него автоматически не попадают.
  3. Использование фигурных скобок без построителя: конструкции вида {ГДЕ ...} предназначены исключительно для механизма построителя (или СКД). Обычный Запрос 1С игнорирует текст внутри фигурных скобок.

Вариант 1. Исключение элементов через обычный параметр запроса (без Построителя)

Если отчет формируется классическим кодом через объект Запрос, проще и надежнее всего отказаться от использования сложного механизма построителя отчета и применить передачу списка исключений через параметр.

Рассмотрим пошаговую реализацию:

  1. Добавим на форму реквизит ИсключаемыеКонтрагенты с типом СписокЗначений (тип значений элементов — СправочникСсылка.Контрагенты) и разместим его на форме для интерактивного выбора пользователем.
  2. В тексте основного запроса отчета добавим условие с отрицанием:

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

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

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

Важный момент: если пользователь оставит список ИсключаемыеКонтрагенты пустым, условие В (&ИсключаемыеКонтрагенты) вернет Ложь, а отрицание НЕ превратит его в Истина. Запрос корректно отберет всех контрагентов без возникновения синтаксических ошибок.

Вариант 2. Правильная интеграция ПостроителяОтчета в алгоритм формирования

Если требуется использовать именно функционал динамического отбора через ПостроительОтчета, свяжем объект построителя с запросом отчета:


// 1. Инициализация построителя при открытии формы
Построитель = Новый ПостроительОтчета;
Построитель.Текст = 
    "ВЫБРАТЬ
    |    Контрагенты.Ссылка КАК Контрагент
    |ИЗ
    |    Справочник.Контрагенты КАК Контрагенты
    |{ГДЕ
    |    Контрагенты.Ссылка.* КАК Контрагент}";

Построитель.ЗаполнитьНастройки();

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

// Переносим параметры отборов из построителя в запрос
Для Каждого Параметр Из Построитель.Параметры Цикл
    ЗапросОтчета.УстановитьПараметр(Параметр.Ключ, Параметр.Значение);
КонецЦикла;

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

Вариант 3. Выбор контрагентов через Таблицу Значений для массовой рассылки

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

Разберем реализацию:

  1. Создадим на форме реквизит ТаблицаДолжников (тип ТаблицаЗначений) с колонками: Отправлять (тип Булево), Контрагент (тип СправочникСсылка.Контрагенты), Сумма (тип Число).
  2. После выполнения запроса заполняем таблицу на форме:

ТаблицаДолжников = Запрос.Выполнить().Выгрузить();
ТаблицаДолжников.Колонки.Добавить("Отправлять", Новый ОписаниеТипов("Булево"));

Для Каждого СтрокаТЗ Из ТаблицаДолжников Цикл
    СтрокаТЗ.Отправлять = Истина; // по умолчанию отправка включена для всех
КонецЦикла;
  1. В процедуре нажатия кнопки «Отправить всем» обходим только отмеченные строки:

Процедура ДействияФормыОтправитьВсем(Кнопка)
    Для Каждого Стр Из ТаблицаДолжников Цикл
        Если Стр.Отправлять Тогда
            // Выполняем формирование и отправку письма контрагенту Стр.Контрагент
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

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

← На главную