При разработке отчетов на схеме компоновки данных (СКД) мы часто сталкиваемся с необходимостью вычисления показателей, зависящих от предыдущих периодов. Яркий пример — расчет оборота счетчика как разности между текущим и предыдущим показаниями. Для реализации этой логики разработчики используют мощную функцию СКД ВычислитьВыражение.
Однако здесь возникает техническая дилемма. Чтобы рассчитать значение за первый отчетный месяц (например, январь 2020 года), системе обязательно требуются данные за предыдущий месяц (декабрь 2019 года). Если мы просто ограничим период в запросе январем, то расчет за первый месяц окажется пустым или неверным. Нам приходится выбирать данные за декабрь, но выводить эту «техническую» колонку пользователю в отчет нельзя. В этой статье мы подробно разберем, как скрыть ненужный начальный период, сохранив точность всех вычислений.
Если мы установим обычный отбор по периоду в параметрах запроса или на вкладке «Отбор» общих настроек СКД, система применит его на уровне базы данных. В результате СУБД вернет строки начиная только с января 2020 года. Функция ВычислитьВыражение не сможет обратиться к историческим данным за декабрь 2019 года, и показатель оборота за январь будет рассчитан неверно.
Наша задача — сделать так, чтобы СКД получила из базы данных информацию за декабрь 2019 года, выполнила все необходимые вычисления над ресурсами, а уже на этапе вывода в табличный документ визуально скрыла «лишнюю» колонку. Рассмотрим эффективные способы решения этой задачи.
Это классический и самый простой способ, предложенный в процессе обсуждения на форуме. Он позволяет отфильтровать колонки отчета уже после того, как СКД произвела все математические расчеты над ресурсами.
Выполним настройку этого механизма по шагам:
Период (или Месяц).Период Больше или равно &ДатаНачалаОтчета.Проанализируем, почему этот метод работает. При такой настройке СКД строит дерево данных в два этапа:
ВычислитьВыражение.Важное ограничение способа: Если ваш отчет интегрирован в типовую конфигурацию на базе БСП (Библиотека стандартных подсистем) и открывается в стандартной общей форме, пользователи не всегда могут легко управлять этим отбором. Настройка скрыта глубоко в меню «Еще» — «Изменить вариант». Кроме того, при сложных иерархических группировках этот режим может приводить к искажению общих итогов.
Если вы хотите избежать сложных настроек СКД и сделать отчет максимально надежным и быстрым, лучшим решением будет перенос расчета разницы показаний непосредственно в текст SQL-запроса. Это избавит нас от необходимости использовать ВычислитьВыражение и загружать лишние периоды в компоновку.
Для реализации этого подхода мы можем использовать левое соединение таблицы самой с собой со смещением периода на один шаг назад. Рассмотрим пример текста запроса:
ВЫБРАТЬ
ТекущиеПоказания.Период КАК Период,
ТекущиеПоказания.Счетчик КАК Счетчик,
ТекущиеПоказания.Показание КАК ПоказаниеТекущее,
ЕСТЬNULL(ПредыдущиеПоказания.Показание, 0) КАК ПоказаниеПредыдущее,
ТекущиеПоказания.Показание - ЕСТЬNULL(ПредыдущиеПоказания.Показание, 0) КАК Оборот
ИЗ
РегистрСведений.ПоказанияСчетчиков КАК ТекущиеПоказания
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПоказанияСчетчиков КАК ПредыдущиеПоказания
ПО ТекущиеПоказания.Счетчик = ПредыдущиеПоказания.Счетчик
И ПредыдущиеПоказания.Период = ДОБАВИТЬКДАТЕ(ТекущиеПоказания.Период, МЕСЯЦ, -1)
ГДЕ
ТекущиеПоказания.Период МЕЖДУ &ДатаНачала И &ДатаКонца
При таком подходе в СКД передаются строки только за выбранный пользователем период (например, с января 2020 года). Однако благодаря левому соединению у нас в каждой строке уже присутствует значение за декабрь 2019 года. Нам больше не нужно запрашивать «технический» месяц и пытаться скрыть его настройки группировок — отчет сразу формируется в нужном виде.
Еще один практичный вариант решения проблемы — использование условного оформления компоновки данных. Этот способ хорош тем, что колонка физически присутствует в расчетах, но визуально сжимается до нулевого размера.
Рассмотрим алгоритм настройки условного оформления:
Максимальная ширина = 0 (в некоторых старых релизах платформы стабильнее работает значение 0.1 или -0.1).Текст = "" (пустая строка — это предотвратит некрасивые переносы букв заголовка в сжатой колонке).Период Меньше &ДатаНачалаОтчета.Период.Данный метод чрезвычайно прост в реализации, однако имеет один весомый минус: при выгрузке отчета в форматы Excel (XLSX) или HTML скрытая колонка останется в структуре файла. Пользователь сможет легко увидеть ее, просто растянув границы ячеек мышкой.
Если ваш отчет имеет сложную структуру или выводится через собственную форму, вы можете управлять видимостью колонок программно в модуле объекта отчета, перехватив процедуру ПриКомпоновкеРезультата. Вы можете полностью сгенерировать табличный документ, найти область с заголовком технического периода и скрыть ее.
Рассмотрим пример кода, реализующий этот подход:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// Компонуем результат в ТабличныйДокумент штатным процессором вывода
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.ПолучитьНастройки(), ДанныеРасшифровки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
// Программный поиск и скрытие колонки в результирующем документе
ТехническаяДата = НачалоМесяца(ДобавитьМесяц(КомпоновщикНастроек.Настройки.ПараметрыДанных.Найти("ДатаНачала").Значение, -1));
ТекстДляПоиска = Формат(ТехническаяДата, "ДФ='ММММ гггг'");
НайденнаяОбласть = ДокументРезультат.НайтиТекст(ТекстДляПоиска, , , Истина, Истина);
Если НайденнаяОбласть <> Неопределено Тогда
НомерКолонки = НайденнаяОбласть.Лево;
// Устанавливаем свойство видимости для всей колонки
ДокументРезультат.Область(, НомерКолонки, , НомерКолонки).Видимость = Ложь;
КонецЕсли;
КонецПроцедуры
Этот метод гарантирует стопроцентный результат и корректность расчетов. СКД выполняет компоновку данных в полном объеме, а на выходе мы аккуратно скрываем ненужную колонку из поля зрения пользователя. Данный подход отлично подходит для создания сложных корпоративных отчетов.
Мы проанализировали четыре способа решения проблемы. Выбор конкретного метода зависит от архитектуры вашего решения: