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