Как программно установить отбор для разных вариантов отчета СКД в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке сложных аналитических отчетов на базе системы компоновки данных (СКД) часто возникает ситуация, когда один отчет содержит несколько различных вариантов. Каждый вариант может базироваться на своем наборе данных, а смысловые поля (например, менеджер или ответственный) могут иметь разные наименования в схеме. Если попытаться жестко добавить отбор по полю, которого нет в текущем наборе данных или структуре выбранного варианта, отчет вернет пустой результат или выдаст ошибку.

Разберем основные причины такого поведения и рассмотрим правильные подходы к программной установке отборов в зависимости от используемого варианта отчета.

Почему безусловное добавление отбора приводит к пустым результатам

Проанализируем типовую ошибку, с которой сталкиваются разработчики при попытке задать отбор напрямую в модуле объекта:

  1. Несуществующее поле в структуре варианта. Если в текущем варианте отчета отсутствует поле компоновки данных (например, МенеджерДокумента), СКД накладывает условие на несуществующее поле, из-за чего выборка оказывается пустой.
  2. Модификация настроек без их применения. Метод КомпоновщикНастроек.ПолучитьНастройки() возвращает копию текущих настроек. Если после изменения не выполнить обратную загрузку через КомпоновщикНастроек.ЗагрузитьНастройки(...), компоновщик не применит новые параметры к макету.
  3. Дублирование условий при повторном формировании. Простое добавление элемента через метод Добавить() без предварительного поиска или очистки приводит к разрастанию коллекции отборов при каждом нажатии кнопки формирования.

Способ 1. Проверка доступности поля перед установкой отбора

Наиболее надежный и гибкий подход заключается не в жесткой привязке к имени варианта, а в динамической проверке: доступно ли конкретное поле для отбора в текущих настройках схемы компоновки данных. Это позволяет избежать ошибок даже в том случае, если пользователь переименует вариант или создаст пользовательскую копию.

Рассмотрим реализацию в процедуре ПриКомпоновкеРезультата модуля объекта отчета:


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

КонецПроцедуры

Способ 2. Определение варианта через ключ или наименование

Если логика отборов строго привязана к определенным вариантам отчета, можно выполнить проверку по имени или ключу текущего варианта. Посмотрим на пример проверки через дополнительные свойства настроек:


НастройкиОтчета = КомпоновщикНастроек.ПолучитьНастройки();

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

Обратите внимание: проверка по наименованию варианта чувствительна к переименованию. Если отчет разрабатывается с использованием стандартных механизмов БСП, для однозначной идентификации рекомендуется использовать свойство КлючВарианта.

Архитектурные рекомендации по проектированию СКД

Чтобы избежать усложнения программного кода в модулях, разберем альтернативные решения на уровне архитектуры схемы компоновки данных:

  1. Унификация псевдонимов полей. На вкладке «Наборы данных» в схеме компоновки данных назначьте одинаковые псевдонимы полям в разных наборах данных (например, переименуйте МенеджерДокумента и Ответственный в единое поле Менеджер). В этом случае отбор накладывается одинаково на все варианты отчета.
  2. Использование общих параметров СКД. Вместо динамического добавления элементов в коллекцию Отбор, добавьте в запросы наборов данных параметр (например, &ТекущийМенеджер). Установка значения параметра выполняется централизованно через коллекцию КомпоновщикНастроек.Настройки.ПараметрыДанных и одинаково применяется ко всем источникам данных.
← На главную