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