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

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

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

Если мы просто добавим поле в ресурсы и укажем агрегатную функцию Сумма, СКД честно сложит все детальные записи. Если выберем Максимум, то в общем итоге мы получим просто максимальное значение по всему отчету, а не сумму максимумов группировок. Разберем по шагам, как правильно и элегантно решить эту задачу несколькими способами.

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

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

Рассмотрим подробнее использование встроенной функции формирования массивов. Перейдем на вкладку «Ресурсы» и для нашего поля (назовем его НашРесурс) пропишем следующее выражение:


Сумма(ВычислитьВыражениеСГруппировкойМассив("Минимум(НашРесурс)", "НашаГруппировкаСМинимумами"))

Как это работает:

  1. Функция ВычислитьВыражениеСГруппировкойМассив заставляет СКД сначала опуститься на уровень группировки НашаГруппировкаСМинимумами (в нашем примере это Документ).
  2. Там она вычисляет Минимум(НашРесурс) для каждого узла.
  3. Затем все полученные значения собираются во внутренний массив в памяти.
  4. Внешняя агрегатная функция Сумма() обходит этот массив и складывает все его элементы.

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

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


Сумма(ВычислитьВыражениеСГруппировкойМассив("Сумма(НашРесурс)", "НашаВтораяГруппировка"))

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

Способ 2: Использование функции ВычислитьВыражениеСГруппировкойТаблицаЗначений

Посмотрим на более сложный пример. Что если нам нужно посчитать сложный итог, зависящий не от одного числа, а от нескольких колонок? Например, мы хотим рассчитать средневзвешенную цену, используя количество и сумму из детальных записей, и передать результат наверх.

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

Способ 3: Два набора данных в СКД (Левое соединение с контролем дублей)

Выясним причину одной из самых частых ошибок СКД — задвоения сумм из шапки документа. У нас есть запрос, который выбирает товары из табличной части и сумму услуг (или дополнительных расходов) из шапки или другой таблицы. Если сделать это одним набором данных, сумма расходов продублируется в каждой строке товара. Итог будет завышен в десятки раз.

Решим эту проблему архитектурно:

  1. Создаем Набор данных 1 (Товары). В нем только детальные записи: номенклатура, количество, цена.
  2. Создаем Набор данных 2 (Суммы документов/статей). В нем только ссылка на документ (или статью) и сумма расходов.
  3. Переходим на вкладку «Связи наборов данных». Указываем связь от Набора 1 к Набору 2 по полю связи (Документ или Статья).

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

Способ 4: Вычисляемые поля и настройка "Рассчитывать по..."

Рассмотрим еще один изящный метод из практики. Допустим, мы выводим группировки: «Статья затрат» -> «Номенклатура». Нам нужно выводить расходы только по статьям, а количество — везде.

Сделаем следующее:

  1. В запросе получаем числовое поле Затрата.
  2. Создаем вычисляемое поле (назовем его СуммаРасходов), но в выражении пишем просто 0 (ноль).
  3. Переходим на вкладку «Ресурсы». Для поля СуммаРасходов в колонке «Выражение» прописываем Сумма(Затрата).
  4. В колонке «Рассчитывать по...» строго указываем группировку Статья.

В итоге на уровне детальных записей и номенклатуры СКД выведет 0, а как только дойдет до группировки «Статья», сработает ресурсное выражение и рассчитается реальная сумма. Никаких искажений и дублей.

Способ 5: Управление расчетом через функцию Уровень()

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

Мы можем написать простое условие прямо в выражении ресурса:


ВЫБОР 
    КОГДА Уровень() = 0 ТОГДА 0 
    ИНАЧЕ Сумма(МойРесурс) 
КОНЕЦ

Этот подход явно указывает СКД: «Если ты находишься на уровне детальных записей, ресурс равен нулю. Во всех остальных случаях (в группировках) суммируй данные».

Способ 6: Визуальное скрытие (Условное оформление)

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

  1. Добавляем новое правило условного оформления.
  2. В оформлении устанавливаем свойство «Текст» в пустую строку (просто очищаем поле) или задаем цвет текста равным цвету фона (белый на белом).
  3. В условии отбора ничего не указываем.
  4. В оформляемых полях выбираем наш проблемный ресурс.
  5. Главное: в области использования оставляем галочку ТОЛЬКО на пункте «В детальных записях».

Вуаля! В отчете пустые аккуратные ячейки на нижнем уровне, а в группировках красуются верные сводные суммы.

Разбор нюансов: Уникальные значения и количество

Отдельно рассмотрим проблему подсчета количества уникальных объектов. Например, нам нужно посчитать уникальных клиентов (торговые точки) за месяц, с группировкой по дням.

Здесь кроется математическая ловушка бизнес-логики. Обратите внимание на разницу:

Оба варианта работают корректно с точки зрения платформы 1С, но дают совершенно разные бизнес-метрики. Внимательно собирайте требования заказчика перед выбором метода расчета итогов.

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

← На главную