Как в СКД рассчитать разницу между последней и предпоследней колонками (неделями)

Программист 1С v8.3 (Управляемые формы) Управленческий учет
← На главную

При построении динамических отчетов в системе компоновки данных (СКД), где колонками являются периоды (например, недели или месяцы), часто возникает задача анализа динамики. Типичный пример: вывести в конце таблицы отдельную колонку, которая покажет разницу между значением прибыли за последнюю неделю и значением за предпоследнюю неделю. Основная сложность заключается в том, что количество недель в отчете может меняться в зависимости от выбранного пользователем периода, и обычные вычисляемые поля с фиксированным смещением могут работать некорректно.

В этой статье мы разберем несколько эффективных способов решения этой задачи: от использования встроенных функций языка выражений СКД до подготовки данных на уровне запроса.

Способ 1. Использование функции ВычислитьВыражение в ресурсах

Самый гибкий способ, не требующий изменения текста запроса, — это использование функции ВычислитьВыражение в настройках ресурсов. Чтобы рассчитать разницу между последним и предпоследним значением группировки (в нашем случае ПериодНеделя), необходимо правильно указать параметры смещения и границы расчета.

Рассмотрим синтаксис выражения, которое нужно поместить в ресурс (обычно это поле Общий итог):


ЕстьNULL(ВычислитьВыражение("Сумма(ВаловаяПрибыль)", "ПериодНеделя", "Группировка", "Последняя", "Последняя"), 0) 
- 
ЕстьNULL(ВычислитьВыражение("Сумма(ВаловаяПрибыль)", "ПериодНеделя", "Группировка", "Предыдущая", "Предыдущая", , "Последняя"), 0)

Проанализируем, как работают эти функции:

  1. Первая часть выражения: находит значение суммы прибыли для самой последней записи в группировке по неделям. Параметры "Последняя", "Последняя" жестко фиксируют контекст на последней колонке.
  2. Вторая часть выражения: ищет «предыдущую» запись относительно указанной границы. Важнейшим моментом здесь является последний параметр (седьмой по счету), в котором мы указываем "Последняя". Это заставляет СКД сначала найти последнюю колонку, а затем отступить от нее на один шаг назад (к предыдущей).

Важное примечание: Использование ЕстьNULL необходимо, так как в выбранном периоде за какую-то неделю может не быть данных, и математическая операция с NULL вернет пустой результат.

Способ 2. Логика в запросе через ранжирование (обратный порядок)

Если вы хотите избежать сложных функций в выражениях СКД, которые могут замедлять отчет на больших объемах данных, можно подготовить данные заранее в тексте запроса. Мы можем присвоить каждой неделе «номер с конца».

Разберем алгоритм по шагам:

  1. Создадим временную таблицу со списком всех периодов, попавших в отчет.
  2. Для каждого периода вычислим его ранг относительно максимальной даты. Самая свежая неделя получит индекс 1, предпоследняя — индекс 2.
  3. В основном запросе присоединим эти индексы к данным о прибыли.

В СКД мы создадим два ресурса:

После этого итоговая разница будет вычисляться простейшим вычитанием этих ресурсов в вычисляемом поле. Этот метод работает молниеносно, так как СКД не нужно анализировать структуру группировок «на лету».

Способ 3. Расчет через массивы (для версий платформы 8.3.15+)

В современных версиях платформы 1С появилась возможность агрегировать данные в массив прямо в ресурсах СКД. Это открывает элегантный способ обращения к элементам коллекции.

Рассмотрим пример выражения для ресурса в общих итогах:


Выбор 
    Когда Количество(Массив(Сумма(ВаловаяПрибыль))) >= 2 
    Тогда Элемент(Массив(Сумма(ВаловаяПрибыль)), Количество(Массив(Сумма(ВаловаяПрибыль))) - 1) 
         - Элемент(Массив(Сумма(ВаловаяПрибыль)), Количество(Массив(Сумма(ВаловаяПрибыль))) - 2)
    Иначе 0 
Конец

Что здесь происходит:

  1. Функция Массив(Сумма(ВаловаяПрибыль)) собирает все суммы по неделям в один список в том порядке, в котором они выведены в отчете.
  2. Мы проверяем, что в массиве хотя бы 2 элемента (иначе разницу считать не из чего).
  3. С помощью функции Элемент() мы обращаемся к последнему индексу (длина - 1) и предпоследнему (длина - 2).

Способ 4. Подход через промежуточную таблицу значений (ТЗ)

Как отмечают опытные разработчики, иногда сложные расчеты внутри СКД (особенно нарастающие итоги и смещения) вызывают «геометрическое» увеличение времени выполнения. В таких случаях эффективнее использовать программную подготовку данных:

  1. Выполните первый запрос СКД без расчетной разницы и выгрузите результат в ТаблицаЗначений.
  2. Добавьте в ТаблицаЗначений колонку ПрибыльРазница.
  3. Одним циклом пройдите по таблице и программно вычислите разницу, зная значения в строках или колонках.
  4. Используйте полученную ТаблицаЗначений как внешний набор данных для окончательного вывода через СКД.

Этот метод гарантирует линейную скорость работы отчета независимо от сложности формулы разницы.

Особенности работы с «пустыми» неделями

Проанализируем важный нюанс: если пользователь выбрал период, в котором, например, на второй неделе не было продаж, эта неделя может просто не попасть в выборку запроса. В этом случае функции Предыдущая или обращение к индексу массива вернут не «календарную» предыдущую неделю, а ту, которая была в базе последней перед текущей (например, месяц назад).

Рекомендация: Чтобы расчет разницы был математически корректным, всегда делайте ЛЕВОЕ СОЕДИНЕНИЕ ваших данных с производственным календарем или таблицей периодов. Это обеспечит наличие в отчете всех недель (с нулевыми суммами), и функции смещения будут работать точно по календарной сетке.

Резюме

Для простых отчетов оптимально использовать Способ 1 с функцией ВычислитьВыражение и корректной установкой параметров границы. Если отчет строится по огромным массивам данных — выбирайте Способ 2 (ранжирование в запросе). Если же требуется сложная постобработка, лучше всего подойдет вариант с Таблицей Значений.

← На главную