При разработке отчетов в системе компоновки данных (СКД) программисты часто сталкиваются с задачей, когда данные в колонках должны визуально объединяться, а итоги по этим колонкам должны рассчитываться не простым суммированием, а по определенной логике — например, как сумма максимальных значений по заказам. Давайте подробно разберем, как реализовать подобный функционал, используя стандартные и расширенные возможности СКД.
Типичная ситуация: в отчете есть группировка Заказ, внутри которой находятся детальные записи (например, номенклатура или подразделения). Если мы просто укажем ресурс Сумма(СуммаЗаказа), система сложит сумму заказа столько раз, сколько строк в детальных записях. Если укажем Максимум(СуммаЗаказа), то на уровне общих итогов мы получим максимум среди всех заказов, а не их сумму.
Проанализируем решение этой проблемы с помощью функции ВычислитьВыражениеСГруппировкойМассив. Это мощный инструмент, который позволяет сначала произвести расчет внутри вложенной группировки, а затем агрегировать полученный массив на верхнем уровне.
Для поля ресурса СуммаЗаказа в поле "Выражение" на вкладке "Ресурсы" следует написать следующую конструкцию:
Сумма(ВычислитьВыражениеСГруппировкойМассив("Максимум(СуммаЗаказа)", "Заказ"))
Разберем по шагам, что здесь происходит:
Заказ.Максимум(СуммаЗаказа). Это гарантирует, что даже если в заказе 10 строк, значение суммы будет взято один раз.Сумма() складывает все элементы этого массива, выдавая корректный общий итог.Выясним причину, по которой данные начинают "дублироваться". Часто это происходит из-за соединения таблиц в одном запросе. Чтобы этого избежать, мы можем разделить данные на два набора (два разных запроса).
Рассмотрим пример: в первом наборе данных мы выбираем только общие сведения о заказах (Номер, Дата, Сумма), а во втором наборе — детальные записи (Заказ, Подразделение, Работа). Затем на вкладке "Связи наборов данных" мы связываем их по полю Заказ.
Преимущества такого подхода:
СуммаЗаказа приходит из первого набора, где оно уникально для каждого заказа.Сумма(СуммаЗаказа), так как компоновщик сам сопоставит значения.Если мы все же используем один запрос, важно правильно настроить роли полей на вкладке "Набор данных". Для поля Заказ необходимо указать, что оно является измерением. Для ресурса СуммаЗаказа в колонке "Роль" можно проверить параметры родительских полей.
Посмотрим на параметр "Игнорировать значения NULL". Это полезно, когда при левом соединении для некоторых строк детальных записей отсутствуют данные. Правильная расстановка ролей позволяет СКД корректно определять границы группировок и не "размножать" итоги там, где это не требуется.
Когда пользователь просит "объединить строки в колонку", он чаще всего имеет в виду визуальное схлопывание одинаковых значений. В СКД это настраивается на вкладке "Настройки" — "Другие настройки".
Проанализируем ключевые параметры:
Если стандартное объединение не помогает, воспользуемся Макет оформлений. На вкладке "Макеты" мы можем создать собственный макет для группировки или поля. Это позволяет нам жестко задать область ячеек, которая будет выводиться для конкретного уровня отчета, реализуя практически любой сложный дизайн.
Иногда нужно скрыть повторяющиеся значения программно, не меняя структуру запроса. Для этого можно использовать системное поле Уровень.
Рассмотрим алгоритм действий:
СистемныеПоля.Уровень Больше 1 (или другой уровень, где не нужно показывать сумму).СуммаЗаказа).Таким образом, значение будет рассчитано, но визуально отобразится только на нужном нам уровне группировки.
Профессиональный подход к разработке сложных отчетов заключается в подготовке данных еще на уровне текста запроса. Вместо того чтобы заставлять СКД бороться с дублями, мы можем подготовить данные заранее.
Разберем пример структуры запроса:
// Помещаем суммы заказов во временную таблицу
ВЫБРАТЬ
ЗаказСсылка КАК Заказ,
Сумма(СуммаДокумента) КАК ИтоговаяСумма
ПОМЕСТИТЬ ВТ_СуммыЗаказов
ИЗ
Документ.ЗаказКлиента
СГРУППИРОВАТЬ ПО
ЗаказСсылка;
// Основной запрос
ВЫБРАТЬ
Т_Детали.Заказ,
Т_Детали.Подразделение,
Т_Суммы.ИтоговаяСумма
ИЗ
ВТ_ДетальныеЗаписи КАК Т_Детали
ЛЕВОЕ СОЕДИНЕНИЕ
ВТ_СуммыЗаказов КАК Т_Суммы ПО Т_Детали.Заказ = Т_Суммы.Заказ
При такой структуре СКД получит уже подготовленные данные, и риск ошибки в расчете итогов будет минимальным. Мы совместно проанализировали основные способы решения задачи и можем сделать вывод: для простых отчетов достаточно Авто объединения ячеек, для сложных расчетов итогов лучше использовать ВычислитьВыражениеСГруппировкойМассив, а для гарантированной точности данных — связи наборов данных или временные таблицы.