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