Как отключить расчет ресурсов по нижестоящим группировкам в отчете на СКД и избежать дублирования итогов

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

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

Разбор проблемы: почему СКД «двоит» итоги

Рассмотрим стандартную ситуацию. У нас есть трехуровневая группировка: Клиент —> Накладная —> Товар. Ресурс Оплата является реквизитом документа (шапки). В запросе мы используем ВНУТРЕННЕЕ СОЕДИНЕНИЕ документа с его табличной частью Товары. Проанализируем, что происходит на уровне данных: если в одной накладной на сумму 10 000 рублей содержится 5 разных товаров, то после соединения в выборке окажется 5 строк, и в каждой из них в поле Оплата будет стоять 10 000. При обычном суммировании СКД выдаст итог 50 000 вместо положенных 10 000.

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

Решение №1: Использование функций агрегации с группировкой по массиву

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

Разберем по шагам настройку на вкладке Ресурсы в конструкторе СКД:

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

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

Проанализируем, как работает эта функция:

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

Решение №2: Использование двух наборов данных (Dataset Link)

Если структура отчета позволяет, профессиональным подходом считается разделение данных на два независимых набора. Это полностью исключает дублирование на уровне SQL-запроса.

Рассмотрим алгоритм реализации:

  1. НаборДанных1 (ОбъектныеДанные): Пишем запрос к шапке документа (Ссылка, Партнер, СуммаДокумента).
  2. НаборДанных2 (ДетальныеЗаписи): Пишем запрос к табличной части (Ссылка, Номенклатура, Количество).
  3. На вкладке Связи наборов данных связываем их по полю Ссылка (Источник — Набор 1, Приемник — Набор 2).

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

Решение №3: Тонкая настройка через «ВычислитьВыражение»

Иногда возникают ситуации, когда использование массивов кажется избыточным. Можно попробовать использовать функцию ВычислитьВыражение с указанием области анализа. Рассмотрим пример выражения для ресурса:

ВычислитьВыражение("Сумма(Оплата)", "Накладная", , "Первая", "Первая")

Такой подход заставляет СКД брать сумму только первой записи в каждой группировке Накладная. Однако этот метод имеет существенный минус: если пользователь наложит отбор по конкретному товару, который не является первым в списке накладной, сумма может просто «исчезнуть» или рассчитаться неверно. Поэтому использование ВычислитьВыражениеСГруппировкойМассив остается более надежным вариантом.

Дополнительные советы по оформлению

Выясним причину, почему даже при правильных расчетах отчет может выглядеть неопрятно. Это часто связано с пустыми значениями (NULL). Если вы используете ЛЕВОЕ СОЕДИНЕНИЕ и для какой-то накладной нет движений по оплате, функции агрегации могут вести себя непредсказуемо.

Рекомендуем в поле выражения ресурса всегда добавлять проверку на NULL:


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

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

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

← На главную