Как в СКД рассчитать значение на основании данных предыдущего месяца через вычисляемые поля

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

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

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

Анализируем проблему: почему вычисляемые поля не всегда подходят

Рассмотрим ситуацию: у нас есть запрос к оборотам регистра закупок с детализацией по месяцам. Мы хотим создать поле «Цена», которое будет равно текущей цене, а если ее нет — цене за предыдущий месяц. Автор темы пытался использовать в Вычисляемых полях следующее выражение:


Выбор 
    Когда ЦенаЗакупки = 0 
    Тогда ВычислитьВыражение("ЦенаЗакупки", , , "Предыдущая") 
    Иначе ЦенаЗакупки 
Конец

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

Кроме того, если закупки отсутствуют два или три месяца подряд, обращение к «Предыдущей» записи вернет пустоту, так как в предыдущем месяце значения тоже не было. Функция ВычислитьВыражение сама по себе не является рекурсивной в рамках вычисляемых полей.

Шаг 1: Перенос логики в ресурсы

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

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

Разберем, как должно выглядеть выражение в колонке «Выражение» на закладке ресурсов:


Выбор 
    Когда Максимум(ЦенаЗакупки) = 0 
    Тогда ВычислитьВыражение("Максимум(ЦенаЗакупки)", "ПериодМесяц", , "Предыдущая", "Предыдущая") 
    Иначе Максимум(ЦенаЗакупки) 
Конец

Шаг 2: Разбор параметров функции ВычислитьВыражение

Проанализируем параметры, которые мы указали в функции, чтобы понимать, за что отвечает каждый из них:

  1. "Максимум(ЦенаЗакупки)" — это само выражение, которое мы хотим вычислить. Мы берем максимум цены, чтобы получить значение из исходных данных.
  2. "ПериодМесяц" — (второй параметр) указывает на группировку, в разрезе которой производятся вычисления. Это критически важно: функция должна понимать, что «Предыдущая» — это запись по предыдущему месяцу в рамках той же номенклатуры.
  3. Третий параметр (Область) — в данном случае оставляем пустым, так как расчет идет в контексте текущей группировки.
  4. "Предыдущая" (Начало) — указывает, откуда начинать поиск данных.
  5. "Предыдущая" (Конец) — указывает, где закончить поиск. Указывая оба параметра как «Предыдущая», мы жестко ограничиваем функцию просмотром только одной предшествующей записи.

Шаг 3: Обработка цепочки пустых значений

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

Для решения этой задачи в более сложных отчетах рекомендуется использовать параметры "Первая" и "Текущая" с указанием направления поиска, либо использовать альтернативный метод — соединение наборов данных.

Альтернативное решение: Соединение двух наборов данных

Если расчеты в ресурсах становятся слишком громоздкими, проанализируем метод соединения «самого с собой» в схеме компоновки данных:

  1. Создаем Набор данных 1 с основными показателями (Продажи, Закупки).
  2. Создаем Набор данных 2, который полностью дублирует первый, но в запросе к периоду добавляется смещение: ДОБАВИТЬКДАТЕ(ПериодМесяц, МЕСЯЦ, 1).
  3. На закладке Связи наборов данных связываем их по ключевым полям (Номенклатура, Склад) и по периоду.

В этом случае в каждой строке текущего месяца у вас уже будет готовое поле из «прошлого» месяца, которое можно использовать в обычных условиях ЕСТЬNULL() или ВЫБОР без использования сложных функций СКД.

Подведем итоги

Для получения корректных данных за прошлый месяц в СКД:

Используя эти методы, мы добьемся стабильной работы отчета и исключим «переворачивание» данных или появление пустых значений там, где должна быть цена из истории.

← На главную