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