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

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием Управленческий учет Торговля и дистрибуция
← На главную

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

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

Анализ проблемы и постановка задачи

Рассмотрим ситуацию: у нас есть иерархический справочник Номенклатура. В отчете выводятся колонки: Сумма остатка, Сумма неликвида и % неликвида. Логика расчета процента следующая:

  1. Для Общего итога: СуммаНеликвида / СуммаОстатка.
  2. Для верхнего уровня иерархии (например, категория "Диваны"): СуммаНеликвида(Группы) / СуммаНеликвида(ОбщийИтог) * %(ОбщийИтог).
  3. Для вложенных уровней (например, "Детские диваны"): СуммаНеликвида(Подгруппы) / СуммаНеликвида(Родителя) * %(Родителя).

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

Способ 1. Использование функции ВычислитьВыражение с параметром Иерархия

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

Способ 2. Разделение формул по уровням группировок

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

  1. Для поля ПроцентНеликвида в колонке "Рассчитывать по" выберем Общий итог. Формула: Сумма(СуммаНеликвида) / Сумма(СуммаОстатка)
  2. Создадим вторую строку для этого же ресурса, выбрав в "Рассчитывать по" поле Номенклатура.Иерархия. Здесь мы применим условие, проверяющее уровень записи:
    
    ВЫБОР 
        КОГДА Уровень() = 1 
            ТОГДА Сумма(СуммаНеликвида) / ВычислитьВыражение("Сумма(СуммаНеликвида)", "", "ОбщийИтог") * (ВычислитьВыражение("Сумма(СуммаНеликвида)", "", "ОбщийИтог") / ВычислитьВыражение("Сумма(СуммаОстаток)", "", "ОбщийИтог"))
        ИНАЧЕ 
            Сумма(СуммаНеликвида) / ВычислитьВыражение("Сумма(СуммаНеликвида)", , "Иерархия", "Предыдущая") * (Ваша_Формула_Расчета_Для_Родителя)
    КОНЕЦ
    

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

Способ 3. Использование системного поля Уровень()

Функция Уровень() крайне полезна при расчетах в иерархии. Она позволяет определить, насколько глубоко в дереве находится текущая строка. Мы можем использовать ее для ветвления логики, чтобы избежать ошибок деления на ноль на самом верхнем уровне. Разберем пример реализации через ВычислитьВыражениеСГруппировкойМассив. Этот метод позволяет собрать данные со всех родительских уровней и извлечь нужное значение:


// Пример получения суммы неликвида родителя для любого уровня вложенности
Максимум(ВычислитьВыражениеСГруппировкойМассив("Сумма(СуммаНеликвида)", "Номенклатура", , "Уровень() = " + Строка(Уровень() - 1)))

Рекомендации по оптимизации

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

Резюме

Для корректного расчета итогов верхней иерархической группировки в СКД необходимо:

  1. Явно разделять формулы ресурсов для Общего итога и Иерархической группировки.
  2. Использовать четвертый параметр функции ВычислитьВыражение со значением "Иерархия".
  3. Применять функцию Уровень() для определения контекста расчета.

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

← На главную