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