При разработке отчетов на системе компоновки данных (СКД) программисты часто сталкиваются с ситуацией, когда необходимо рассчитать значение в группировке не как простую сумму или среднее, а как результат математической операции над другими итогами. Типичный пример — расчет коэффициента рентабельности, процента выполнения плана или средней цены, где формула выглядит как Сумма1 / Сумма2. Однако на практике вместо ожидаемого результата в полях группировок часто появляются «случайные» цифры, взятые из детальных записей. Разберем подробно, почему так происходит и как заставить СКД считать формулы правильно.
Рассмотрим ситуацию, которую часто допускают начинающие разработчики. На закладке Ресурсы для поля Коэффициент прописывается выражение СуммаПродаж / СуммаЗатрат. В этом случае СКД ведет себя следующим образом: при обходе дерева данных для каждой группировки она берет первую попавшуюся детальную запись, вычисляет для нее это выражение и выводит результат в итог группы. Система не понимает, что вы хотите сначала просуммировать все продажи по группе, затем просуммировать все затраты и только потом поделить одно на другое.
Проанализируем правильный подход. Чтобы расчет шел по итогам всей группы, в выражении ресурса обязательно должны присутствовать агрегатные функции. Мы должны явно указать системе, что расчет производится над агрегированными данными.
Для корректного вычисления используем следующую конструкцию в поле «Выражение» на закладке ресурсы:
ВЫБОР
КОГДА Сумма(СуммаЗатрат) = 0
ТОГДА 0
ИНАЧЕ Сумма(СуммаПродаж) / Сумма(СуммаЗатрат)
КОНЕЦ
Обратите внимание на использование функции Сумма(). Она принуждает СКД сначала вычислить итоги по входящим в группу записям, а затем применить к ним вашу математическую формулу. Использование оператора ВЫБОР (CASE) позволяет избежать критической ошибки «Деление на 0», если данных по второму ресурсу в конкретной группе не оказалось.
Если в вашем отчете используется иерархия (например, по справочнику «Номенклатура»), задача усложняется. В иерархических отчетах СКД различает «узлы» (папки) и «листья» (элементы). Часто возникает проблема, когда в папках отображаются некорректные данные или данные дублируются из первого элемента папки.
Выясним причину: СКД может рассчитывать ресурсы по-разному для детальных записей и для итогов. Для решения этой проблемы на закладке Ресурсы можно добавить одно и то же поле Коэффициент несколько раз, но с разными настройками в колонке Рассчитывать по....
Коэффициент. В колонке «Рассчитывать по...» оставим значение пустым (это значит «для всех уровней»). Пропишем стандартную формулу с агрегатами.Номенклатура.Иерархия. Здесь мы можем уточнить формулу специально для родительских записей.Если простая агрегация не дает нужного эффекта в иерархии, рассмотрим использование системной функции Уровень(). Это позволит нам гибко менять алгоритм расчета в зависимости от глубины вложенности группировки:
ВЫБОР
КОГДА Уровень() = 0 ТОГДА Сумма(Поле1) / Сумма(Поле2)
ИНАЧЕ ВычислитьВыражение("Сумма(Поле1) / Сумма(Поле2)", "Номенклатура")
КОНЕЦ
В сложных случаях, когда обычные ресурсы не справляются, мы можем использовать функцию ВычислитьВыражение. Она позволяет управлять контекстом расчета и обращаться к данным других группировок или всей таблицы.
Синтаксис функции для нашего случая выглядит так:
ВычислитьВыражение("Сумма(Ресурс1) / Сумма(Ресурс2)", "ИмяГруппировки")
Этот метод гарантирует, что расчет будет привязан именно к итогам указанной группировки, а не к произвольным строкам. Также полезно помнить про параметр "Группировка", который позволяет выполнять расчет в контексте текущего уровня, игнорируя нижестоящие детальные записи.
Иногда программист делает все правильно: прописывает агрегаты, настраивает уровни, но в отчете все равно видит старые, неверные данные. Это одна из самых коварных особенностей работы в 1С:Предприятии — кэширование настроек компоновки.
Разберем, как это работает. Когда пользователь открывает отчет, система сохраняет его текущие настройки (состав колонок, формулы, отборы). Если вы изменили формулу ресурса в Конфигураторе и запустили отчет снова, 1С может подтянуть «старую» структуру из кэша пользователя, игнорируя ваши изменения в коде метаданных.
Чтобы исключить влияние кэша, рекомендуем выполнить следующие действия:
%AppData%\1C\1Cv8).Проанализировав ситуацию, описанную в теме форума, мы видим, что именно кэширование стало финальной преградой. Автор верно применил агрегатные функции Сумма(Сумма1) / Сумма(Сумма2), но результат обновился только после фактического пересоздания объекта в системе (переименования), что сбросило некорректные настройки.
Подведем итог. Для создания корректного вычисляемого ресурса на уровне группировки выполним следующие шаги:
Сумма(), Максимум() или другие агрегаты для каждого операнда.ВЫБОР КОГДА.Следуя этим правилам, вы сможете строить сложные аналитические отчеты, где расчетные показатели будут всегда точными и предсказуемыми на любом уровне вложенности данных.