При разработке отчетов на системе компоновки данных (СКД) разработчики часто сталкиваются с ситуацией, когда платформа автоматически формирует многоуровневую (ступенчатую) шапку. Это происходит, если поля группировок, реквизиты и ресурсы разнесены по разным уровням структуры отчета. Попытка решить проблему «в лоб» через создание собственного макета оформления или макета заголовка группировки приводит к другому ограничению: макет жестко фиксирует состав и ширину колонок. Если пользователь в режиме предприятия снимет флажок у одного из ресурсов или добавит новое поле, статичный макет не перестроится, что приведет к искажению отчета.
Разберем основные причины такого поведения СКД, а также рассмотрим программные и штатные способы решения этой задачи.
Проанализируем, почему стандартный макет СКД лишает отчет гибкости:
Если визуальные требования к шапке строгие, а структура колонок должна оставаться динамической, наиболее надежным подходом является программная постобработка сформированного документа в модуле объекта отчета.
Рассмотрим, как это работает. СКД штатно формирует стандартную динамическую таблицу, после чего в обработчике ПриКомпоновкеРезультата мы находим строку шапки и программно объединяем нужные ячейки по вертикали или горизонтали.
Посмотрим на пример реализации обработчика в модуле объекта отчета:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Позволяем СКД штатно сформировать табличный документ
// или вызываем стандартный вывод, после чего модифицируем результат
ОбъединитьЯчейкиВШапкеИЦентрировать(ДокументРезультат);
КонецПроцедуры
Теперь разберем алгоритм вспомогательной процедуры, которая выполняет поиск служебных заголовков и склеивает многоуровневые ячейки шапки:
Процедура ОбъединитьЯчейкиВШапкеИЦентрировать(ТабДок)
Выполнено = Ложь;
Для ИндексСтроки = 1 По ТабДок.ВысотаТаблицы Цикл
Если Выполнено Тогда
Прервать;
КонецЕсли;
// Ищем ключевую ячейку начала шапки
Если ТабДок.Область(ИндексСтроки, 1).Текст = "№ п/п" Тогда
Для ИндексКолонки = 1 По ТабДок.ШиринаТаблицы Цикл
ТекущаяЯчейка = ТабДок.Область(ИндексСтроки, ИндексКолонки);
НижняяЯчейка = ТабДок.Область(ИндексСтроки + 1, ИндексКолонки);
// Проверяем заполнение и объединяем ячейки для конкретных колонок
Если ТекущаяЯчейка.Текст = "" И НижняяЯчейка.Текст = "Оборудование" Тогда
ТекстЗаголовка = НижняяЯчейка.Текст;
ОбъединяемаяОбласть = ТабДок.Область(ИндексСтроки, ИндексКолонки, ИндексСтроки + 1, ИндексКолонки);
ОбъединяемаяОбласть.Объединить();
ОбъединяемаяОбласть.ГоризонтальноеПоложение = ГоризонтальноеПоложение.Центр;
ОбъединяемаяОбласть.ВертикальноеПоложение = ВертикальноеПоложение.Центр;
ОбъединяемаяОбласть.Текст = ТекстЗаголовка;
КонецЕсли;
Если ТекущаяЯчейка.Текст = "" И НижняяЯчейка.Текст = "Комментарий" Тогда
ТекстЗаголовка = НижняяЯчейка.Текст;
ОбъединяемаяОбласть = ТабДок.Область(ИндексСтроки, ИндексКолонки, ИндексСтроки + 1, ИндексКолонки);
ОбъединяемаяОбласть.Объединить();
ОбъединяемаяОбласть.ГоризонтальноеПоложение = ГоризонтальноеПоложение.Центр;
ОбъединяемаяОбласть.ВертикальноеПоложение = ВертикальноеПоложение.Центр;
ОбъединяемаяОбласть.Текст = ТекстЗаголовка;
КонецЕсли;
ТекущаяЯчейка.ГоризонтальноеПоложение = ГоризонтальноеПоложение.Центр;
ТекущаяЯчейка.ВертикальноеПоложение = ВертикальноеПоложение.Центр;
Если НижняяЯчейка.Текст = "Время" Тогда
НижняяЯчейка.ГоризонтальноеПоложение = ГоризонтальноеПоложение.Центр;
НижняяЯчейка.ВертикальноеПоложение = ВертикальноеПоложение.Центр;
КонецЕсли;
КонецЦикла;
Выполнено = Истина;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Важный нюанс: при жестком поиске по текстовым строкам (например, "Оборудование") переименование полей или смена языка интерфейса могут нарушить работу алгоритма. Для универсальности рекомендуется анализировать состав выбранных полей через коллекцию КомпоновщикНастроек.Настройки.Выбор.Элементы.
Во многих случаях свернуть шапку в одну строку можно без написания кода и без создания макетов, исключительно штатными средствами схемы компоновки данных:
Расположение полей группировки и установим значение Вместе или Отдельно. Это позволяет избежать создания лишних ярусов строк для каждого поля группировки.Расположение реквизитов в режим Вместе с владельцем, чтобы они не дробили заголовок на подуровни.Для создания компактной шапки в СКД в первую очередь следует использовать штатные параметры Расположение полей группировки и настройку выбранных полей на уровне группировок. Если же требуется нестандартное оформление ячеек, которое невозможно получить типовыми настройками, используем постобработку в событии ПриКомпоновкеРезультата, избегая статичных макетов, ломающих динамический вывод данных.