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

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

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

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

Почему СКД выводит заголовок, если данных нет

Проанализируем внутренний алгоритм работы процессора компоновки данных. При формировании отчета система сначала инициализирует и отрисовывает шапку элемента структуры (заголовок группировки и заголовки выбранных полей), и только после этого приступает к обходу записей набора данных. Если записей не обнаружено, процесс обхода завершается, но уже выведенные строки шапки остаются в результирующем документе.

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

Способ 1. Программное отключение пустых группировок до компоновки

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

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

  1. Выполняем запросы наборов данных или проверяем количество строк в результирующих таблицах значений.
  2. Если по конкретному набору данных строк не найдено, отключаем соответствующую ветку в структуре настроек компоновщика, устанавливая свойство Использование в значение Ложь.
  3. Выполняем компоновку макета и вывод отчета с обновленными настройками.

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


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
	
	СтандартнаяОбработка = Ложь;
	
	// Получаем текущие пользовательские настройки
	Настройки = КомпоновщикНастроек.ПолучитьНастройки();
	
	// Проверяем наличие данных для каждой группировки через отдельный запрос
	Запрос = Новый Запрос;
	Запрос.Текст = 
		"ВЫБРАТЬ ПЕРВЫЕ 1
		|	1 КАК Поле
		|ИЗ
		|	РегистрНакопления.ВзаиморасчетыСКонтрагентами КАК Взаиморасчеты
		|ГДЕ
		|	Взаиморасчеты.Период МЕЖДУ &НачалоПериода И &КонецПериода";
	
	// Устанавливаем параметры запроса из настроек компоновщика
	ПараметрНачало = Настройки.ПараметрыДанных.Элементы.Найти("НачалоПериода");
	Если ПараметрНачало <> Неопределено И ПараметрНачало.Использование Тогда
		Запрос.УстановитьПараметр("НачалоПериода", ПараметрНачало.Значение);
	КонецЕсли;
	
	РезультатПроверки = Запрос.Выполнить();
	
	// Если записей нет, отключаем первую группировку в структуре
	Если РезультатПроверки.Пустой() Тогда
		Настройки.Структура[0].Использование = Ложь;
	КонецЕсли;
	
	// Компонуем макет и выводим отчет
	КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
	МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
	
	ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
	ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
	
	ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
	ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
	ПроцессорВывода.Вывести(ПроцессорКомпоновки);
	
КонецПроцедуры

Способ 2. Использование пользовательского макета группировки без кода

Рассмотрим вариант решения задачи непосредственно в конструкторе схемы компоновки данных без написания программного кода. Суть трюка заключается в переносе шапки и заголовка таблицы из секции заголовка в макет самой строки группировки.

Разберем по шагам последовательность настройки схемы:

  1. В настройках структуры отчета для целевой группировки отключаем вывод стандартных заголовков полей. Для этого в свойствах группировки во вкладке Другие настройки параметру Расположение реквизитов или Расположение полей группировки задаем значение, исключающее стандартную шапку, либо очищаем заголовки полей.
  2. Создаем родительскую группировку по ключевому полю, которое гарантированно заполнено при наличии записей (например, по идентификатору строки или значению группировочного поля).
  3. Переходим на вкладку Макеты схемы компоновки данных. Добавляем новый макет с типом Макет группировки (обратите внимание: выбираем именно макет группировки, а не макет заголовка).
  4. В созданной области макета оформляем и визуальный заголовок секции, и шапку колонок с наименованиями полей.

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

Способ 3. Постобработка сформированного табличного документа

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

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

Посмотрим на пример программного удаления пустых секций после формирования отчета:


// В процедуре ПриКомпоновкеРезультата после стандартного вывода
ПроцессорВывода.Вывести(ПроцессорКомпоновки);

// Ищем заголовок пустой секции в сформированном документе
ОбластьЗаголовка = ДокументРезультат.НайтиТекст("Общее юр. лицо");

Если ОбластьЗаголовка <> Неопределено Тогда
	
	НомерСтрокиЗаголовка = ОбластьЗаголовка.Верх;
	
	// Проверяем строку, где должны начинаться детальные данные (например, через 2 строки после заголовка)
	СтрокаДанных = ДокументРезультат.Область(НомерСтрокиЗаголовка + 2, 1, НомерСтрокиЗаголовка + 2, ДокументРезультат.ШиринаТаблицы);
	
	// Если под шапкой пустота или сразу начинается следующий заголовок — удаляем строки шапки
	Если ПустаяСтрока(СтрокаДанных.Текст) Тогда
		// Выделяем область заголовка и шапки колонок для удаления
		ОбластьДляУдаления = ДокументРезультат.Область(НомерСтрокиЗаголовка, , НомерСтрокиЗаголовка + 2, );
		ДокументРезультат.УдалитьОбласть(ОбластьДляУдаления, ТипСмещенияТабличногоДокумента.ПоВертикали);
	КонецЕсли;
	
КонецЕсли;

Способ 4. Пошаговый вывод через процессор вывода

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

Разберем логику работы этого метода:

  1. Инициализируем ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент.
  2. Выводим результат каждого отдельного элемента структуры во временный объект ТабличныйДокумент.
  3. Анализируем высоту временного табличного документа: если количество выведенных строк соответствует только высоте шапки (нет ни одной строки с реальными данными), мы игнорируем этот фрагмент.
  4. Если данные присутствуют, переносим содержимое временного документа в итоговый с помощью метода Вывести().

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

← На главную