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