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