При работе с Системой компоновки данных (СКД) разработчики часто сталкиваются с необходимостью вычислить сложный показатель на уровне детальных записей (или низкой группировки) и корректно просуммировать полученные результаты на уровне вышестоящих итогов. Типичный пример — расчет доли задолженности или средневзвешенных коэффициентов. Проблема заключается в том, что язык выражений СКД имеет жесткие ограничения на вложенность агрегатных функций, что приводит к синтаксическим ошибкам вида «Ошибка в выражении».
В этой статье мы проанализируем, почему возникают такие сложности, и рассмотрим несколько эффективных способов их решения.
Разберем типичную ситуацию: у нас есть формула, которая отлично работает на уровне группировки ДоговорКонтрагента, но при попытке рассчитать итог по Контрагенту система выдает ошибку. Рассмотрим пример исходной формулы:
Сумма(СуммаВзаиморасчетовОстаток) / ВычислитьВыражение("Сумма(СуммаВзаиморасчетовОстаток)", "Контрагент", "Группировка") * ДоговорКонтрагентаДопустимоеЧислоДнейЗадолженности
Когда мы пытаемся обернуть это выражение в другую функцию Сумма() или использовать ВычислитьВыражениеСГруппировкойМассив() для получения итогов по контрагенту, платформа 1С сообщает о синтаксической ошибке. Это происходит потому, что функции языка выражений компоновки данных не поддерживают прямую вложенность агрегатов. Система не может одновременно вычислять итог по текущей группировке и итерироваться по массиву итогов вложенных группировок внутри одного выражения.
Самый надежный способ, к которому часто прибегают опытные разработчики, — это расчет всех необходимых коэффициентов непосредственно в тексте запроса. Проанализируем этот подход:
СГРУППИРОВАТЬ ПО.После этого в СКД нам остается только добавить поле в ресурсы и использовать обычную функцию Сумма(). Это снимает нагрузку с процессора компоновки и исключает ошибки вложенности. Однако этот метод не всегда удобен, если расчет зависит от динамических настроек отчета или состава группировок, выбранных пользователем.
СКД позволяет задавать разные выражения для одного и того же ресурса в зависимости от того, для какой группировки рассчитывается итог. Рассмотрим, как это настроить на закладке Ресурсы:
ДоговорКонтрагента). Здесь укажем нашу исходную формулу.Контрагент) и Общий итог.
Сумма(ВычислитьВыражениеСГруппировкойМассив("Сумма(СуммаВзаиморасчетовОстаток) * ДоговорЧислоДней / ВычислитьВыражение(""Сумма(СуммаВзаиморасчетовОстаток)"", ""Контрагент"")", "ДоговорКонтрагента"))
Важный нюанс: Обратите внимание на использование двойных кавычек внутри строки выражения. При передаче строкового параметра в функцию ВычислитьВыражениеСГруппировкойМассив все внутренние кавычки должны быть экранированы.
Чтобы упростить структуру ресурсов и сделать отчет более читаемым, мы можем вынести часть расчетов в Вычисляемые поля. Посмотрим на алгоритм:
БазаДляРасчета), где будет храниться значение ДоговорКонтрагентаДопустимоеЧислоДнейЗадолженности или другой коэффициент.Контрагента будем оперировать уже этим полем.Для наиболее сложных случаев, когда требуется статистическая обработка или специфическая классификация (например, ABC-анализ), проанализируем применение функции ГрупповаяОбработка(). Эта функция позволяет обработать массив значений внутри контекста группировки.
Пример синтаксиса для использования в выражении ресурса:
ABCКлассификация(ГрупповаяОбработка("Сумма(СуммаОборот)"))
Хотя этот метод реже используется в повседневных задачах, он является мощным инструментом, когда стандартных агрегатных функций недостаточно для реализации бизнес-логики.
Если вы продолжаете получать синтаксическую ошибку, проверьте следующие моменты:
ВычислитьВыражение, доступны в соответствующих группировках.ЕстьNull(Поле, 0) в запросе или вычисляемом поле.Выбирая между расчетом в запросе и использованием сложных выражений СКД, всегда оценивайте объем данных. Если записей очень много, расчет в запросе будет работать значительно быстрее, так как платформа оптимизирует его на уровне SQL-сервера.