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