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

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

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

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

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

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

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

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

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

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

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

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

Посмотрим на пример формулы, которую мы можем записать в поле выражений для ресурса Площадь:


Выбор 
    Когда Культура Есть Null 
        Тогда Сумма(Расходы.Площадь) 
    Иначе 
        Сумма(Посев.Посеяно) 
Конец

Проанализируем детально, как СКД обрабатывает это выражение на разных уровнях:

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

Важный нюанс: Расчет математически верных общих итогов

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

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

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

Рассмотрим, как правильно настроить ресурс для расчета общего итога в такой ситуации:

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

Сумма(ВычислитьВыражениеСГруппировкойМассив(
    "Выбор Когда Культура Есть Null Тогда Сумма(Расходы.Площадь) Иначе Сумма(Посев.Посеяно) Конец", 
    "Культура"
))

Разберем по шагам логику работы этой тяжелой, но крайне полезной функции:

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

← На главную