Как правильно рассчитать дату предыдущей продажи в СКД с помощью функции ВычислитьВыражение

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

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

В чем суть проблемы и почему функция не работает в Вычисляемых полях

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

ВычислитьВыражение("Период", "Партнер",, "Предыдущая", "Предыдущая")

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

Дело в том, что расчет данных в СКД происходит в несколько строго разграниченных этапов:

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

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

Пошаговое руководство по настройке корректного расчета

Разберем по шагам, как перенести вычисления в ресурсы и правильно составить структуру отчета, чтобы даты продаж рассчитывались корректно для каждого партнера.

Шаг 1. Настройка структуры отчета

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

  1. Создадим родительскую группировку по полю Партнер.
  2. Внутри нее добавим подчиненную группировку по полю Период. Именно на уровне этой детальной группировки периодов и будет происходить расчет нашего показателя.

Шаг 2. Перенос формулы в Ресурсы

Перейдем на вкладку «Ресурсы» схемы компоновки данных. Нам нужно объявить наше поле ПредыдущаяДатаПродажи ресурсом, но рассчитывать его только для определенных уровней отчета.

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

Давайте проанализируем параметры функции, которую мы указали в ресурсах:

Важные нюансы: Сортировка и обработка пустых значений

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

Пропишем в ресурсах более надежный вариант формулы:


ВычислитьВыражение("Период", "Период", , "Предыдущая", "Предыдущая", "Период Возр")

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

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


Выбор 
    Когда ВычислитьВыражение("Период", "Период", , "Предыдущая", "Предыдущая", "Период Возр") Есть Null 
        Тогда "Первая продажа" 
    Иначе ВычислитьВыражение("Период", "Период", , "Предыдущая", "Предыдущая", "Период Возр") 
Конец

Резюме

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

  1. Никогда не используйте функции смещения на вкладке «Вычисляемые поля», если расчет зависит от группировок отчета.
  2. Переносите формулы в «Ресурсы» и четко ограничивайте область их расчета конкретными группировками в колонке «Рассчитывать по...».
  3. Всегда явно указывайте параметры сортировки внутри функции ВычислитьВыражение, чтобы избежать ошибок при изменении порядка вывода строк пользователем.
← На главную