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