При разработке отчетов в конфигурациях на обычных формах (таких как 1С:Управление производственным предприятием) разработчики часто сталкиваются с ситуацией: в коде формы создается реквизит типа ПостроительОтчета, настраиваются поля и отбор, однако при формировании отчета выбранные условия фильтрации никак не влияют на итоговый результат. Разберем по шагам, почему возникает эта ошибка и какие существуют надежные варианты реализации отборов.
Проанализируем типовую ошибку, возникающую при попытке добавить отбор:
Реквизит.ДоступныеПоля.Добавить("Ссылка", Истина);
Реквизит.Текст =
"ВЫБРАТЬ
| Контрагенты.Ссылка КАК Контрагенты
|ИЗ
| Справочник.Контрагенты КАК Контрагенты
|{ГДЕ
| Контрагенты.Ссылка}";
Реквизит.ЗаполнитьНастройки();
Реквизит.Отбор.Добавить("Ссылка", "Контрагенты", "Контрагенты");
Выясним основные причины, из-за которых этот код не работает:
ЗаполнитьНастройки(): метод ЗаполнитьНастройки() заново инициализирует коллекцию доступных полей и отборов на основе текста запроса. Если вызывать ДоступныеПоля.Добавить() до вызова ЗаполнитьНастройки(), добавленные вручную поля стираются. Добавление элементов в коллекцию Отбор должно выполняться строго после заполнения настроек.Запрос и собственный макет, настройки из объекта ПостроительОтчета в него автоматически не попадают.{ГДЕ ...} предназначены исключительно для механизма построителя (или СКД). Обычный Запрос 1С игнорирует текст внутри фигурных скобок.Если отчет формируется классическим кодом через объект Запрос, проще и надежнее всего отказаться от использования сложного механизма построителя отчета и применить передачу списка исключений через параметр.
Рассмотрим пошаговую реализацию:
ИсключаемыеКонтрагенты с типом СписокЗначений (тип значений элементов — СправочникСсылка.Контрагенты) и разместим его на форме для интерактивного выбора пользователем.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Взаиморасчеты.Контрагент КАК Контрагент,
| Взаиморасчеты.СуммаВзаиморасчетовОстаток КАК СуммаДолга
|ИЗ
| РегистрНакопления.ВзаиморасчетыСКонтрагентами.Остатки(&Период, ) КАК Взаиморасчеты
|ГДЕ
| НЕ (Взаиморасчеты.Контрагент В (&ИсключаемыеКонтрагенты))";
Запрос.УстановитьПараметр("Период", Период);
Запрос.УстановитьПараметр("ИсключаемыеКонтрагенты", ИсключаемыеКонтрагенты);
РезультатЗапроса = Запрос.Выполнить();
Важный момент: если пользователь оставит список ИсключаемыеКонтрагенты пустым, условие В (&ИсключаемыеКонтрагенты) вернет Ложь, а отрицание НЕ превратит его в Истина. Запрос корректно отберет всех контрагентов без возникновения синтаксических ошибок.
Если требуется использовать именно функционал динамического отбора через ПостроительОтчета, свяжем объект построителя с запросом отчета:
// 1. Инициализация построителя при открытии формы
Построитель = Новый ПостроительОтчета;
Построитель.Текст =
"ВЫБРАТЬ
| Контрагенты.Ссылка КАК Контрагент
|ИЗ
| Справочник.Контрагенты КАК Контрагенты
|{ГДЕ
| Контрагенты.Ссылка.* КАК Контрагент}";
Построитель.ЗаполнитьНастройки();
// 2. В процедуре формирования отчета получаем модифицированный текст запроса
ЗапросОтчета = Новый Запрос;
ЗапросОтчета.Текст = Построитель.ПолучитьТекстЗапроса();
// Переносим параметры отборов из построителя в запрос
Для Каждого Параметр Из Построитель.Параметры Цикл
ЗапросОтчета.УстановитьПараметр(Параметр.Ключ, Параметр.Значение);
КонецЦикла;
Результат = ЗапросОтчета.Выполнить();
Если задача отчета заключается в подготовке списка должников с возможностью отправки почтовых уведомлений по кнопке «Отправить всем», наиболее удобным решением для пользователя является управление списком через флажки в таблице на форме.
Разберем реализацию:
ТаблицаДолжников (тип ТаблицаЗначений) с колонками: Отправлять (тип Булево), Контрагент (тип СправочникСсылка.Контрагенты), Сумма (тип Число).
ТаблицаДолжников = Запрос.Выполнить().Выгрузить();
ТаблицаДолжников.Колонки.Добавить("Отправлять", Новый ОписаниеТипов("Булево"));
Для Каждого СтрокаТЗ Из ТаблицаДолжников Цикл
СтрокаТЗ.Отправлять = Истина; // по умолчанию отправка включена для всех
КонецЦикла;
Процедура ДействияФормыОтправитьВсем(Кнопка)
Для Каждого Стр Из ТаблицаДолжников Цикл
Если Стр.Отправлять Тогда
// Выполняем формирование и отправку письма контрагенту Стр.Контрагент
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Таким образом, отбор будет наглядно управляться пользователем непосредственно перед отправкой без необходимости усложнения логики построителя отчета.