Как правильно реализовать условие на пустую дату и обработать необязательные параметры в СКД

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

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

Анализ проблемы: почему возникает ошибка «Не задано значение параметра»

Рассмотрим ситуацию, описанную в теме. Автор пытается использовать конструкцию вида:


И (ВЫБОР
    КОГДА &НачалоПериода <> ДАТАВРЕМЯ(1, 1, 1)
        ТОГДА &НачалоПериода <= КП.Дата
    ИНАЧЕ ИСТИНА
КОНЕЦ)

На первый взгляд логика верна: мы проверяем, не является ли дата пустой (01.01.0001). Но при исполнении система выдает ошибку. Проанализируем причину. В СКД каждый параметр имеет флаг «Использование». Если пользователь в настройках отчета (на вкладке «Параметры» или в пользовательских настройках) снимает галочку с параметра &НачалоПериода, то для СКД этого параметра больше не существует в контексте выполнения текущего запроса.

Когда генератор запросов встречает прямое обращение к &НачалоПериода (вне специальных операторов), он пытается подставить туда значение. Если параметр «выключен», подставлять нечего, и выполнение прерывается с ошибкой. Таким образом, нужно различать два состояния: параметр не используется (выключен флаг) и параметр пуст (флаг стоит, но значение — пустая дата).

Решение 1: Настройка флагов использования и запрета незаполненных значений

Самый простой способ избежать ошибки «в лоб» — убедиться, что параметр всегда доступен запросу. Разберем по шагам, как это настроить в конструкторе СКД:

  1. Перейдем на закладку Параметры.
  2. Найдем наш параметр НачалоПериода.
  3. Проверим колонку Использование. Для параметров, которые обязательно должны присутствовать в коде запроса, должно стоять значение «Всегда».
  4. Обратим внимание на флаг Запрет незаполненных значений. Если мы хотим позволить пользователю оставлять дату пустой, этот флаг должен быть снят.

Однако такой подход заставляет нас писать громоздкие условия ВЫБОР в самом тексте запроса, что снижает читаемость и может негативно сказаться на производительности (плане запроса СУБД). Рассмотрим более профессиональные методы.

Решение 2: Использование расширения языка запросов (фигурные скобки)

Система компоновки данных обладает мощным механизмом — расширением языка запросов. Это специальные инструкции в фигурных скобках {}, которые подсказывают СКД, как модифицировать запрос в зависимости от настроек пользователя. Рассмотрим ситуацию, когда нам нужно наложить условие на дату только в том случае, если пользователь активировал этот параметр.

Вместо сложной логики ВЫБОР в секции ГДЕ или в условии соединения ПО, мы напишем следующее:


ГДЕ
    {КП.Дата >= &НачалоПериода, КП.Дата <= &ОкончаниеПериода}

Как это работает? Проанализируем поведение системы:

Это самый эффективный и «чистый» способ работы в СКД.

Решение 3: Обработка пустых дат через выражения параметров

Иногда нам принципиально нужно, чтобы параметр всегда участвовал в запросе, но мы хотим переопределить «пустую дату» на какое-то экстремальное значение (например, начало времен или конец времен), чтобы условие сравнения работало корректно. Выясним, как это сделать без изменения текста запроса.

На закладке Параметры в СКД есть колонка Выражение. Мы можем прописать там логику на языке выражений СКД:

Для параметра &НачалоПериода:

ВЫБОР КОГДА &НачалоПериода = ДАТАВРЕМЯ(1,1,1) ТОГДА ДАТАВРЕМЯ(1900,1,1) ИНАЧЕ &НачалоПериода КОНЕЦ

Для параметра &ОкончаниеПериода:

ВЫБОР КОГДА &ОкончаниеПериода = ДАТАВРЕМЯ(1,1,1) ТОГДА ДАТАВРЕМЯ(3999,12,31) ИНАЧЕ КонецПериода(&ОкончаниеПериода, "День") КОНЕЦ

В этом случае в тексте запроса можно будет использовать простейшее сравнение КП.Дата МЕЖДУ &НачалоПериода И &ОкончаниеПериода, и оно всегда будет отрабатывать логически верно, даже если пользователь не заполнил даты.

Решение 4: Применение типа «СтандартныйПериод»

Для удобства пользователя и разработчика рекомендуется использовать один параметр типа СтандартныйПериод вместо двух отдельных дат. Рассмотрим, как это упрощает жизнь:

  1. Создадим параметр ПериодОтчета с типом СтандартныйПериод.
  2. В параметрах запроса &НачалоПериода и &ОкончаниеПериода (которые используются в тексте запроса) в колонке «Выражение» укажем:
    • Для начала: &ПериодОтчета.ДатаНачала
    • Для окончания: &ПериодОтчета.ДатаОкончания
  3. Сами параметры начала и окончания сделаем Скрытыми (флаг «Ограничение доступности»).

Теперь пользователь выбирает период через удобный интерфейс (например, «Этот месяц»), а СКД сама корректно заполняет даты. Если период не выбран, даты будут пустыми, и здесь снова вступят в силу правила из Решения 2 или Решения 3.

Особенности условий в соединениях (JOIN)

Если условие на дату стоит в секции ПО при левом соединении таблиц, нужно быть особенно осторожным. Проанализируем ситуацию: если мы напишем ЛЕВОЕ СОЕДИНЕНИЕ ... ПО Т1.Ссылка = Т2.Ссылка И Т2.Дата >= &НачалоПериода, и параметр будет отключен, СКД может повести себя по-разному в зависимости от версии платформы.

Правильным подходом для соединений будет использование расширения компоновки данных непосредственно внутри секции ПО:


ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК КП
ПО ОсновнаяТаблица.Контрагент = КП.Ссылка
   {И КП.Дата >= &НачалоПериода}

Важный момент: если вы используете ВЫБОР КОГДА внутри условий запроса, помните замечание из сообщения №2 форума: логические операции вроде A > B не возвращают тип Булево, который можно было бы просто «вернуть» из ВЫБОР. В языке запросов 1С они могут находиться только в условиях ГДЕ, ПО или ИМЕЮЩИЕ. Внутри ВЫБОР вы обязаны явно возвращать значения: ТОГДА ИСТИНА ИНАЧЕ ЛОЖЬ.

Подводя итог, можно сказать, что лучшая практика для СКД — это максимальный отказ от ручного управления параметрами через ВЫБОР КОГДА в тексте запроса в пользу использования фигурных скобок и настройки выражений параметров. Это делает отчет надежным, а код запроса — понятным и оптимизированным.

← На главную