Почему при отключении отбора по периоду в отчете СКД пропадают все данные и как это исправить?

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

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

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

Суть проблемы: что происходит «под капотом»?

Давайте проанализируем, как мыслит разработчик и как мыслит платформа 1С.

Логика человека: «Я убрал галочку с параметра периода. Это значит, что фильтр должен отключиться, и программа покажет мне все записи из базы».

Логика платформы: Когда галочка использования параметра снята, параметр становится недоступным для пользователя, но он не исчезает из текста запроса, если он там жестко прописан. В этот момент платформе нужно передать какое-то значение в параметры &ДатаНачала и &ДатаОкончания. Поскольку значение не задано, передается «пустая дата» — 01.01.0001 00:00:00.

Если ваш запрос выглядит следующим образом:


ВЫБРАТЬ
    Документ.Ссылка,
    Документ.Дата
ИЗ
    Документ.РеализацияТоваровУслуг КАК Документ
ГДЕ
    Документ.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания

То при снятой галочке платформа фактически выполняет такой запрос:


ГДЕ Документ.Дата МЕЖДУ ДАТАВРЕМЯ(1,1,1) И ДАТАВРЕМЯ(1,1,1)

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

Способ №1. Использование расширения языка запросов (Фигурные скобки)

Это наиболее правильный, «каноничный» способ работы с необязательными условиями в СКД. Язык запросов в компоновке данных имеет специальный синтаксис — фигурные скобки {}.

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

Рассмотрим, как нужно изменить текст запроса.

Для условия в секции ГДЕ

Вместо жесткого условия:


ГДЕ
    Обороты.Период МЕЖДУ &ДатаНачала и &ДатаОкончания

Мы должны написать:


{ГДЕ
    Обороты.Период МЕЖДУ &ДатаНачала и &ДатаОкончания}

Теперь, если пользователь снимет галочку с периода, СКД полностью удалит секцию ГДЕ из запроса перед отправкой в СУБД SQL, и будут выбраны все записи.

Обратите внимание: если внутри фигурных скобок нужно перечислить несколько полей для отбора, используется запятая, которая работает как логическое «И».

Для параметров виртуальных таблиц

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

Неправильно (для необязательного периода):


ИЗ
    РегистрНакопления.Продажи.Обороты(&ДатаНачала, &ДатаОкончания, , ) КАК ПродажиОбороты

Правильно:


ИЗ
    РегистрНакопления.Продажи.Обороты({&ДатаНачала}, {&ДатаОкончания}, , ) КАК ПродажиОбороты

В этом случае, если даты не заданы, параметры виртуальной таблицы останутся пустыми, и регистр вернет обороты за всё время существования базы.

Способ №2. Явная логика в запросе (Работа с пустой датой)

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

Идея заключается в том, чтобы прямо в запросе сказать: «Если дата начала пустая, то условие считается выполненным, иначе проверяем реальную дату».

Давайте посмотрим, как это выглядит в коде:


ГДЕ 
    (&ДатаНачала = ДАТАВРЕМЯ(1,1,1) ИЛИ Документ.Дата >= &ДатаНачала)
    И 
    (&ДатаОкончания = ДАТАВРЕМЯ(1,1,1) ИЛИ Документ.Дата <= &ДатаОкончания)

Также можно использовать функцию НачалоПериода и КонецПериода для подстраховки, если в параметры передаются даты со временем:


ГДЕ 
   (&ДатаНачала = ДАТАВРЕМЯ(1,1,1)
    Или ГрафикПлатежей.ДатаПлатежа >= НачалоПериода(&ДатаНачала, День))
   И (&ДатаКонца = ДАТАВРЕМЯ(1,1,1) 
    Или ГрафикПлатежей.ДатаПлатежа <= КонецПериода(&ДатаКонца, День))

Почему этот способ менее предпочтителен для СКД?

  1. Использование оператора ИЛИ в условиях соединения или фильтрации часто мешает оптимизатору СУБД использовать индексы, что может замедлить работу отчета на больших объемах данных.
  2. Текст запроса становится более громоздким и сложным для чтения.

Однако этот метод надежен и работает всегда, независимо от специфичных настроек компоновщика.

Настройка параметров: «Фокус с галочками»

Чтобы все вышеописанное работало идеально при использовании СтандартногоПериода, давайте проверим правильность настройки вкладки «Параметры» в схеме компоновки данных. Это частая причина ошибок.

Предположим, у нас есть три параметра:

Пошаговая настройка:

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

Как это работает вместе с фигурными скобками?

Когда пользователь снимает галочку с параметра Период, значение этого параметра становится Неопределено. Соответственно, выражения &Период.ДатаНачала не могут быть вычислены корректно. Компоновщик видит, что связанные параметры не заданы. Если в запросе вы использовали фигурные скобки {&ДатаНачала}, СКД понимает: «Параметр не задан пользователем, значит, нужно исключить этот отбор».

Резюме

Чтобы ваш отчет корректно отрабатывал ситуацию «Период не выбран»:

  1. Используйте расширение языка запросов СКД: заключайте условия с параметрами в фигурные скобки {}.
  2. Для виртуальных таблиц передавайте параметры внутри фигурных скобок: .Обороты({&Начало}, {&Конец}).
  3. Если по каким-то причинам вы не можете использовать расширения СКД, прописывайте явную логику проверки на пустую дату ДАТАВРЕМЯ(1,1,1) через оператор ИЛИ.

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

← На главную