При разработке отчетов на базе Системы компоновки данных (СКД) программисты часто сталкиваются с ситуацией, когда простые арифметические операции (например, расчет процента выполнения плана или отклонения) выдают в итогах странные, пугающе огромные цифры. На первый взгляд формула кажется верной, но результат в группировках и общих итогах не поддается логике. Разберем по шагам, почему так происходит, и как заставить СКД считать математику корректно.
Рассмотрим ситуацию, которую описал автор темы. Есть формула расчета отклонения: (КоличествоПлан - КоличествоФакт) / КоличествоПлан. В детальных записях (в конкретных строках отчета) эта формула работает безупречно. Однако, как только мы смотрим на уровень группировки (например, по Складу или Номенклатуре), вместо ожидаемых 0,01 (1%) мы видим значение 8,1 или даже больше.
Проанализируем причину такого поведения системы. В СКД существует четкое разделение между Вычисляемыми полями и Ресурсами:
Если вы добавили поле с формулой деления в "Вычисляемые поля", а затем на закладке "Ресурсы" просто указали для него функцию Сумма(), система сделает следующее: она возьмет процент, рассчитанный для каждой строки, и просто сложит эти проценты между собой. Именно поэтому вместо среднего процента отклонения вы получаете накопленную сумму всех отклонений по всем строкам, входящим в группировку.
Это самый надежный и профессиональный метод. Основное правило СКД гласит: любые формулы, содержащие деление или расчет долей, должны описываться не в вычисляемых полях, а непосредственно в выражении ресурса.
Выясним, как должна выглядеть правильная формула. Чтобы получить корректный процент по группировке, нам нужно сначала просуммировать числитель, затем просуммировать знаменатель, и только после этого выполнить деление. Выражение на закладке "Ресурсы" должно выглядеть так:
(Сумма(КоличествоПлан) - Сумма(КоличествоФакт)) / Сумма(КоличествоПлан)
Важно помнить: если вы попытаетесь написать Сумма((Поле1 - Поле2) / Поле1), вы снова получите неверный результат, так как агрегатная функция Сумма будет применена к результату деления каждой строки. Запомните принцип: сначала суммируем слагаемые, потом делим итоги.
При использовании формул с делением в ресурсах мы неизбежно столкнемся с риском возникновения ошибки "Деление на 0" (например, если план не был задан). В СКД это может привести к тому, что поле в отчете останется пустым или отчет вообще выдаст ошибку выполнения.
Проанализируем ситуацию с NULL. В 1С любая математическая операция с NULL (например, 100 - NULL) дает в результате NULL. Если в ваших данных есть пропуски, расчет "сломается". Рассмотрим безопасный вариант написания ресурса с использованием функции ВЫБОР и ЕСТЬNULL:
ВЫБОР
КОГДА Сумма(ЕСТЬNULL(КоличествоПлан, 0)) = 0
ТОГДА 0
ИНАЧЕ (Сумма(ЕСТЬNULL(КоличествоПлан, 0)) - Сумма(ЕСТЬNULL(КоличествоФакт, 0))) / Сумма(ЕСТЬNULL(КоличествоПлан, 0))
КОНЕЦ
Такой подход гарантирует стабильную работу отчета даже при отсутствии данных в некоторых периодах или по отдельным номенклатурным позициям.
Некоторые разработчики предпочитают выносить расчеты в текст запроса. Это допустимо, но имеет существенный минус. Запрос вычислит процент только для детальных записей. Когда СКД начнет строить итоги, она не будет знать, что это "процент", и по умолчанию просто сложит эти значения (если в ресурсах стоит Сумма).
Если вы все же решили считать в запросе, вам все равно придется зайти на закладку Ресурсы и прописать там ту же формулу деления сумм, которую мы рассматривали выше. В этом случае поле из запроса будет использоваться только как "сырые данные" для агрегации.
Как отметил автор темы, проблему иногда удается решить через "Пользовательские поля" в настройках отчета (в режиме пользователя). Рассмотрим, почему это работает. Когда пользователь создает поле-выражение, СКД на лету пытается проанализировать контекст. Если в формуле используются числовые показатели, которые уже являются ресурсами, система автоматически применяет к ним правила агрегации.
Однако мы рекомендуем не полагаться на этот метод при разработке тиражных решений, так как пользователь может случайно изменить формулу, и логика расчета нарушится. Лучше один раз правильно настроить схему в Конфигураторе.
Посмотрим на типичную ошибку из обсуждения: попытка написать Сумма(Поле1)/Сумма(Поле2) прямо на закладке "Вычисляемые поля". При попытке сохранить такую схему 1С выдаст ошибку: "использование вложенных агрегатных функций не допускается".
Это происходит потому, что Вычисляемые поля работают на уровне "до того, как данные начали группироваться". Агрегатные функции (Сумма, Количество, Среднее) там недоступны, так как системе еще не к чему их применять. Запомните: в "Вычисляемых полях" мы пишем только атомарные формулы (строка к строке), а в "Ресурсах" — формулы для итогов и групп.
ЧЦ=10; ЧДЦ=2 и, если нужно, добавьте условное оформление для выделения отрицательных отклонений красным цветом.Таким образом, мы выяснили, что "странные цифры" в отчетах — это не ошибка платформы 1С, а результат простого математического суммирования долей. Перенос логики деления в Ресурсы с предварительным суммированием показателей решает эту задачу раз и навсегда.