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