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