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