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