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

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

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

В этой ситуации СКД по умолчанию выводит элемент дважды:

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

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

Почему нельзя просто отфильтровать дубли в запросе?

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


ГДЕ НЕ Показатель.Ссылка В (ВЫБРАТЬ Показатели.Родитель ИЗ Справочник.Показатели КАК Показатели)

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


Способ 1. Использование Пользовательского поля и Отбора «После группировки» (Классический метод)

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

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

Шаг 1. Создание пользовательского поля

Перейдем на вкладку «Настройки» в конструкторе СКД, далее откроем вкладку «Пользовательские поля» и добавим новое Поле-выражение. Назовем его, например, ЛишняяИерархия.

В окне редактирования выражения для детальных и итоговых записей пропишем следующий код:


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

Обратите внимание: вместо "ИмяПоляГруппировки" вам нужно вписать реальное имя вашего поля иерархии из набора данных (например, "Показатель" или "Подразделение").

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

Шаг 2. Добавление поля в настройки группировки

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

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

Это самый важный шаг. Нам нужно установить отбор не на весь отчет, а конкретно на нашу иерархическую группировку. Выделим группировку в структуре отчета, перейдем на вкладку «Отбор» и добавим условие:

Показатель Не равно ЛишняяИерархия

В колонке «Применение» для этого элемента отбора обязательно выберем значение «После группировки или для иерархии».

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


Способ 2. Определение контекста через ВычислитьВыражение (Метод автора темы)

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

Для этого в вычисляемых полях или условном оформлении используется выражение:

ВычислитьВыражение("Ссылка", , "Группировка", "Последняя")

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


Способ 3. Разделение наборов данных и связь через «Связи наборов данных»

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

Давайте проанализируем этот метод:

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

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


Способ 4. Визуальное скрытие через Условное оформление

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

Выясним, как настроить такое оформление:

  1. Перейдем на вкладку «Условное оформление» в настройках отчета или группировки.
  2. Добавим новое правило оформления. В оформляемых полях укажем ресурсы, которые дублируются (например, План, Факт).
  3. В условии укажем наше равенство: Показатель Равно ЛишняяИерархия (используя пользовательское поле из Способа 1).
  4. В свойствах оформления зададим параметры: Цвет текста = Белый (или цвет фона), либо установим свойство Текст = "" (пустая строка).

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

← На главную