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