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