Как обработать неустановленный параметр в запросе СКД и избежать ошибки

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

При разработке отчетов на базе Системы компоновки данных (СКД) в 1С программисты часто сталкиваются с неприятной ошибкой: «Не установлен параметр запроса». Эта проблема возникает, когда параметр используется непосредственно внутри логических выражений запроса (например, в конструкции ВЫБОР КОГДА &Параметр ТОГДА ...), а пользователь на форме отчета снимает галочку использования этого параметра.

В отличие от стандартных отборов в секции ГДЕ, которые СКД может автоматически исключить из результирующего SQL-запроса, жестко прописанные в логике выбора параметры исключить невозможно. В этой статье мы подробно разберем, почему возникает эта ошибка, и рассмотрим четыре эффективных способа ее решения.

Выясняем причину: почему стандартные фигурные скобки не всегда помогают?

Расширение языка запросов СКД позволяет использовать фигурные скобки {} для указания необязательных условий. Например, конструкция ГДЕ {Номенклатура = &Номенклатура} прекрасно работает: если пользователь отключит параметр, СКД просто вырежет это условие из финального текста запроса.

Однако, если параметр участвует в вычисляемых полях или условных конструкциях в секции ВЫБОР, платформа 1С не может динамически изменить структуру выражения без нарушения синтаксиса SQL. Если параметр не передан, СУБД физически не может выполнить запрос, содержащий пустой маркер &Параметр. Выяснив причину проблемы, перейдем к механизмам ее обхода.


Способ 1. Метод «двух параметров» (полностью в конструкторе СКД)

Это самый изящный декларативный способ решения проблемы, который настраивается исключительно в схеме компоновки данных и не требует написания ни одной строчки программного кода.

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

Разберем настройку по шагам:

  1. Откроем схему компоновки данных и перейдем на вкладку Параметры.
  2. Создадим параметр &ПользовательскийПараметр. Именно его мы будем выводить в пользовательские настройки на форму. Для него установим флаг Использование в значение Авто (чтобы пользователь мог его включать и выключать).
  3. Создадим второй параметр — &ПараметрДляЗапроса. Его мы будем использовать непосредственно в тексте запроса (например: Выбор когда &ПараметрДляЗапроса Тогда 1 иначе 2 Конец).
  4. Для параметра &ПараметрДляЗапроса установим галочку Ограничение доступности (чтобы скрыть его от пользователя) и установим свойство Использование в значение Всегда.
  5. В поле Выражение для параметра &ПараметрДляЗапроса напишем формулу на языке выражений СКД:

Выбор Когда ЗначениеЗаполнено(&ПользовательскийПараметр) Тогда &ПользовательскийПараметр Иначе Ложь Конец

Вместо значения Ложь вы можете указать любое дефолтное значение, соответствующее вашему типу данных (например, 0, пустую строку или пустую ссылку).

Почему это работает: Поскольку параметр для запроса имеет признак обязательного использования, СКД гарантированно передаст его в СУБД. При этом его значение динамически вычислится на основе того, установлен ли пользовательский флаг.


Способ 2. Программная предобработка в модуле отчета

Если логика вашего отчета требует более сложных проверок или вы не хотите загромождать вкладку параметров СКД «дублирующими» строками, можно перехватить процесс компоновки программно в модуле объекта отчета.

Рассмотрим, как реализовать предобработку в процедуре ПриКомпоновкеРезультата. Нам нужно принудительно включить использование параметра и присвоить ему дефолтное значение, если пользователь снял флажок.

Посмотрим на пример кода:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    // Отключаем стандартный вывод, чтобы управлять процессом вручную
    СтандартнаяОбработка = Ложь;
    
    // Получаем доступ к настройкам компоновщика
    ПараметрыНастроек = КомпоновщикНастроек.Настройки.ПараметрыДанных;
    ПараметрДанных = ПараметрыНастроек.Элементы.Найти("ИмяВашегоПараметра");
    
    // Проверяем, отключен ли параметр пользователем
    Если ПараметрДанных <> Неопределено И НЕ ПараметрДанных.Использование Тогда
        // Насильно включаем параметр и задаем значение по умолчанию
        ПараметрДанных.Использование = Истина;
        ПараметрДанных.Значение = Ложь; // Или любое другое дефолтное значение
    КонецЕсли;
    
    // То же самое необходимо сделать для пользовательских настроек (актуально для Управляемых Форм)
    ПараметрыПользовательские = КомпоновщикНастроек.ПользовательскиеНастройки.ПараметрыДанных;
    ПараметрПольз = ПараметрыПользовательские.Элементы.Найти("ИмяВашегоПараметра");
    Если ПараметрПольз <> Неопределено И НЕ ПараметрПольз.Использование Тогда
        ПараметрПольз.Использование = Истина;
        ПараметрПольз.Значение = Ложь;
    КонецЕсли;
    
    // Выполняем стандартный вывод отчета программным путем
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.Настройки, ДанныеРасшифровки);
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
КонецПроцедуры

Этот способ надежно защищает отчет от падения и позволяет выполнять тонкую настройку значений "на лету" перед формированием отчета.


Способ 3. Обход для параметров типа «Список значений»

Ситуация усложняется, когда параметр представляет собой массив или список значений (например, отбор по списку складов или контрагентов). Если пользователь отключает такой параметр, простая проверка через ЗначениеЗаполнено() в конструкторе СКД может отработать некорректно.

Для таких случаев в тексте SQL-запроса можно применить изящный прием с использованием виртуальной выборки и подзапроса:


ГДЕ (Номенклатура В (&СписокНоменклатуры) 
    ИЛИ НЕ 1 В (ВЫБРАТЬ ПЕРВЫЕ 1 1 ИЗ Справочник.Номенклатура ГДЕ Номенклатура.Ссылка В (&СписокНоменклатуры)))

Проанализируем логику этого условия:

  1. Для параметра &СписокНоменклатуры в СКД обязательно устанавливается свойство Использование = Всегда.
  2. Если пользователь не заполнил список, то подзапрос ВЫБРАТЬ ПЕРВЫЕ 1... вернет пустой результат.
  3. Условие НЕ 1 В (ПустойРезультат) вернет истину (Истина), и система выберет все элементы справочника без ограничений, предотвратив ошибку пустого параметра.

Способ 4. Использование фигурных скобок в полях выбора (SELECT)

Малоизвестный, но эффективный факт: расширение языка запросов СКД позволяет применять фигурные скобки не только в секции ГДЕ, но и непосредственно в списке полей выборки.

Посмотрим на пример такого синтаксиса:


ВЫБРАТЬ
    Ссылка КАК Номенклатура,
    {&Параметр КАК МоеНеобязательноеПоле}
ИЗ
    Справочник.Номенклатура

Если пользователь отключает параметр &Параметр в интерфейсе, СКД при генерации итогового SQL-запроса просто «вырежет» это поле из списка выборки. Однако помните, что данный способ подходит только тогда, когда поле выводится независимо. Если значение должно участвовать в математических или логических расчетах внутри запроса, используйте Способ 1.

Резюме

Мы рассмотрели различные варианты обхода ошибки незаполненного параметра в СКД 1С. Для простых логических условий в запросе идеальным выбором станет Метод двух параметров (Способ 1), так как он не требует кодинга и полностью поддерживается платформой на декларативном уровне. Для сложных отборов используйте программную предобработку или специализированные конструкции обхода списков.

← На главную