Как разбить период в отчете СКД на подпериоды (месяцы и недели) с иерархическими заголовками колонок?

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

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

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

Подготовка данных в запросе СКД

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

Рассмотрим пример запроса (для отладки которого удобно использовать управляемую консоль запросов), который извлекает данные и формирует необходимые поля для группировки:


ВЫБРАТЬ
    ТаблицаДанных.Дата AS Дата,
    НАЧАЛОПЕРИОДА(ТаблицаДанных.Дата, МЕСЯЦ) КАК Месяц,
    НАЧАЛОПЕРИОДА(ТаблицаДанных.Дата, НЕДЕЛЯ) КАК Неделя,
    ТаблицаДанных.Сумма КАК Сумма
ИЗ
    ВашаТаблица AS ТаблицаДанных

В этом запросе (где может пригодиться bm Консоль запросов) мы выполняем следующие действия:

  1. Выбираем исходную дату (Дата) и некий числовой показатель (Сумма) из таблицы данных (в отладке поможет Консоль запросов УФ).
  2. Используем функцию НАЧАЛОПЕРИОДА для получения начальной даты месяца (Месяц) и начальной даты недели (Неделя) из исходной даты. Эти поля будут служить основой для наших группировок.

Также может быть полезно добавить вычисляемые поля в СКД для более удобного отображения дат в заголовках. Например, для поля Месяц мы можем использовать формат "Январь 2022 г.", а для поля Неделя – "01.01 - 07.01". Это можно сделать как в запросе, так и через вычисляемые поля на закладке "Вычисляемые поля" в настройках СКД.

Пример использования вычисляемых полей в СКД (не в запросе):

Именно эти "Представления" мы будем использовать для вывода в заголовках колонок, чтобы информация была максимально читаемой для пользователя.

Настройка структуры отчета в СКД (закладка "Настройки")

После подготовки данных в запросе мы переходим к настройке структуры отчета на закладке "Настройки" в СКД.

  1. Создадим новую группировку в области "Колонки". Назовем ее, например, "МесяцГруппировка" и в качестве поля выберем наше поле Месяц (или ПредставлениеМесяца, если мы его создали).
  2. В эту группировку "МесяцГруппировка" мы вложим подчиненную группировку. Создадим ее, назовем "НеделяГруппировка" и в качестве поля выберем Неделя (или ПредставлениеНедели).

На данном этапе, если мы сформируем отчет, скорее всего, мы получим результат, похожий на "Январь | 02.05.2022 | 09.05.2022 | ...", как было описано в сообщении 13, или "Январь | Январь | Январь | ...", как в сообщении 19, что не соответствует желаемому объединенному заголовку. Чтобы добиться нужного визуального представления, нам потребуется использовать макеты СКД.

Использование макетов группировок для достижения иерархии заголовков

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

Рассмотрим пошагово, как создать макет для нашей группировки "Месяц", чтобы она объединяла заголовок над неделями:

  1. Переходим на закладку "Макеты" в настройках СКД.
  2. Создаем новый макет. Нажимаем кнопку "Добавить" (зеленый плюсик) и в появившемся окне "Редактирование макета" устанавливаем следующие параметры:
    • Тип макета: Выбираем "Заголовок группировки". Это важно, так как нам нужно изменить именно заголовок.
    • Область использования: "Колонка". Мы работаем с группировками в колонках.
    • Группировка: Выбираем нашу группировку "МесяцГруппировка".
    • Поле: Выбираем поле, по которому идет группировка, то есть Месяц (или ПредставлениеМесяца).

    После установки этих параметров нажимаем "Далее".

  3. Открывается табличный документ для редактирования макета. — для этой задачи отлично подойдёт визуальный редактор макетов табличных документов. Это графический редактор, в котором мы будем "рисовать" наш заголовок.
    • Объединяем ячейки: Выделяем несколько ячеек в первой строке макета (например, от A1 до C1, или столько, сколько вы ожидаете увидеть недель под одним месяцем, хотя точное количество не всегда известно заранее, СКД сама "растянет" макет, если он правильно настроен). Нажимаем правую кнопку мыши и выбираем "Объединить". Это создаст одну большую ячейку для заголовка месяца.
    • Вставляем параметр: В объединенную ячейку необходимо вставить текст, который будет представлять значение нашей группировки (месяца). Делаем это с помощью параметра. Нажимаем правую кнопку мыши на объединенной ячейке, выбираем "Параметры", затем "Поля группировки" и выбираем поле Месяц (или ПредставлениеМесяца). В ячейке появится текст вроде [Месяц].
    • Настройка внешнего вида: Вы можете применить форматирование (жирный шрифт, выравнивание по центру) к этой ячейке через панель инструментов.
    • Растягивание по горизонтали: Важным моментом является то, что СКД должна понимать, что этот заголовок месяца должен "растягиваться" над всеми колонками дочерней группировки (недель). Обычно, если макет создан для заголовка группировки колонки, СКД автоматически старается его растянуть. Если нет, иногда требуется использовать параметр "Растягивать по горизонтали" в свойствах области макета (вызывается из контекстного меню по правой кнопке мыши на самой области).
  4. Сохраняем макет.

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

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

Альтернативный подход: Программная постобработка табличного документа

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

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

Рассмотрим общую логику и примерный скелет кода для такой постобработки:

  1. Переопределяем обработчик события ПриКомпоновкеРезультата. В модуле формы отчета нам необходимо создать (или переопределить) процедуру с таким именем.
    
    Процедура ПриКомпоновкеРезультата(ДокументРезультат, Отчет, ДанныеРасшифровки)
        // Здесь будет наш код постобработки
    КонецПроцедуры
    

    Параметр ДокументРезультат – это наш сформированный табличный документ, с которым мы будем работать.

  2. Идентификация строк заголовков. Самая сложная часть – это программно определить, в каких строках табличного документа находятся заголовки месяцев и заголовки недель. Это может быть сделано несколькими способами:
    • Поиск по тексту ячеек (например, "Январь 2022 г.").
    • Предположение о фиксированных номерах строк, если структура отчета достаточно стабильна (что редко бывает).
    • Использование ДанныеРасшифровки для получения более детальной информации о структуре вывода, хотя это также может быть нетривиально.
  3. Обход и объединение ячеек. После того как мы определили нужные строки, мы можем итерироваться по ним.

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

    
    // Примерный скелет кода в процедуре ПриКомпоновкеРезультата()
    // Этот код сильно упрощен и требует адаптации под конкретный отчет
    
    Перем НомерСтрокиЗаголовковМесяцев;
    // Здесь нужно определить реальный номер строки, где СКД вывела заголовки месяцев.
    // Это может быть 3, 4 или другая строка, в зависимости от других группировок.
    // Допустим, мы знаем, что месяцы находятся в 3-й строке табличного документа.
    НомерСтрокиЗаголовковМесяцев = 3; 
    
    Если ДокументРезультат.Области.Количество() > 0 Тогда
        // Проходим по всей ширине табличного документа в строке с месяцами
        Перем ТекущаяКолонка = 1;
        Пока ТекущаяКолонка <= ДокументРезультат.ШиринаТаблицы Цикл
            Перем ТекстМесяца = ДокументРезультат.Область(НомерСтрокиЗаголовковМесяцев, ТекущаяКолонка).Текст;
            Если Не ПустаяСтрока(ТекстМесяца) Тогда // Если это не пустая ячейка
                Перем КолонкаКонцаМесяца = ТекущаяКолонка;
                // Ищем все соседние ячейки в той же строке, которые содержат тот же текст месяца
                Пока КолонкаКонцаМесяца + 1 <= ДокументРезультат.ШиринаТаблицы 
                      И ДокументРезультат.Область(НомерСтрокиЗаголовковМесяцев, КолонкаКонцаМесяца + 1).Текст = ТекстМесяца
                Цикл
                    КолонкаКонцаМесяца = КолонкаКонцаМесяца + 1;
                КонецЦикла;
    
                // Если мы нашли более одной ячейки с одинаковым текстом, объединяем их
                Если КолонкаКонцаМесяца > ТекущаяКолонка Тогда
                    ДокументРезультат.ОбъединитьЯчейки(НомерСтрокиЗаголовковМесяцев, ТекущаяКолонка, НомерСтрокиЗаголовковМесяцев, КолонкаКонцаМесяца);
                КонецЕсли;
                // Для корректного отображения, возможно, потребуется установить выравнивание по центру
                ДокументРезультат.Область(НомерСтрокиЗаголовковМесяцев, ТекущаяКолонка).ГоризонтальноеПоложение = ГоризонтальноеПоложение.Центр;
            КонецЕсли;
            // Переходим к следующей необъединенной ячейке
            ТекущаяКолонка = КолонкаКонцаМесяца + 1;
        КонецЦикла;
    КонецЕсли;
    

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

Дополнительные настройки и советы

  1. Сортировка колонок: Если недели или месяцы отображаются не в хронологическом порядке, убедитесь, что в настройках СКД на закладке "Порядок" для полей Месяц и Неделя (или их вычисляемых аналогов) установлена соответствующая сортировка (по возрастанию).
  2. "Плюсики" (сворачивание/разворачивание): Запрос на "плюсики" для сворачивания/разворачивания колонок в шапке (как в сообщении 14) является распространенным. К сожалению, стандартная функциональность СКД предоставляет сворачивание/разворачивание иерархических группировок для *строк* отчета, но не для *колонок* в виде "плюсиков" в шапке, которые работают интерактивно. Для колонок иерархия просто отображается. Если такая интерактивность критична, это, скорее всего, потребует глубокой программной доработки, возможно, даже с использованием активных элементов табличного документа, что выходит за рамки типовых средств СКД.
  3. Использование стандартного параметра "Период": Если вы хотите предоставить пользователю возможность удобно выбирать диапазон дат и детализацию, вы можете использовать стандартный параметр СКД "Период" с типом "СтандартныйПериод". СКД автоматически адаптирует группировки в зависимости от выбранного периода (например, если выбран месяц, она покажет недели; если год — месяцы). Однако, это не всегда гарантирует идеальное форматирование заголовков, и все равно может потребоваться донастройка макетов.

Заключение

Задача разбиения периода на подпериоды в колонках отчета СКД с иерархическим представлением заголовков (месяц над неделями) является одной из более сложных задач форматирования в СКД. Мы выяснили, что наиболее предпочтительным и устойчивым способом решения является использование макетов группировок. Они позволяют нам явно определить, как должен выглядеть заголовок родительской группировки, чтобы он объединял ячейки над своими дочерними элементами.

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

← На главную