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

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

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

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

Способ 1. Использование коллекции ДоступныеПоляОтбора (Рекомендуемый)

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

Рассмотрим по шагам, как получить тип поля с помощью метода НайтиПоле():

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

Посмотрим на пример реализации:


// Инициализация (если компоновщик создается программно)
ИсточникНастроек = Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновкиДанных);
КомпоновщикНастроек.Инициализировать(ИсточникНастроек);

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

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

Способ 2. Рекурсивный обход групп и элементов отбора

Отбор в СКД может содержать не только одиночные элементы, но и группы (ГруппаЭлементовОтбораКомпоновкиДанных с видами соединений «И», «ИЛИ», «НЕ»). Для полного анализа структуры настроек разберем процедуру рекурсивного обхода.

Напишем универсальную функцию для извлечения всех используемых полей:


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

Способ 3. Разбор пути к данным через метаданные

Если по какой-либо причине коллекция доступных полей недоступна (например, при анализе сохраненного XML-файла настроек без инициализации схемы), можно разобрать строковое представление поля через точку.

Проанализируем алгоритм:

  1. Преобразуем ПолеКомпоновкиДанных в строку с помощью Строка(ЭлементОтбора.ЛевоеЗначение).
  2. Разбиваем полученную строку на массив подстрок по разделителю "." (точка).
  3. Первый элемент массива сопоставляем с полями наборов данных схемы компоновки для определения базового типа.
  4. Последующие элементы массива последовательно разыменовываем через реквизиты объекта в Метаданные.

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

← На главную