При разработке отчетов на системе компоновки данных (СКД) программисты часто сталкиваются с необходимостью вывести нарастающий итог. Казалось бы, штатная функция ВычислитьВыражение() создана именно для этого, однако на практике новички часто получают пустые колонки в детальных записях отчета. Проанализируем типичную ситуацию: настройки выполнены, ресурсы добавлены, но поле в отчете остается пустым. Выясним причину такого поведения системы и разберем правильный алгоритм настройки.
Рассмотрим ситуацию, с которой столкнулся автор темы. В схеме компоновки данных было создано вычисляемое поле, но его выражение в списке полей было оставлено пустым. При этом в закладке Ресурсы была прописана магическая формула с использованием ВычислитьВыражение(). Логика разработчика понятна: "Я хочу итог, значит, иду в ресурсы". Однако здесь кроется фундаментальная особенность работы СКД.
Проанализируем, как СКД обрабатывает данные. Система разделяет вывод на два уровня:
Если вы прописали выражение только в ресурсах, оно будет рассчитано исключительно для итоговых строк (группировок). В детальных записях (строках с конкретными документами или записями регистра) система попытается взять значение из выражения самого поля. Если там пусто — вы получите пустую ячейку, даже если ресурс настроен идеально.
Решение: чтобы нарастающий итог отображался в каждой строке детальных записей, необходимо продублировать или перенести выражение функции ВычислитьВыражение() непосредственно в настройки вычисляемого поля на соответствующей закладке СКД.
Рассмотрим по шагам правильный процесс настройки на примере расчета прибыли (Доход - Расход) с накоплением:
1. Перейдем на закладку Вычисляемые поля. Добавим новое поле, например, ПрибыльНарастающимИтогом. В колонке Выражение напишем следующую конструкцию:
ВычислитьВыражение("Сумма(Доход - Расход)", , , "Первая", "Текущая")
2. Перейдем на закладку Ресурсы. Выберем наше поле ПрибыльНарастающимИтогом. В выражении ресурса укажем точно такое же выражение или просто Сумма(ПрибыльНарастающимИтогом), если вы хотите, чтобы в итогах группировок выводилось последнее накопленное значение.
3. На закладке Настройки добавим это поле в Выбранные поля. Теперь в отчете данные появятся и в строках, и в итогах.
Для свободного владения инструментом разберем параметры функции более подробно. Синтаксис выглядит так: ВычислитьВыражение(Выражение, Группировка, ТипРасчета, Начало, Конец, Упорядочивание).
Параметр 1: Выражение. Здесь мы указываем, что именно нужно считать. Важно понимать, что внутри этой функции можно использовать другие агрегатные функции, такие как Сумма(), Количество(), Максимум().
Параметр 2: Группировка. Если оставить его пустым, расчет идет в контексте текущей группировки. Если написать "Общая", расчет пойдет по всему отчету без учета иерархии групп. Если указать имя конкретной группировки (например, "Номенклатура"), нарастающий итог будет сбрасываться при переходе к новой группе.
Параметры 3 и 4: Начало и Конец (Границы окна). Для классического нарастающего итога мы используем значения "Первая" и "Текущая". Это заставляет систему суммировать значения от самой первой записи в выборке до текущей строки включительно.
Параметр 6: Упорядочивание. Это критически важный параметр, о котором часто забывают. Нарастающий итог напрямую зависит от порядка записей. Если пользователь в настройках отчета изменит сортировку, математический смысл нарастающего итога может нарушиться. Чтобы этого избежать, в шестом параметре рекомендуется явно указывать поле сортировки, например:
ВычислитьВыражение("Сумма(СуммаОборот)", , , "Первая", "Текущая", "ПериодСекунда Возр")
Проанализируем еще одну причину, по которой расчет может выдавать некорректный результат или пустоту. Если в одном из слагаемых (Доход или Расход) встречается значение NULL, любая арифметическая операция с ним вернет NULL. Даже если вы обработали NULL в запросе, вычисляемые поля СКД могут генерировать их заново в процессе компоновки.
Посмотрим на безопасный вариант написания выражения:
ВычислитьВыражение("Сумма(ЕстьNULL(Доход, 0) - ЕстьNULL(Расход, 0))", , , "Первая", "Текущая")
Использование функции ЕстьNULL гарантирует, что отсутствие данных в одной из колонок не "обнулит" весь нарастающий итог строки.
Рассмотрим ситуацию с большими объемами данных. Нужно понимать, что ВычислитьВыражение() — это мощный, но ресурсозатратный инструмент. Система вынуждена для каждой строки отчета заново пробегать диапазон от "Первой" до "Текущей". В отчетах на сотни тысяч строк это может привести к значительному замедлению формирования.
Если вы заметили падение производительности, проанализируем альтернативные варианты:
Т1.Период <= Т2.Период. Это перенесет нагрузку на СУБД, что зачастую работает быстрее.ПорядковыйНомер() или НомерВГруппировке(), которые работают значительно эффективнее.Если в вашем отчете включен вывод иерархии (например, иерархия справочника Номенклатура или Контрагенты), нарастающий итог может вести себя неожиданно. Система может начать суммировать значения папок вместе с элементами, что приведет к завышению итоговых показателей (задвоению).
В таких случаях при вычислении выражения стоит проверять тип записи. Рассмотрим пример, где мы исключаем иерархические уровни из расчета:
ВычислитьВыражение("Сумма(Выбор Когда СистемныеПоля.Уровень = 0 Тогда СуммаОборот Иначе 0 Конец)", , , "Первая", "Текущая")
Подводя итог, отметим: функция ВычислитьВыражение() является стандартом для создания гибких отчетов. Главное — помнить о разделении контекста ресурсов и вычисляемых полей, всегда обрабатывать пустые значения и следить за порядком сортировки данных.