Как программно сгруппировать колонки в отчете СКД?

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

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

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

Причина некорректной группировки

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

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

Чтобы группировка сработала корректно, нам нужно явно указать, к какой именно прямоугольной области табличного документа ее следует применить.

Решение 1: Группировка в готовом табличном документе

Этот способ основан на постобработке уже сформированного отчета в процедуре ПриКомпоновкеРезультата(). Суть метода — получить нужную область с помощью метода Область() и уже к ней применить Сгруппировать().

Синтаксис метода выглядит так:


ТабличныйДокумент.Область(НомерПервойСтроки, НомерПервойКолонки, НомерПоследнейСтроки, НомерПоследнейКолонки)

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

Посмотрим на пример кода в обработчике ПриКомпоновкеРезультата:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)

    СтандартнаяОбработка = Истина; // Выполняем стандартное формирование отчета

    // После того как отчет сформирован, ДокументРезультат заполнен.
    // Теперь мы можем его доработать.

    // Предположим, мы хотим сгруппировать колонки с 5-й по 7-ю.
    НомерПервойКолонкиДляГруппировки = 5;
    НомерПоследнейКолонкиДляГруппировки = 7;

    // Определяем, на какие строки будет действовать группировка.
    // Нам нужно начать с первой строки (или со строки шапки) и закончить последней.
    // Если этого не сделать, группировка может примениться только к одной строке.
    НомерПервойСтроки = 1; 
    НомерПоследнейСтроки = ДокументРезультат.ВысотаТаблицы;

    // Получаем нужную область и применяем метод Сгруппировать()
    // Параметр Истина означает, что группируются именно колонки.
    ОбластьДляГруппировки = ДокументРезультат.Область(
        НомерПервойСтроки, 
        НомерПервойКолонкиДляГруппировки, 
        НомерПоследнейСтроки, 
        НомерПоследнейКолонкиДляГруппировки
    );
    
    ОбластьДляГруппировки.Сгруппировать(Истина);

КонецПроцедуры

Важный момент: основная ошибка, с которой столкнулся автор в теме на форуме, заключалась в том, что не был указан полный диапазон строк. Если вызвать метод, например, так: ДокументРезультат.Область(, 5, , 7), то платформа может взять только первую строку. Указание последней строки (НомерПоследнейСтроки) решает эту проблему и применяет группировку ко всей высоте таблицы.

Этот метод хорош, когда структура отчета заранее известна или ее можно легко вычислить. Однако в сложных динамических отчетах определение номеров нужных колонок и строк может стать нетривиальной задачей.

Решение 2: Декларативная настройка в конструкторе СКД

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

Разберем по шагам, как это сделать:

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

После формирования отчета вы увидите, что над вашими колонками появилась общая шапка, а слева от нее — значок "+" или "-", позволяющий сворачивать и разворачивать эту группу. Этот подход не требует ни строчки кода и является более гибким.

Решение 3: Автоматическая группировка при ручном выводе

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

У объекта ТабличныйДокумент есть пара методов:

Все колонки, которые будут выведены в табличный документ между вызовами этих двух методов, будут автоматически объединены в одну группу.

Посмотрим на пример:


Процедура СформироватьОтчет(ТабДок)

    Макет = ПолучитьМакет("МойМакет");
    ОбластьКолонка1 = Макет.ПолучитьОбласть("Колонка1");
    ОбластьКолонка2 = Макет.ПолучитьОбласть("Колонка2");
    ОбластьКолонка3 = Макет.ПолучитьОбласть("Колонка3");
    
    // ... код вывода заголовков и прочих областей ...

    // Начинаем создавать группу
    ТабДок.НачатьАвтогруппировкуКолонок();

    // Выводим колонки, которые должны попасть в группу
    ТабДок.Присоединить(ОбластьКолонка1);
    ТабДок.Присоединить(ОбластьКолонка2);

    // Завершаем создание группы
    ТабДок.ЗакончитьАвтогруппировкуКолонок();

    // Эта колонка уже не попадет в группу
    ТабДок.Присоединить(ОбластьКолонка3);
    
    // ...
    
КонецПроцедуры

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

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

← На главную