Как в СКД реализовать расчет итогов для «замысловатых» вычисляемых полей по группировкам?

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

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

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

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

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

Решение через функцию ВычислитьВыражениеСГруппировкойМассив

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

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

  1. Определим выражение для уровня «Сделка»: СУММА(СуммаПродажи) + МАКСИМУМ(Сделка.Реквизит1).
  2. Для уровня «Партнер» и «Общий итог» обернем это выражение в специальную функцию.

Итоговая формула для расчета по полю «Поле 1» будет выглядеть следующим образом:


Сумма(ВычислитьВыражениеСГруппировкойМассив("СУММА(СуммаПродажи) + МАКСИМУМ(Сделка.Реквизит1)", "Сделка"))

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

Настройка на закладке «Ресурсы» — правильный подход

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

Посмотрим на пример настройки ресурсов:

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

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

Важные нюансы и ограничения

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

1. Проблема пустых значений (NULL). Если Сделка.Реквизит1 не заполнен, то прибавление его к сумме может дать NULL для всей сделки. Рекомендуем всегда использовать функцию ЕСТЬNULL. Проанализируем исправленный код:

Сумма(СуммаПродажи) + Максимум(ЕСТЬNULL(Сделка.Реквизит1, 0))

2. Производительность. Функция ВычислитьВыражениеСГруппировкойМассив выполняется в памяти сервера приложений 1С, а не в СУБД. Если в отчете выводятся десятки тысяч партнеров и сотни тысяч сделок, формирование отчета может замедлиться. В таких случаях стоит рассмотреть возможность предварительного расчета данных в основном запросе СКД с помощью временных таблиц.

3. Зависимость от структуры. Выясним важную деталь: расчет жестко привязан к имени группировки (в нашем примере — "Сделка"). Если пользователь в настройках отчета удалит эту группировку или изменит её имя, формула перестанет работать и может выдать ошибку. Для создания универсальных отчетов такие зависимости стараются минимизировать.

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

Альтернативный вариант: Связи наборов данных

Если логика становится слишком сложной для одного выражения, мы можем пойти другим путем. Создадим два набора данных — запроса:

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

← На главную