Как программно получить значение отбора в модуле объекта отчета СКД?

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

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

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

Понимание структуры компоновщика настроек

Прежде чем переходить к коду, проанализируем, где именно хранятся настройки. В объекте КомпоновщикНастроек есть три важные коллекции:

  1. Настройки (Settings): Это настройки, заданные разработчиком в схеме компоновки по умолчанию.
  2. ПользовательскиеНастройки (UserSettings): Это именно те элементы (отборы, параметры, поля), которые вынесены на форму и которые видит пользователь.
  3. ФиксированныеНастройки (FixedSettings): Настройки, установленные программно, которые пользователь не может изменить.

Для получения итогового результата, который учитывает все три источника, необходимо использовать метод КомпоновщикНастроек.ПолучитьНастройки(). Именно этот метод возвращает "финальный" вариант настроек, который будет применен при выполнении компоновки.

Способ 1: Простой перебор элементов (линейный поиск)

Если структура отчетов простая и вы уверены, что пользователь не создает вложенных групп (И/ИЛИ), можно использовать цикл для поиска нужного поля. Рассмотрим пример получения значения отбора по полю ДоговорКлиента.

Выясним причину, почему поиск по индексу (например, Получить(0)) опасен: пользователь может изменить порядок отборов, добавить новые или удалить старые. В этом случае ваш код либо упадет с ошибкой, либо получит неверные данные.

Правильный подход выглядит следующим образом:


// В модуле объекта отчета (например, в событии ПриКомпоновкеРезультата)
Настройки = КомпоновщикНастроек.ПолучитьНастройки();

ТребуемоеПоле = Новый ПолеКомпоновкиДанных("ДоговорКлиента");
ЗначениеДоговора = Неопределено;

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

Если ЗначениеДоговора = Неопределено Тогда
    // Обработка ситуации, когда отбор не заполнен или не найден
КонецЕсли;

Способ 2: Рекурсивный поиск во вложенных группах

Рассмотрим более сложную ситуацию. Пользователь может сгруппировать отборы (например, "Договор = А ИЛИ Договор = Б"). В этом случае линейный цикл из предыдущего примера не найдет поле, так как оно будет находиться внутри объекта ГруппаЭлементовОтбораКомпоновкиДанных.

Разберем по шагам, как реализовать универсальную функцию поиска:


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

Использование этой функции в модуле объекта:


Настройки = КомпоновщикНастроек.ПолучитьНастройки();
ДоговорКлиента = НайтиЗначениеОтбора(Настройки.Отбор.Элементы, "ДоговорКлиента");

Способ 3: "Зеркальный" параметр (самый надежный)

Проанализируем профессиональный прием, который часто используют опытные разработчики 1С. Чтобы не "бегать" по коллекции отборов, можно связать отбор с параметром СКД.

В схеме СКД на закладке "Параметры" создайте параметр ДоговорКлиента. Затем на закладке "Настройки" -> "Отбор" добавьте отбор по полю ДоговорКлиента, а в колонке "Использование" укажите, что это поле связано с созданным параметром.

Теперь получить значение гораздо проще, так как параметры доступны по имени:


Настройки = КомпоновщикНастроек.ПолучитьНастройки();
ПараметрДоговор = Настройки.ПараметрыДанных.Элементы.Найти("ДоговорКлиента");

Если ПараметрДоговор <> Неопределено И ПараметрДоговор.Использование Тогда
    ЗначениеДоговора = ПараметрДоговор.Значение;
КонецЕсли;

Важные нюансы при работе с типами данных

При программном извлечении значения отбора важно учитывать ВидСравнения. Посмотрим на пример: если пользователь выбрал вид сравнения В списке, то в свойстве ПравоеЗначение будет находиться не ссылка на один объект, а объект типа СписокЗначений.

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

Также стоит помнить о методе КомпоновщикНастроек.Настройки.ПараметрыДанных.НайтиЗначениеПараметра(). Это встроенный метод платформы, который позволяет быстро найти объект параметра по его имени (типа ПараметрКомпоновкиДанных), что гораздо эффективнее ручного перебора коллекций.

Заключение

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

← На главную