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

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

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

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

Понимание проблемы: почему не работает обычная сумма

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

Проанализируем ситуацию: нам нужно заставить систему выполнить двухэтапный расчет:

  1. На уровне группировки "ТС" определить последнее значение.
  2. На уровне "Общего итога" собрать эти значения в массив и просуммировать их.

Способ 1. Разделение формул в настройках ресурсов

Первое, что мы должны сделать — это использовать возможность СКД задавать разные выражения для разных уровней расчета. На вкладке "Ресурсы" одно и то же поле можно добавить несколько раз, указывая в колонке "Рассчитывать по..." конкретную группировку или "Общий итог".

Рассмотрим настройку ресурсов для нашего случая:

Для группировки "ТС" (Транспортное средство):

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

Здесь мы явно указываем, что хотим получить значение из последней строки внутри каждой группы ТС.

Для "Общего итога":

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

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

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


Сумма(ВычислитьВыражениеСГруппировкойМассив("Максимум(ВычисляемоеЗначение)", "ТС"))

Разберем, что происходит внутри этой формулы:

Важный нюанс: Вложенные вычисления для точности

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


Сумма(ВычислитьВыражениеСГруппировкойМассив("ВычислитьВыражение(""Сумма(Значение)"", , , ""Последняя"", ""Последняя"")", "ТС"))

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

Почему важна сортировка

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

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

Альтернатива: Подготовка данных в запросе

Если выражения в ресурсах становятся слишком громоздкими (как в Сообщении 12), стоит рассмотреть вариант переноса логики в текст запроса. Мы можем подготовить временную таблицу, в которой уже будут отобраны только нужные "последние" записи для каждого ТС.

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

В этом случае в ресурсах нам достаточно будет написать простую Сумма(Значение), и она корректно отработает на всех уровнях, так как лишних записей просто не будет в выборке.

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

← На главную