Как убрать пустые группировки в СКД после применения отбора по детальным записям?

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

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

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

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

Способ 1. Перенос отбора на уровень конкретной группировки (Рекомендуемый)

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

Проанализируем этот процесс по шагам:

  1. Откроем схему компоновки данных и перейдем на вкладку Настройки.
  2. В окне структуры отчета выделим конкретную группировку, которая становится пустой (в нашем примере это Подразделение).
  3. В нижней части экрана перейдем на вкладку Отбор (это будет персональный отбор для выбранной группировки, а не для всего отчета).
  4. Добавим новое условие отбора по нашему ресурсу, например: [Ресурс] [Больше] [0] или [Ресурс] [Заполнено].
  5. Так как значения ресурсов рассчитываются снизу вверх по иерархии группировок, для подразделения, в котором не осталось подходящих сотрудников, значение ресурса станет равным NULL или 0. Соответственно, вся группировка подразделения отсечется автоматически.
  6. Чтобы под строкой подразделения в готовом отчете не выводился служебный текст примененного отбора, перейдем на вкладку Другие настройки этой группировки, найдем параметр Выводить отбор и установим для него значение Не выводить.

Способ 2. Отбор по заполнению детального поля на уровне родительской группировки

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

Выполним следующие действия:

  1. В структуре настроек СКД выберем группировку Подразделение.
  2. Перейдем в настройки её отбора.
  3. Добавим условие: [Сотрудник] [Заполнено] (или [Сотрудник] [Не равно] [Пустая ссылка Сотрудники]).

Рассмотрим, как это работает изнутри. Если все подчиненные детальные записи сотрудников для конкретного подразделения были отфильтрованы общим отбором, то значение поля Сотрудник на уровне группировки Подразделение примет значение NULL. Условие "Заполнено" отсечет такие строки, и пустые подразделения исчезнут из финального отчета.

Способ 3. Использование роли «Игнорировать NULL» в наборе данных

Часто пустые родительские строки появляются из-за особенностей связи таблиц в самом запросе схемы компоновки. Например, если используется ЛЕВОЕ СОЕДИНЕНИЕ таблицы подразделений с таблицей сотрудников, и для некоторых подразделений в базе данных физически нет сотрудников, запрос все равно вернет строки с незаполненными сотрудниками.

Мы можем указать СКД игнорировать такие пустые записи на уровне схемы данных:

  1. Перейдем на вкладку Наборы данных в конструкторе СКД.
  2. Найдем поле детальной группировки (в нашем случае Сотрудник).
  3. В колонке Роль нажмем кнопку редактирования параметров роли поля.
  4. Установим флажок Игнорировать NULL.

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

Способ 4. Использование функции ВычислитьВыражениеСГруппировкойМассив

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

Выясним, как рассчитать количество записей, оставшихся после применения отбора, с помощью встроенных функций компоновки:

  1. Перейдем на вкладку Вычисляемые поля и добавим новое служебное поле (например, КоличествоСотрудниковПослеОтбора).
  2. В качестве выражения для этого поля или в качестве выражения ресурса на вкладке Ресурсы укажем следующую конструкцию:

Сумма(ВычислитьВыражениеСГруппировкойМассив("1", "Сотрудник", "ИмяРесурса > 0"))

Разберем подробнее, как работает это выражение:

После этого нам остается лишь зайти в настройки группировки Подразделение и установить отбор: [КоличествоСотрудниковПослеОтбора] [Больше] [0]. При этом выводить само вычисляемое поле в выбранные поля отчета пользователю совершенно не обязательно — оно может использоваться скрытно.

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

В некоторых случаях (например, при сложной структуре отчета с фиксированными макетами или кросс-таблицами) стандартные декларативные методы СКД могут вести себя непредсказуемо. Тогда на помощь приходит программная обработка процесса компоновки в модуле объекта отчета.

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


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

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

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

← На главную