Разработка отчетов в системе компоновки данных (СКД) часто выходит за рамки простого вывода строк из базы данных. Особенно это касается аналитических и аудиторских отчетов, где требуется не только показать первичные данные, но и произвести над ними математические операции: сложить определенные строки, найти разность между показателями из разных наборов данных или рассчитать проценты. На уровне детальных записей вычисляемые поля СКД справляются с этим отлично. Однако, когда дело доходит до вывода Общего итога, разработчики часто сталкиваются с тем, что система выдает «непонятные» или математически неверные суммы.
В этой статье мы подробно разберем, почему возникает проблема расчета итогов по вычисляемым полям, и рассмотрим эффективные практические методы получения корректных данных в общих итогах СКД.
Прежде чем переходить к настройке отчета, проанализируем ситуацию и поймем, как СКД обрабатывает формулы на разных уровнях группировки. Главная ошибка начинающих разработчиков заключается в предположении, что СКД сначала рассчитывает формулу для каждой строки, а затем просто складывает получившиеся результаты в колонке итогов. На самом деле это не так.
По умолчанию СКД рассчитывает выражение ресурса на уровне группировки (или общего итога) по той же самой формуле, но подставляет в нее уже агрегированные значения. Рассмотрим классический пример: расчет рентабельности или процента. Допустим, у нас есть формула СуммаПродаж / Себестоимость. На уровне строк формула работает верно. Но на уровне общего итога СКД выполнит деление общей суммы продаж на общую себестоимость, вместо того чтобы сложить проценты по каждой строке (что математически абсолютно верно для рентабельности, но совершенно не подходит, если вам нужно было именно сложить результаты построчных вычислений).
Если же мы имеем дело со сложными вычислениями («строку 1 сложить со строкой 5, вычесть строку 9»), или если данные поступают из разных несвязанных или частично связанных наборов данных, стандартный расчет итогов полностью ломается. Происходит так называемое «двойное агрегирование» или дублирование (замножение) записей при связи «один ко многим».
Чтобы заставить СКД сначала вычислить формулу для каждой строки детальной группировки, а затем сложить (или обработать иным образом) эти результаты на уровне общего итога, мы должны использовать специальную функцию ВычислитьВыражениеСГруппировкойМассив.
Эта функция вычисляет выражение для каждого элемента указанной группировки, помещает результаты в массив, а внешняя агрегатная функция (например, Сумма) производит их финальную обработку. Рассмотрим подробнее, как настроить такое поле на вкладке «Ресурсы» в схеме компоновки данных.
Допустим, у нас есть детальная группировка по полю Номенклатура, и вычисляемое поле ИтоговыйПоказатель. Чтобы получить корректный общий итог, в колонке «Выражение» для ресурса мы пишем следующую конструкцию:
Сумма(ВычислитьВыражениеСГруппировкойМассив("ВашеВычисляемоеПоле", "Номенклатура"))
Если расчет более сложный и включает в себя математические операции непосредственно внутри функции, мы можем прописать формулу прямо в ней:
Сумма(ВычислитьВыражениеСГруппировкойМассив("Поле1 - Поле2 + Поле3", "ДетальнаяГруппировка"))
Этот подход гарантирует, что на уровне общих итогов мы получим чистую сумму результатов расчетов по каждой номенклатурной позиции, избежав искажения данных из-за наложения агрегатных функций.
СКД обладает мощным, но редко используемым функционалом — возможностью задавать разные формулы расчета одного и того же ресурса для разных уровней группировок отчета. Мы можем настроить систему так, чтобы для строк применялась одна логика, а для общих итогов — совершенно другая.
Разберем по шагам, как это реализовать на вкладке «Ресурсы»:
Организация, Контрагент). Задайте для них стандартную формулу расчета (например, обычную сумму).Этот способ незаменим, когда логика итогов принципиально отличается от логики детальных строк.
Если перед вами стоит задача «что-то прибавить, а что-то отнять» в общем итоге в зависимости от определенных условий (например, от типа операции, статьи аудита или бизнес-направления), лучшим решением будет использование конструкции ВЫБОР КОГДА непосредственно внутри агрегатных функций в ресурсах.
Посмотрим на пример выражения в ресурсах для расчета общего итога с условным сложением и вычитанием строк:
Сумма(ВЫБОР КОГДА СтатьяАудита = "Доходы" ТОГДА ВычисляемоеПоле ИНАЧЕ -ВычисляемоеПоле КОНЕЦ)
Также можно комбинировать несколько предопределенных ресурсов, выстраивая сложные логические цепочки:
Сумма(Ресурс1) - Сумма(Ресурс2) + ВЫБОР КОГДА Сумма(Ресурс3) > 0 ТОГДА Сумма(Ресурс3) ИНАЧЕ 0 КОНЕЦ
Использование условных операторов на уровне расчета ресурсов позволяет гибко управлять итоговыми показателями без необходимости дублировать вычисляемые поля в схеме.
Если ваш отчет построен на нескольких наборах данных (например, один набор получает плановые показатели, второй — фактические, а третий — результаты аудиторских корректировок), и они связаны в СКД связью «один ко многим», стандартное суммирование неизбежно приведет к «замножению» сумм из левой (главной) таблицы.
Выясним причину: СКД выполняет соединение наборов данных аналогично левому соединению в SQL. Если одной строке из левой таблицы соответствует 5 строк из правой, левое значение повторится 5 раз, и обычная функция Сумма() сложит его тоже 5 раз.
Для решения этой проблемы мы можем использовать комбинацию функций Максимум (или Среднее) и уже знакомого нам массива группировок:
Сумма(ВычислитьВыражениеСГруппировкойМассив("Максимум(ПолеЛевогоНабора)", "КлючСвязиЛевогоНабора"))
В данном случае выражение сначала выбирает только одно (максимальное) уникальное значение для каждого ключевого поля, исключая дубли, созданные связью наборов, а затем безопасно суммирует их на уровне общего итога.
Если формулы отчета перегружены условными операторами, связи между наборами данных слишком запутанные, а итоговые показатели никак не хотят сходиться из-за сложной математики, настоятельно рекомендуется перенести расчеты из СКД на уровень кода 1С.
Вместо использования нескольких связанных наборов данных типа «Запрос» непосредственно в компоновщике, соберите все данные программно в модуле объекта отчета. Произведите всю необходимую математику, включая вычитание одних строк из других и расчет промежуточных итогов, в обычной Таблице Значений. Затем передайте эту готовую, предварительно рассчитанную «плоскую» таблицу в СКД через Набор данных - Объект.
При таком подходе СКД избавится от необходимости выполнять сложную аналитическую агрегацию и будет использоваться исключительно как удобный инструмент визуализации, вывода структуры и оформления отчета, что сбережет время разработчика и гарантирует 100% точность выводимых итогов.