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

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

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

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

Выясняем причину: почему СКД «задваивает» строки?

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

Для того чтобы разработчик не потерял эти собственные данные родителя, СКД разделяет вывод:

  1. Строка-группировка (Иерархия) — отображает консолидированные, агрегированные данные по всей ветке, включая сам родительский элемент и все его дочерние узлы.
  2. Строка-элемент (Детальная запись) — отображает исключительно собственные показатели конкретно этого элемента, даже если он является родителем для других.

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

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

Решение проблемы с помощью вычисляемых полей и отборов после группировки

Рассмотрим самый популярный и быстрый способ решения проблемы без изменения структуры запроса. Он основан на использовании языка выражений СКД и постобработки отборов.

Для реализации этого метода выполним следующие шаги:

Шаг 1. Создание вычисляемого поля

Перейдем на вкладку «Вычисляемые поля» в конструкторе схемы компоновки данных. Добавим новое поле со следующими параметрами:


Выбор 
    Когда Уровень() = 0 Тогда 
        Неопределено 
    Иначе 
        ВычислитьВыражение("Подразделение", , "Иерархия") 
Конец

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

Шаг 2. Настройка ресурсов

Перейдем на вкладку «Ресурсы». Если для корректного расчета итогов ваше вычисляемое поле используется в числовых показателях, убедитесь, что основные суммируемые поля (например, СуммаОборотов) рассчитываются по группировкам стандартным образом. Само вычисляемое поле РодительИерархии добавлять в ресурсы не требуется. Для задач, где формулы показателей должны различаться на разных уровнях дерева, подойдёт методика раздельного расчета итогов для разных группировок в СКД.

Шаг 3. Настройка структуры и применение отборов

Теперь перейдем на вкладку «Настройки». Нам нужно наложить отбор, но сделать это правильно:

  1. В структуре отчета выберите группировку, которая выводится с типом «Иерархия» (например, группировка по полю Подразделение).
  2. Перейдите на вкладку «Отбор» конкретно для этой группировки (не в общие настройки отчета!).
  3. Добавьте новое условие отбора: Подразделение Не равно РодительИерархии.
  4. Важнейший нюанс: Нажмите правой кнопкой мыши по созданному элементу отбора и найдите свойство «Режим применения отбора» (или тип применения). Установите для него значение «После группировки или для иерархии».

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

Анализ опасного подводного камня: проблема исчезновения конечных элементов

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

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

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


Выбор 
    Когда Подразделение.ЭтоГруппа Тогда 
        ВычислитьВыражение("Подразделение", , "Иерархия") 
    Иначе 
        Неопределено 
Конец

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

Альтернативный метод А: Использование связей наборов данных

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

Разберем этот метод по шагам:

  1. Создаем Набор данных №1 (Имя: «ИерархияИсточника»): Это простой запрос, который выбирает только саму структуру справочника (ссылку и ее родителя). Этот набор будет отвечать исключительно за построение дерева.
  2. Создаем Набор данных №2 (Имя: «ДанныеРесурсов»): Этот запрос выбирает числовые показатели (суммы, количества, обороты) только в разрезе конечных элементов (не групп).
  3. Переходим на вкладку «Связи наборов данных».
  4. Связываем Набор №1 и Набор №2 по ключевому полю (например, Подразделение).
  5. В настройках связи обязательно указываем поле источника связи и приемника, а также ставим флаг в колонке «Иерархическая связь».

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

Альтернативный метод Б: Корректировка структуры группировок

Иногда дублирование строк возникает из-за банальной ошибки при проектировании структуры отчета на вкладке «Настройки». Рассмотрим типичную ошибку начинающих разработчиков.

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

Помните: группировка с типом «Иерархия» уже сама по себе выводит и родительские папки, и конечные подчиненные элементы. Никаких дополнительных вложенных группировок по этому же полю или детальных записей внутрь нее добавлять не нужно. Достаточно оставить одну корневую группировку с типом «Иерархия» и выбрать необходимые ресурсы в выбранных полях.

Сравнительный анализ решений

Проанализируем все рассмотренные варианты, чтобы вы могли выбрать наиболее подходящий под ваши задачи:

Используя данные подходы, вы сможете создавать аккуратные, профессионально выглядящие отчёты без лишнего визуального «мусора» и дублирования информации, обеспечивая при этом абсолютную точность и корректность выводимых итоговых данных.

← На главную