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