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