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

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

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

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

Выясняем причину: почему двоятся итоги?

Давайте проанализируем ситуацию на примере. Допустим, у нас есть один Заказ покупателя №1 на сумму 100 000 рублей. В рамках этого заказа создано два подчиненных документа Заказ на производство №1 и Заказ на производство №2. При левом соединении этих таблиц в запросе СКД получит две строки:

  1. Заказ покупателя №1 (100 000 руб.) -> Заказ на производство №1 (Количество: 5)
  2. Заказ покупателя №1 (100 000 руб.) -> Заказ на производство №2 (Количество: 10)

Если мы укажем для поля СуммаЗаказа стандартное выражение ресурса Сумма(СуммаЗаказа), система сложит 100 000 из первой строки и 100 000 из второй. Общий итог по отчету покажет 200 000 рублей вместо реальных 100 000. Наша задача — заставить СКД выводить сумму только на уровне головного документа и корректно складывать эти суммы в общих итогах, игнорируя дубли подчиненных строк.

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

Это классический и самый гибкий способ решения проблемы непосредственно через настройки ресурсов компоновки данных. Он позволяет управлять расчетом итогов на разных уровнях группировок без изменения структуры запроса.

Разберем этот метод по шагам:

  1. Перейдем на вкладку «Ресурсы» в схеме компоновки данных.
  2. Добавим наше поле СуммаЗаказа (или СуммаОплаты) в список ресурсов несколько раз, чтобы настроить расчет для каждой группировки индивидуально.
  3. Для первой строки ресурса настроим расчет только для группировки верхнего уровня (в нашем случае это ДокЗаказПокупателя):
    • Выражение: Максимум(СуммаЗаказа) (поскольку в рамках одного заказа сумма всегда одинакова, функция Максимум или Среднее вернет корректное исходное значение заказа).
    • Рассчитывать по: Указываем только группировку ДокЗаказПокупателя.
  4. Для подчиненных группировок (например, ЗаказНаПроизводство и Номенклатура) мы либо вообще не добавляем строки ресурсов, либо явно оставляем выражение пустым. Благодаря этому на нижних уровнях иерархии в колонках сумм будет пустота, что визуально избавит отчет от дублей.
  5. Теперь настроим расчет общего итога по отчету. Для этого добавим еще одну строку для ресурса СуммаЗаказа:
    • Выражение:
      
      Сумма(ВычислитьВыражениеСГруппировкойМассив("Максимум(СуммаЗаказа)", "ДокЗаказПокупателя"))
      
    • Рассчитывать по: Выбираем только значение ОбщийИтог.

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

Решение №2: Использование двух наборов данных и связей в СКД

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

Проанализируем этот подход подробнее:

  1. Создаем НаборДанных1 (Заказы покупателей):

    Пишем простой запрос, который выбирает только уникальные данные по заказам покупателей и их суммы:

    
    ВЫБРАТЬ
        ЗаказПокупателя.Ссылка КАК ДокЗаказПокупателя,
        ЗаказПокупателя.СуммаДокумента КАК СуммаЗаказа
    ИЗ
        Документ.ЗаказПокупателя КАК ЗаказПокупателя
    
  2. Создаем НаборДанных2 (Производство):

    Пишем второй запрос, который выбирает подчиненные документы и номенклатуру:

    
    ВЫБРАТЬ
        Выпуск.ЗаказПокупателя КАК ДокЗаказПокупателя,
        Выпуск.ЗаказНаПроизводство КАК ДокЗаказНаПроизводство,
        Выпуск.Номенклатура КАК Номенклатура,
        Выпуск.Количество КАК Количество
    ИЗ
        РегистрНакопления.ВыпускПродукции КАК Выпуск
    
  3. Настраиваем связи наборов данных:

    Переходим на вкладку «Связи наборов данных». Добавляем новую строку связи:

    • Источник связи: НаборДанных1
    • Приемник связи: НаборДанных2
    • Условие связи: ДокЗаказПокупателя = ДокЗаказПокупателя
  4. Настраиваем ресурсы:

    Теперь на вкладке «Ресурсы» мы можем определить поле СуммаЗаказа как обычную сумму: Сумма(СуммаЗаказа) без указания конкретных группировок.

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

Почему условное оформление — это плохой путь?

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

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

Использовать условное оформление для решения этой задачи категорически не рекомендуется.

Резюме

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

← На главную