При разработке отчетов на Системе Компоновки Данных (СКД) мы часто сталкиваемся с задачей объединения данных из "шапки" документа и его табличной части. Типичный пример: отчет по ЗаказамКлиентов, где нужно вывести перечень товаров (Номенклатуру) и общую сумму заказа.
Проблема возникает в момент расчета общих итогов. Поскольку при соединении данных сумма документа дублируется для каждой строки товара, стандартная функция Сумма() в ресурсах складывает эти дубли, выдавая некорректный, завышенный результат. Рассмотрим подробно, как решить эту задачу и получить правильные цифры.
Представим структуру данных, которую мы получаем в запросе:
Если мы просто укажем в ресурсах Сумма(СуммаДокумента), система сложит 200 + 200 и покажет итог 400, хотя реальная сумма заказа — 200. Давайте разберем способы, как заставить СКД считать правильно.
Самый надежный и современный способ, работающий в платформе 1С (начиная с версий 8.2.14), заключается в использовании функции ВычислитьВыражениеСГруппировкойМассив. Она позволяет сначала "свернуть" данные по группировке, а потом просуммировать уникальные значения.
Рассмотрим настройку на вкладке "Ресурсы":
СуммаДокумента.ОбщийИтог (или иерархию, если нужно).
Сумма(ВычислитьВыражениеСГруппировкойМассив("Максимум(СуммаДокумента)", "ЗаказКлиента"))
Как это работает:
ЗаказКлиента.Максимум(СуммаДокумента). Поскольку внутри одного заказа сумма одинакова во всех строках, максимум вернет верное число (200).Сумма() складывает значения этого массива.Для самих группировок (строк заказа) в ресурсах можно оставить выражение Максимум(СуммаДокумента) и рассчитывать его по группировке ЗаказКлиента.
Если отчет сложный, имеет смысл изменить архитектуру схемы компоновки, разделив данные на два независимых набора. Это исключает дублирование данных на уровне источника.
Порядок действий:
Ссылка, СуммаДокумента, Контрагент).Ссылка, Номенклатура, СуммаСтроки).Ссылка.В этом случае СКД понимает, что СуммаДокумента относится к "родительской" записи. При расчете итогов система сама корректно агрегирует данные, не умножая сумму документа на количество строк товаров.
Иногда возникает соблазн просто посчитать сумму по колонке табличной части, например, использовать формулу Сумма(СуммаСтроки) вместо суммы документа. Давайте проанализируем, почему это может привести к ошибке.
Как верно замечено в обсуждении, если пользователь наложит отбор на отчет (например, Номенклатура = "Товар А"), то:
Сумма(СуммаСтроки) покажет стоимость только этой строки (например, 100 р.).СуммаДокумента в базе данных остается неизменной (200 р.).Если ваша задача — показать именно полную сумму документа, независимо от того, какие товары отобраны фильтром, метод суммирования строк не подойдет. Необходимо использовать Способ 1 или Способ 2, описанные выше.
Чтобы отчет выглядел красиво, часто комбинируют функции для разных уровней группировок. На вкладке "Ресурсы" можно добавить одно поле несколько раз:
СуммаДокумента | Выражение: Максимум(СуммаДокумента) | Рассчитывать по: ЗаказКлиента.
СуммаДокумента | Выражение: Сумма(ВычислитьВыражениеСГруппировкойМассив("Максимум(СуммаДокумента)", "ЗаказКлиента")) | Рассчитывать по: ОбщийИтог.