При разработке отчетов в системе компоновки данных (СКД) часто возникает задача расчета коэффициентов оборачиваемости или показателей присутствия товара в наличии. Например, необходимо вычислить процент дней за выбранный период, в течение которых товар фактически находился на складе (остаток был больше нуля).
В процессе реализации этой задачи разработчики часто сталкиваются с ситуацией, когда на уровне детальных записей расчет выполняется корректно, а в иерархических группировках или общих итогах значения суммируются некорректно, давая аномальные результаты (например, 911% вместо 100%). Разберем причины такого поведения платформы и найдем правильный способ настройки выражения в СКД.
Рассмотрим стандартную формулу, которую обычно пытаются применить в вычисляемом поле или ресурсах СКД для вычисления доли дней с положительным остатком:
Количество(ВычислитьВыражениеСГруппировкойМассив("ОстатокСУчетомНастроек", , "ОстатокСУчетомНастроек>0")) / (РазностьДат(&НачалоПериода, &ОкончаниеПериода, "День") + 1) * 100
Проблема данной формулы заключается во втором параметре функции ВычислитьВыражениеСГруппировкойМассив. Если этот параметр оставить пустым, СКД будет формировать массив значений без привязки к конкретному разрезу (в данном случае — без группировки по полю Период).
На детальном уровне элементов номенклатуры такое выражение может возвращать требуемое число элементов массива (количество дней). Однако на уровне родительских групп и иерархии платформа начинает собирать в массив все детальные записи поддерева. В результате функция Количество() считывает общее число элементов по всем вложенным позициям номенклатуры за все дни. Так получается число 82 вместо положенных 9 дней, что при умножении на 100 и делении на 9 дает некорректный результат 911,11%.
Для исправления расчета необходимо жестко зафиксировать группировку, в разрезе которой функция должна формировать массив значений. В нашей задаче такой группировкой является день (поле Период или ПериодДень).
Разберем правильный синтаксис выражения ресурса или вычисляемого поля:
Количество(ВычислитьВыражениеСГруппировкойМассив("ОстатокСУчетомНастроек", "Период", "ОстатокСУчетомНастроек>0")) / (РазностьДат(&НачалоПериода, &ОкончаниеПериода, "День") + 1) * 100
Проанализируем параметры функции ВычислитьВыражениеСГруппировкойМассив по шагам:
"ОстатокСУчетомНастроек" — вычисляемый показатель остатка на каждый день."Период" — указываем группировку по дням. Теперь СКД формирует по одному значению массива на каждый уникальный день периода в рамках текущего контекста отчета."ОстатокСУчетомНастроек>0" — в массив попадают только те дни, когда остаток номенклатуры был строго больше нуля.После этого платформа выполнит обертку Количество() над полученным массивом уникальных дней и корректно разделит его на продолжительность периода, дав правильный результат как на уровне элементов, так и в иерархических группах номенклатуры.
Использование сложных агрегатных функций вида ВычислитьВыражениеСГруппировкойМассив в вычисляемых полях или ресурсах СКД выполняется в памяти платформы 1С. На больших объемах данных это может привести к снижению производительности отчета.
Если отчет работает медленно, рекомендуется вынести логику расчета флага наличия непосредственно в запрос набора данных. Разберем этот вариант по шагам:
ВЫБОР
КОГДА Остаток > 0 ТОГДА 1
ИНАЧЕ 0
КОНЕЦ КАК ДеньСНаличием
Сумма(ДеньСНаличием) / Количество(Различные Период) * 100
Такой подход обеспечивает высокую скорость работы отчета и исключает ошибки суммирования процентов в иерархических записях.