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