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