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

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

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

Однако здесь возникает техническая дилемма. Чтобы рассчитать значение за первый отчетный месяц (например, январь 2020 года), системе обязательно требуются данные за предыдущий месяц (декабрь 2019 года). Если мы просто ограничим период в запросе январем, то расчет за первый месяц окажется пустым или неверным. Нам приходится выбирать данные за декабрь, но выводить эту «техническую» колонку пользователю в отчет нельзя. В этой статье мы подробно разберем, как скрыть ненужный начальный период, сохранив точность всех вычислений.

Причина проблемы: почему стандартный отбор ломает отчет

Если мы установим обычный отбор по периоду в параметрах запроса или на вкладке «Отбор» общих настроек СКД, система применит его на уровне базы данных. В результате СУБД вернет строки начиная только с января 2020 года. Функция ВычислитьВыражение не сможет обратиться к историческим данным за декабрь 2019 года, и показатель оборота за январь будет рассчитан неверно.

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

Способ 1. Отбор на уровне группировки с применением «После группировки или для иерархии»

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

Выполним настройку этого механизма по шагам:

  1. Перейдем на вкладку Настройки в конструкторе СКД.
  2. В структуре отчета найдем группировку колонок по полю Период (или Месяц).
  3. Выделим эту группировку и в нижней части окна настроек перейдем на вкладку Отбор. Обратите внимание: отбор нужно ставить не для всего отчета, а конкретно для выбранной группировки колонок!
  4. Добавим новое условие отбора, например: Период Больше или равно &ДатаНачалаОтчета.
  5. Нажмем правой кнопкой мыши на добавленное свойство отбора и найдем пункт Режим отображения / Применение отбора (в зависимости от версии платформы). Нам необходимо установить свойство применения в значение После группировки или для иерархии.

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

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

Способ 2. Перенос расчета на уровень базы данных (Self-Join в запросе)

Если вы хотите избежать сложных настроек СКД и сделать отчет максимально надежным и быстрым, лучшим решением будет перенос расчета разницы показаний непосредственно в текст SQL-запроса. Это избавит нас от необходимости использовать ВычислитьВыражение и загружать лишние периоды в компоновку.

Для реализации этого подхода мы можем использовать левое соединение таблицы самой с собой со смещением периода на один шаг назад. Рассмотрим пример текста запроса:


ВЫБРАТЬ
    ТекущиеПоказания.Период КАК Период,
    ТекущиеПоказания.Счетчик КАК Счетчик,
    ТекущиеПоказания.Показание КАК ПоказаниеТекущее,
    ЕСТЬNULL(ПредыдущиеПоказания.Показание, 0) КАК ПоказаниеПредыдущее,
    ТекущиеПоказания.Показание - ЕСТЬNULL(ПредыдущиеПоказания.Показание, 0) КАК Оборот
ИЗ
    РегистрСведений.ПоказанияСчетчиков КАК ТекущиеПоказания
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПоказанияСчетчиков КАК ПредыдущиеПоказания
        ПО ТекущиеПоказания.Счетчик = ПредыдущиеПоказания.Счетчик
        И ПредыдущиеПоказания.Период = ДОБАВИТЬКДАТЕ(ТекущиеПоказания.Период, МЕСЯЦ, -1)
ГДЕ
    ТекущиеПоказания.Период МЕЖДУ &ДатаНачала И &ДатаКонца

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

Способ 3. Визуальное скрытие через Условное оформление (Ширина = 0)

Еще один практичный вариант решения проблемы — использование условного оформления компоновки данных. Этот способ хорош тем, что колонка физически присутствует в расчетах, но визуально сжимается до нулевого размера.

Рассмотрим алгоритм настройки условного оформления:

  1. В настройках СКД перейдем на вкладку Условное оформление.
  2. Добавим новый элемент оформления.
  3. В поле Оформление установим два параметра:
    • Максимальная ширина = 0 (в некоторых старых релизах платформы стабильнее работает значение 0.1 или -0.1).
    • Текст = "" (пустая строка — это предотвратит некрасивые переносы букв заголовка в сжатой колонке).
  4. В поле Условие зададим отбор для скрываемого периода, например: Период Меньше &ДатаНачалаОтчета.
  5. В поле Оформляемые поля укажем наше поле группировки — Период.

Данный метод чрезвычайно прост в реализации, однако имеет один весомый минус: при выгрузке отчета в форматы Excel (XLSX) или HTML скрытая колонка останется в структуре файла. Пользователь сможет легко увидеть ее, просто растянув границы ячеек мышкой.

Способ 4. Программное скрытие колонки в модуле отчета

Если ваш отчет имеет сложную структуру или выводится через собственную форму, вы можете управлять видимостью колонок программно в модуле объекта отчета, перехватив процедуру ПриКомпоновкеРезультата. Вы можете полностью сгенерировать табличный документ, найти область с заголовком технического периода и скрыть ее.

Рассмотрим пример кода, реализующий этот подход:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    // Компонуем результат в ТабличныйДокумент штатным процессором вывода
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.ПолучитьНастройки(), ДанныеРасшифровки);
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
    // Программный поиск и скрытие колонки в результирующем документе
    ТехническаяДата = НачалоМесяца(ДобавитьМесяц(КомпоновщикНастроек.Настройки.ПараметрыДанных.Найти("ДатаНачала").Значение, -1));
    ТекстДляПоиска = Формат(ТехническаяДата, "ДФ='ММММ гггг'");
    
    НайденнаяОбласть = ДокументРезультат.НайтиТекст(ТекстДляПоиска, , , Истина, Истина);
    Если НайденнаяОбласть <> Неопределено Тогда
        НомерКолонки = НайденнаяОбласть.Лево;
        // Устанавливаем свойство видимости для всей колонки
        ДокументРезультат.Область(, НомерКолонки, , НомерКолонки).Видимость = Ложь;
    КонецЕсли;
    
КонецПроцедуры

Этот метод гарантирует стопроцентный результат и корректность расчетов. СКД выполняет компоновку данных в полном объеме, а на выходе мы аккуратно скрываем ненужную колонку из поля зрения пользователя. Данный подход отлично подходит для создания сложных корпоративных отчетов.

Резюме и рекомендации

Мы проанализировали четыре способа решения проблемы. Выбор конкретного метода зависит от архитектуры вашего решения:

← На главную