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

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

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

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

Суть проблемы: почему обычное суммирование не работает

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

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

Решение №1: Использование функции ВычислитьВыражениеСгруппировкойМассив

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

Рассмотрим алгоритм настройки:

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

Сумма(ВычислитьВыражениеСгруппировкойМассив("Выбор Когда РазностьДат(ВычислитьВыражение(""ДатаСоздания"", , , ""Предыдущая"", ""Предыдущая""), ДатаСоздания, ""Минута"") < 5 Тогда 100 Иначе 0 Конец", "ДетальныеЗаписи"))

Разберем, что делает эта формула:

Решение №2: Реализация логики на уровне запроса (Self-Join)

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

Рассмотрим пример реализации в схеме компоновки данных:

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

ВЫБОР 
    КОГДА РАЗНОСТЬДАТ(Документы2.ДатаСоздания, Документы1.ДатаСоздания, МИНУТА) < 5 
    ТОГДА 100 
    ИНАЧЕ 0 
КОНЕЦ КАК ПолеДляИтогов

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

Важные нюансы и настройки ресурсов

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

Проанализируем вкладку «Ресурсы» подробнее:

В СКД есть колонка «Рассчитывать по...». Если вы используете первый способ (с массивом), вы можете указать, для каких именно группировок должен применяться этот расчет. Например, для «Детальных записей» оставить простое выражение, а для группировки Ответственный и Общий итог — выражение с массивом. Это позволит оптимизировать производительность отчета.

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

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

← На главную