При разработке отчетов на системе компоновки данных (СКД) часто возникает задача заполнения «пустот» в данных. Типичный пример: если в текущем месяце не было закупок или продаж, необходимо отобразить цену из последнего месяца, когда такая операция совершалась. На первый взгляд, функция ВычислитьВыражение кажется идеальным инструментом для этого, но при ее использовании в вычисляемых полях разработчики часто сталкиваются с тем, что данные отображаются некорректно или сортировка «переворачивается».
В этой статье мы подробно разберем, почему стандартный подход через вычисляемые поля может не работать, и рассмотрим пошаговое решение через использование ресурсов и правильную настройку параметров функции.
Рассмотрим ситуацию: у нас есть запрос к оборотам регистра закупок с детализацией по месяцам. Мы хотим создать поле «Цена», которое будет равно текущей цене, а если ее нет — цене за предыдущий месяц. Автор темы пытался использовать в Вычисляемых полях следующее выражение:
Выбор
Когда ЦенаЗакупки = 0
Тогда ВычислитьВыражение("ЦенаЗакупки", , , "Предыдущая")
Иначе ЦенаЗакупки
Конец
Проблема такого подхода заключается в том, что Вычисляемые поля обрабатываются на уровне детальных записей до того, как СКД выполнит окончательную группировку и расчет итогов. Когда в настройках отчета включено «Дополнение периодов» (чтобы видеть пустые месяцы), СКД генерирует виртуальные строки. Вычисляемое поле в этом случае часто не может корректно обратиться к «предыдущей» строке, так как логическая последовательность периодов еще не до конца сформирована в контексте вычисления полей.
Кроме того, если закупки отсутствуют два или три месяца подряд, обращение к «Предыдущей» записи вернет пустоту, так как в предыдущем месяце значения тоже не было. Функция ВычислитьВыражение сама по себе не является рекурсивной в рамках вычисляемых полей.
Для корректного расчета подобных показателей необходимо переместить выражение на закладку Ресурсы. В ресурсах СКД работает уже с агрегированными данными, что позволяет функции ВычислитьВыражение точно понимать границы группировок и порядок следования периодов.
Важное правило: при работе в ресурсах все поля должны быть обернуты в агрегатные функции, такие как Сумма(), Максимум() или Среднее(). Даже если вы понимаете, что в разрезе месяца цена одна, для СКД это обязательное требование.
Разберем, как должно выглядеть выражение в колонке «Выражение» на закладке ресурсов:
Выбор
Когда Максимум(ЦенаЗакупки) = 0
Тогда ВычислитьВыражение("Максимум(ЦенаЗакупки)", "ПериодМесяц", , "Предыдущая", "Предыдущая")
Иначе Максимум(ЦенаЗакупки)
Конец
Проанализируем параметры, которые мы указали в функции, чтобы понимать, за что отвечает каждый из них:
Если нам нужно, чтобы цена «протягивалась» через несколько пустых месяцев (например, закупка была в январе, а в феврале, марте и апреле ее не было), стандартная конструкция с «Предыдущей» может не справиться, если мы смотрим только на один шаг назад. Выясним причину: в марте функция посмотрит в февраль, увидит там 0 и вернет 0.
Для решения этой задачи в более сложных отчетах рекомендуется использовать параметры "Первая" и "Текущая" с указанием направления поиска, либо использовать альтернативный метод — соединение наборов данных.
Если расчеты в ресурсах становятся слишком громоздкими, проанализируем метод соединения «самого с собой» в схеме компоновки данных:
ДОБАВИТЬКДАТЕ(ПериодМесяц, МЕСЯЦ, 1).В этом случае в каждой строке текущего месяца у вас уже будет готовое поле из «прошлого» месяца, которое можно использовать в обычных условиях ЕСТЬNULL() или ВЫБОР без использования сложных функций СКД.
Для получения корректных данных за прошлый месяц в СКД:
ВычислитьВыражение.ВычислитьВыражение в ресурсах работает с результатами агрегатных функций (Сумма, Максимум), а не с сырыми данными полей.Используя эти методы, мы добьемся стабильной работы отчета и исключим «переворачивание» данных или появление пустых значений там, где должна быть цена из истории.