При разработке сложных аналитических отчетов в Системе компоновки данных (СКД) разработчики часто сталкиваются с необходимостью выводить разные расчетные данные для одного и того же ресурса на разных уровнях иерархии. Представим типичную бизнес-ситуацию: в отчете по растениеводству на уровне конкретной группировки «Культура» нам необходимо рассчитывать площадь на основе фактически посеянных площадей (поле Посев.Посеяно), а на более высоких уровнях (например, по отделениям или организации в целом) и в общих итогах — выводить стандартную сумму физической площади из документов расходов (поле Расходы.Площадь).
Попытки решить эту задачу «в лоб» через написание одного общего произвольного выражения часто приводят к ошибкам, так как стандартные механизмы СКД накладывают ограничения на вывод разных ресурсов в одну и ту же ячейку. В рамках этой статьи мы подробно рассмотрим два наиболее эффективных и проверенных на практике способа реализации условного расчета ресурсов по группировкам, проанализируем их плюсы и минусы, а также разберем важный нюанс корректного расчета общих итогов.
Рассмотрим самый надежный, декларативный и заложенный создателями платформы 1С метод. Некоторые разработчики ошибочно предполагают, что если в таблице ресурсов указать для поля конкретную группировку в колонке «Рассчитывать по...», то для остальных уровней отчета этот ресурс перестанет рассчитываться вовсе. На самом деле СКД обладает великолепной гибкостью: мы можем добавлять одно и то же поле в список ресурсов несколько раз, задавая для каждой строки индивидуальные формулы и правила применения.
Давайте разберем по шагам, как настроить такую схему на вкладке «Ресурсы» в конструкторе схемы компоновки данных:
Площадь (или Расходы.Площадь).Сумма(Посев.Посеяно).Культура. Если в настройках структуры отчета используется вывод этой же группировки с иерархией, обязательно добавляем сюда же предопределенное поле Культура Иерархия.Площадь.Сумма(Расходы.Площадь).ОбщийИтог, но пустая ячейка работает как правило по умолчанию.Выясним причину, почему эта схема работает безотказно. Компоновщик макета СКД при формировании отчета анализирует каждую выводимую строку. Когда он рассчитывает итог по группировке Культура, он видит максимально точное (специфичное) правило расчета, описанное в первой строке нашей таблицы ресурсов, и применяет формулу Сумма(Посев.Посеяно). При расчете любых других группировок (например, по полям, бригадам или филиалам), а также при расчете общих итогов, точечное правило для культуры не подходит, и СКД автоматически обращается к универсальному правилу «по умолчанию» из второй строки, рассчитывая Сумма(Расходы.Площадь).
Иногда разработчики хотят решить задачу непосредственно внутри самого языка выражений СКД, избегая добавления множества строк в ресурсы. Напрямую спросить у системы «Какая сейчас выводится группировка?» с помощью какой-то готовой функции (например, гипотетической ИмяТекущейГруппировки()) в СКД нельзя. Однако мы можем применить логический прием, основанный на анализе контекста расчета.
Когда СКД рассчитывает итоги для уровней выше нашей целевой группировки (или вообще в параллельных ветках отчета), значение самого группировочного поля Культура в контексте этой строки агрегации отсутствует. Соответственно, система видит его как NULL. Мы можем использовать это для построения условного выражения в ресурсах.
Посмотрим на пример формулы, которую мы можем записать в поле выражений для ресурса Площадь:
Выбор
Когда Культура Есть Null
Тогда Сумма(Расходы.Площадь)
Иначе
Сумма(Посев.Посеяно)
Конец
Проанализируем детально, как СКД обрабатывает это выражение на разных уровнях:
Культура (и нижестоящих детальных записей) поле Культура заполнено конкретным значением из базы данных. Условие Культура Есть Null возвращает ложь, управление переходит к ветке Иначе, и на экран выводится сумма посеянных площадей.Культура возвращает NULL, условие выполняется, и рассчитывается стандартная сумма расходов по площадям.Важное предупреждение: Несмотря на кажущуюся простоту и изящество, данный способ таит в себе скрытую угрозу. Если в вашей базе данных у некоторых записей поле Культура окажется действительно не заполнено (системное значение NULL в самой СУБД), то расчет итогов для таких строк пойдет по неверной ветке условия. Они определятся системой как «вышестоящий уровень», и вместо формулы посева применится формула расходов. Именно поэтому Способ 1 с явным указанием группировок в ресурсах является стандартом разработки и рекомендуется к применению в первую очередь.
При внедрении условных формул для разных группировок разработчики практически всегда сталкиваются с проблемой «не бьющихся» общих итогов. Предположим, мы успешно настроили отчет по Способу 1: на уровне культур выводится площадь посева, а на верхних уровнях — площадь расходов.
Бизнес-пользователь открывает отчет, видит детальные строки по культурам, складывает их показатели на калькуляторе и обнаруживает, что сумма в строке «Общий итог» не совпадает со сложением строк на экране! Это происходит потому, что в общем итоге СКД честно выполняет формулу по умолчанию (берет общую сумму расходов по площадям из базы), а не математически суммирует те результаты, которые были выведены на уровне культур.
Чтобы заставить СКД на верхних уровнях не просто применять базовую формулу, а **физически сложить уже рассчитанные результаты** по нижестоящим группировкам, мы должны использовать специальную функцию ВычислитьВыражениеСГруппировкойМассив.
Рассмотрим, как правильно настроить ресурс для расчета общего итога в такой ситуации:
Площадь.ОбщийИтог (и другие вышестоящие группировки при необходимости).
Сумма(ВычислитьВыражениеСГруппировкойМассив(
"Выбор Когда Культура Есть Null Тогда Сумма(Расходы.Площадь) Иначе Сумма(Посев.Посеяно) Конец",
"Культура"
))
Разберем по шагам логику работы этой тяжелой, но крайне полезной функции:
ВычислитьВыражениеСГруппировкойМассив дает команду компоновщику СКД временно «спуститься» на уровень группировки Культура.NULL), для каждого отдельного элемента группировки.Сумма(...) производит математическое сложение всех элементов этого массива.В результате на уровне общего итога мы получаем красивую, логичную и математически верную сумму, которая в точности соответствует ожиданиям конечных пользователей и исключает любые вопросы к качеству работы отчета.