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