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