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

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

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

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

Почему возникает ошибка при расчете итогов?

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

Сумма(СуммаВзаиморасчетовОстаток) / ВычислитьВыражение("Сумма(СуммаВзаиморасчетовОстаток)", "Контрагент", "Группировка") * ДоговорКонтрагентаДопустимоеЧислоДнейЗадолженности

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

Решение 1: Перенос логики расчета в запрос

Самый надежный способ, к которому часто прибегают опытные разработчики, — это расчет всех необходимых коэффициентов непосредственно в тексте запроса. Проанализируем этот подход:

  1. Мы заранее подготавливаем данные во временных таблицах.
  2. Рассчитываем общие суммы по контрагентам с помощью СГРУППИРОВАТЬ ПО.
  3. Соединяем эти данные с основной таблицей и получаем готовый коэффициент для каждой строки.

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

Решение 2: Настройка ресурсов по отдельным группировкам

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

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

Сумма(ВычислитьВыражениеСГруппировкойМассив("Сумма(СуммаВзаиморасчетовОстаток) * ДоговорЧислоДней / ВычислитьВыражение(""Сумма(СуммаВзаиморасчетовОстаток)"", ""Контрагент"")", "ДоговорКонтрагента"))

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

Решение 3: Использование промежуточных вычисляемых полей

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

  1. Создадим вычисляемое поле (например, БазаДляРасчета), где будет храниться значение ДоговорКонтрагентаДопустимоеЧислоДнейЗадолженности или другой коэффициент.
  2. В настройках ресурсов для расчета на уровне Контрагента будем оперировать уже этим полем.
  3. Если необходимо вычислить долю, используем пользовательские поля. Они часто корректнее обрабатывают относительные величины при делении по разным уровням группировок.

Решение 4: Использование функции ГрупповаяОбработка

Для наиболее сложных случаев, когда требуется статистическая обработка или специфическая классификация (например, ABC-анализ), проанализируем применение функции ГрупповаяОбработка(). Эта функция позволяет обработать массив значений внутри контекста группировки.

Пример синтаксиса для использования в выражении ресурса:

ABCКлассификация(ГрупповаяОбработка("Сумма(СуммаОборот)"))

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

Рекомендации по отладке

Если вы продолжаете получать синтаксическую ошибку, проверьте следующие моменты:

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

← На главную