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

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

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

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

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

Почему стандартная иерархия ломает структуру колонок?

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

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

Пошаговый алгоритм настройки кросс-таблицы в СКД

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

Шаг 1. Подготовка набора данных

Для начала убедимся, что наш запрос выбирает как саму номенклатуру, так и ее родителя (папку). Проанализируем типичный запрос для получения данных:


ВЫБРАТЬ
    ПродажиОбороты.Номенклатура КАК Номенклатура,
    ПродажиОбороты.Номенклатура.Родитель КАК Родитель,
    ПродажиОбороты.Склад КАК Склад,
    ПродажиОбороты.КоличествоОборот КАК Количество
ИЗ
    РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, Авто, ) КАК ПродажиОбороты

Обратите внимание: поле Номенклатура.Родитель обязательно должно быть доступно в схеме компоновки данных.

Шаг 2. Настройка структуры колонок в таблице

Вместо одной группировки по полю Номенклатура с типом «Иерархия», мы построим вложенную структуру в области «Колонки» нашей таблицы:

  1. В структуру колонок добавляем группировку по полю Номенклатура.Родитель. Указываем тип группировки — Элементы (без иерархии).
  2. Внутрь созданной группировки (как подчиненный элемент) добавляем группировку по полю Номенклатура. Тип группировки также выбираем — Элементы (без иерархии).

Альтернативный вариант структуры: в качестве родительской группировки можно использовать саму Номенклатуру с типом Только иерархия, а в качестве подчиненной — Номенклатуру с типом Без иерархии. Результат будет аналогичным.

Шаг 3. Настройка расположения полей группировок

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

  1. Выделяем в структуре настроек отчета всю таблицу или конкретно родительскую группировку колонок (Номенклатура.Родитель).
  2. Переходим на вкладку «Другие настройки» (в правой нижней части конструктора).
  3. Находим параметр «Расположение полей группировок».
  4. Устанавливаем для него значение «Отдельно» или «Отдельно и только в итогах».

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

Шаг 4. Настройка итогов по колонкам

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

  1. Выделяем подчиненную группировку колонок в структуре.
  2. В окне «Другие настройки» находим параметр «Расположение итогов».
  3. Устанавливаем его в значение «Нет».

При этом общие итоги по всей таблице останутся на своем месте (если они включены в общих настройках таблицы).

Решение проблемы с пустыми группами («Товары без группы»)

Если в вашей базе данных есть товары, лежащие непосредственно в корне справочника «Номенклатура», то у них нет родителя. В этом случае над такими колонками в отчете появится пустая ячейка, что выглядит не совсем профессионально. Мы можем легко исправить это с помощью стандартного механизма условного оформления:

  1. Переходим на вкладку «Условное оформление» (в целом для отчета или для родительской группировки колонок).
  2. Добавляем новый элемент оформления.
  3. На вкладке «Оформление» выбираем свойство «Текст» и вводим понятное значение, например, "Товары без группы" или "Основной каталог".
  4. На вкладке «Условие» добавляем условие сравнения: Номенклатура.Родитель Не заполнено.
  5. На вкладке «Оформляемые поля» выбираем поле Номенклатура.Родитель.

Теперь пустые ячейки в шапке заменятся на красивый и понятный текст, а СКД корректно объединит эти колонки под общим заголовком.

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

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


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

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

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

← На главную