При разработке отчетов на базе Системы компоновки данных (СКД) часто возникает задача: ограничить вывод данных конкретным параметром (например, менеджером, подразделением или проектом) только для одной определенной группировки, в то время как другие группировки или таблицы отчета должны выводить полные данные без этого ограничения. Типичный пример — отчет по взаиморасчетам в конфигурации «Управление торговлей 10.3», где группировку по контрагентам нужно отфильтровать по ответственному менеджеру, но итоговая таблица со смежными показателями должна оставаться полной.
В этой статье мы подробно разберем, как правильно реализовать такое поведение системы, рассмотрим базовый способ настройки отборов на уровне группировок, а также решим критические проблемы производительности СУБД, особенности работы на обычных формах в УТ 10.3 и нюансы расчета общих итогов.
Частой ошибкой начинающих разработчиков является жесткое указание параметра в секции ГДЕ основного запроса СКД. Например:
ВЫБРАТЬ
ВзаиморасчетыОстатки.Организация,
ВзаиморасчетыОстатки.Контрагент,
ВзаиморасчетыОстатки.СуммаВзаиморасчетовОстаток
ИЗ
РегистрНакопления.ВзаиморасчетыСКонтрагентами.Остатки КАК ВзаиморасчетыОстатки
ГДЕ
ВзаиморасчетыОстатки.Контрагент.Менеджер = &Менеджер
Если оставить запрос в таком виде, платформа принудительно потребует заполнения параметра &Менеджер для всего отчета. Применить его только к отдельной части структуры не получится. Чтобы решить эту задачу, выполним следующие шаги:
ГДЕ условие фильтрации по менеджеру. Полностью очистим запрос от параметра &Менеджер. Проверим вкладку «Параметры» — автоматический параметр должен исчезнуть (или мы можем отключить его вручную).Контрагент.Менеджер, вид сравнения — Равно. Правое значение оставим доступным для выбора пользователем.Теперь при формировании отчета СКД применит фильтр исключительно к выбранной ветке группировки, не затрагивая остальные таблицы.
Рассмотрим ситуацию глубже. Когда мы удалили секцию ГДЕ из основного запроса, СУБД больше не фильтрует данные на этапе извлечения из базы. Это означает, что сервер 1С:Предприятия загрузит в оперативную память абсолютно все записи регистра остатков взаиморасчетов, а фильтрация по менеджеру будет происходить «на лету» средствами процессора компоновки.
Если в базе данных хранятся сотни тысяч контрагентов, отчет мгновенно приведет к критическому падению производительности и ошибке нехватки памяти СУБД. Чтобы избежать этого, спроектируем отчет с использованием нескольких связанных наборов данных.
Выясним, как связать два набора данных для оптимизации:
ВЫБРАТЬ
ВзаиморасчетыОстатки.Организация,
ВзаиморасчетыОстатки.Контрагент,
ВзаиморасчетыОстатки.СуммаВзаиморасчетовОстаток
ИЗ
РегистрНакопления.ВзаиморасчетыСКонтрагентами.Остатки КАК ВзаиморасчетыОстатки
ВЫБРАТЬ
Контрагенты.Ссылка КАК Контрагент,
Контрагенты.ОсновнойМенеджерПокупателя КАК Менеджер
ИЗ
Справочник.Контрагенты КАК Контрагенты
ГДЕ
Контрагенты.ОсновнойМенеджерПокупателя = &Менеджер
НаборДанных1НаборДанных2Контрагент = КонтрагентМенеджер с параметром &МенеджерБлагодаря такой архитектуре СКД применит интеллектуальный алгоритм: сначала получит данные из первого набора, а затем передаст отфильтрованные по менеджеру ключевые поля во второй запрос. Это позволит минимизировать объем передаваемых данных между СУБД и сервером приложений.
Конфигурация «Управление торговлей 10.3» построена на обычных (неуправляемых) формах. В этой среде стандартный механизм быстрого доступа к пользовательским настройкам компоновки работает нестабильно, особенно когда отбор назначен не на весь отчет, а на подчиненную группировку. Пользователь просто не увидит поле выбора менеджера на форме отчета.
Для решения этой проблемы применим программную установку отбора в модуле объекта отчета при компоновке результата. Разберем по шагам этот алгоритм:
МенеджерНаФорме. Сделаем его доступным для изменения на форме.ПриКомпоновкеРезультата.
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// Получаем значение вспомогательного параметра с формы
ПараметрМенеджер = КомпоновщикНастроек.Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("МенеджерНаФорме"));
Если ПараметрМенеджер <> Неопределено И ЗначениеЗаполнено(ПараметрМенеджер.Значение) Тогда
// Находим первую группировку в структуре настроек
Если КомпоновщикНастроек.Настройки.Структура.Количество() > 0 Тогда
ГруппировкаМенеджер = КомпоновщикНастроек.Настройки.Structure[0];
// Очищаем предыдущие отборы группировки
ГруппировкаМенеджер.Отбор.Элементы.Очистить();
// Программно создаем новый элемент отбора по менеджеру контрагента
ЭлементОтбора = ГруппировкаМенеджер.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Контрагент.ОсновнойМенеджерПокупателя");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = ПараметрМенеджер.Значение;
ЭлементОтбора.Использование = Истина;
КонецЕсли;
КонецЕсли;
// Стандартный вывод отчета с программно модифицированными настройками
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.Настройки, ДанныеРасшифровки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецПроцедуры
Этот код гарантирует, что пользователь сможет комфортно выбирать менеджера на обычной форме УТ 10.3, а система сама перенаправит этот выбор в настройки нужной группировки в обход глобального ограничения.
Проанализируем еще одну важную деталь. По умолчанию в СКД отбор, установленный на уровне группировки, скрывает строки только внутри этой группировки. При этом общие итоги по отчету (Grand Totals) продолжают рассчитываться по абсолютно всем данным запроса.
Рассмотрим пример:
Если мы установим локальный отбор по Иванову для группировки «Контрагент», в строках отчета мы увидим детальные записи на сумму 150 000 руб., однако в строке «Итого» внизу отчета по-прежнему будет отображаться сумма 1 000 000 руб.
Если по бизнес-требованиям общие итоги должны пересчитываться с учетом выбранного менеджера, то использование отборов группировок вам не подходит. В таком случае необходимо использовать вариант со связанными наборами данных или применять глобальные параметры СКД. Если же логика отчета требует показать долю конкретного менеджера в общем объеме взаиморасчетов предприятия, то текущее поведение СКД с локальным отбором является абсолютно верным.