К статье
Практический материал

Разработка и Конфигурация · 12 мин

1С: как обратиться к метаданным

Как обратиться к метаданным в 1С: коллекция Метаданные, методы НайтиПоПолномуИмени, ПолучитьФункциональнуюОпцию, работа с реквизитами и формами объектов конфигурации.

Метаданные в 1С — это описание структуры конфигурации: справочники, документы, регистры, их реквизиты, табличные части, формы и прочие объекты. Обращение к метаданным из встроенного языка нужно, когда код должен работать универсально: построить отчёт по произвольному объекту, проверить наличие реквизита, сформировать список документов определённого вида или реализовать механизм, не привязанный к конкретной конфигурации.

Главная точка входа — глобальное свойство Метаданные. Через него доступны все коллекции объектов конфигурации: Метаданные.Справочники, Метаданные.Документы, Метаданные.РегистрыСведений и так далее. Каждый элемент коллекции — это объект описания метаданного, из которого можно прочитать имя, синоним, состав реквизитов, длину кода и другие свойства, заданные в конфигураторе.

Важно понимать различие: метаданные описывают структуру, а не данные. Получив объект Метаданные.Справочники.Номенклатура, вы не получите сами элементы справочника — только информацию о том, какие у него реквизиты, какая длина наименования, есть ли иерархия. Для доступа к данным используются менеджеры объектов (Справочники.Номенклатура) и запросы.

Что такое метаданные и когда к ним обращаются

Каждый объект конфигурации, который разработчик создаёт в конфигураторе, получает описание в дереве метаданных. Во время выполнения это описание доступно только для чтения: из кода нельзя добавить реквизит в справочник или изменить длину наименования — такие изменения выполняются только через конфигуратор с последующим обновлением структуры базы данных.

Типовые сценарии обращения к метаданным:

  • универсальные обработки переноса и обмена данными, которые обходят все объекты конфигурации;
  • построение динамических запросов, когда имя таблицы известно только в момент выполнения;
  • проверка наличия объекта или реквизита в конфигурации (актуально для внешних обработок, работающих в разных базах);
  • заполнение списков выбора видами документов или справочников;
  • получение представления объекта — синонима — для вывода пользователю.

Базовый синтаксис обращения через коллекцию Метаданные

Самый простой способ — прямое обращение по имени объекта через соответствующую коллекцию:

МетаСправочник = Метаданные.Справочники.Номенклатура;

Сообщить(МетаСправочник.Имя); // "Номенклатура"

Сообщить(МетаСправочник.Синоним); // "Номенклатура" (представление)

Сообщить(МетаСправочник.ДлинаКода); // длина кода

Сообщить(МетаСправочник.Иерархический); // Истина/Ложь

Если имя объекта заранее неизвестно и приходит в виде строки, используют индексное обращение к коллекции:

ИмяОбъекта = "Номенклатура";

МетаОбъект = Метаданные.Справочники[ИмяОбъекта];

При обращении по строке обязательно проверяйте результат: если объекта с таким именем нет, будет возвращено Неопределено, а попытка прочитать его свойства вызовет ошибку исполнения. Безопасный шаблон:

МетаОбъект = Метаданные.Справочники.Найти(ИмяОбъекта);

Если МетаОбъект = Неопределено Тогда

ВызватьИсключение "Справочник """ + ИмяОбъекта + """ отсутствует в конфигурации";

КонецЕсли;

Поиск объектов: НайтиПоПолномуИмени, НайтиПоТипу, НайтиПоСсылке

Когда тип объекта тоже неизвестен заранее, используются методы самой коллекции Метаданные:

НайтиПоПолномуИмени — поиск по строке вида «Справочник.Номенклатура» или «Документ.РеализацияТоваровУслуг.Реквизит.Организация»:

МетаОбъект = Метаданные.НайтиПоПолномуИмени("Документ.РеализацияТоваровУслуг");

Если МетаОбъект <> Неопределено Тогда

Сообщить(МетаОбъект.ПолноеИмя());

КонецЕсли;

НайтиПоТипу — определяет, какому объекту конфигурации соответствует тип значения:

МетаОбъект = Метаданные.НайтиПоТипу(ТипЗнч(Ссылка));

Если МетаОбъект <> Неопределено Тогда

ВидОбъекта = МетаОбъект.Имя; // например, "Номенклатура"

КонецЕсли;

НайтиПоСсылке (в новых версиях платформы — НайтиПоСсылкам для массива) — получение метаданных по ссылке на объект базы данных. Это удобно в универсальных механизмах, где на вход приходит произвольная ссылка, а нужно понять, документ это или элемент справочника.

bsl
Функция ВидОбъектаПоСсылке(Ссылка)
	МетаОбъект = Ссылка.Метаданные();
	Возврат МетаОбъект.ПолноеИмя();
КонецФункции

Работа с реквизитами, табличными частями и измерениями

У каждого объекта метаданных есть вложенные коллекции, описывающие его состав. Для справочников и документов это Реквизиты и ТабличныеЧасти, для регистров сведений и накопления — Измерения, Ресурсы и Реквизиты. Обход реквизитов — типовая задача универсальных обработок:

МетаОбъект = Метаданные.Документы.РеализацияТоваровУслуг;

Для Каждого Реквизит Из МетаОбъект.Реквизиты Цикл

Сообщить(Реквизит.Имя + " (" + Реквизит.Синоним + "): " + Строка(Реквизит.Тип));

КонецЦикла;

Стандартные реквизиты (код, наименование, номер, дата, проведён) хранятся отдельно — в коллекции СтандартныеРеквизиты. Это частая причина ошибок: разработчик обходит только Реквизиты и не находит «Код» или «Дату». Табличные части обходятся аналогично, у каждой — своя коллекция Реквизиты:

Для Каждого ТЧ Из МетаОбъект.ТабличныеЧасти Цикл

Сообщить("Табличная часть: " + ТЧ.Имя);

Для Каждого Реквизит Из ТЧ.Реквизиты Цикл

Сообщить(" - " + Реквизит.Имя);

КонецЦикла;

КонецЦикла;

Свойство Тип реквизита возвращает описание типов, из которого можно узнать, составной ли тип и какие конкретно типы входят в него. Это необходимо при построении динамических запросов и сопоставлении данных при обмене.

Типичные ошибки
01
Обход только коллекции Реквизиты без СтандартныхРеквизитов — поля Код, Наименование, Дата, Номер «теряются» при универсальной выгрузке.
02
Использование имени объекта вместо синонима в интерфейсе: пользователь видит техническое имя вместо привычного представления.
03
Обращение к Метаданные.Документы[Имя] без проверки на Неопределено — обработка падает в конфигурациях, где объекта нет.
04
Попытка изменить метаданные из кода: коллекция доступна только на чтение, структуру меняют через конфигуратор.

Метаданные в запросах и динамическом построении таблиц

На практике метаданные часто нужны, чтобы сформировать текст запроса к таблице, имя которой известно только во время выполнения. Имя таблицы в запросе совпадает с полным именем метаданного:

ПолноеИмя = МетаОбъект.ПолноеИмя(); // "Справочник.Номенклатура"

Запрос = Новый Запрос;

Запрос.Текст = "ВЫБРАТЬ ПЕРВЫЕ 10 Таб.Ссылка ИЗ " + ПолноеИмя + " КАК Таб";

Результат = Запрос.Выполнить();

При таком подходе имена полей тоже подставляются из метаданных. Перед включением реквизита в текст запроса убедитесь, что он существует у конкретного объекта: у разных видов документов набор реквизитов различен, и запрос с несуществующим полем не выполнится.

Обратите внимание на безопасность: если имя таблицы или поля приходит от пользователя, проверяйте его через Метаданные.НайтиПоПолномуИмени(), а не подставляйте строку напрямую. Это защищает и от ошибок, и от некорректных данных в тексте запроса.

Порядок действий для универсального запроса
  1. 1
    Получите объект метаданных: Метаданные.НайтиПоПолномуИмени(ПолноеИмя).
  2. 2
    Проверьте, что результат не Неопределено.
  3. 3
    Сформируйте список полей, проверяя наличие каждого реквизита в коллекции Реквизиты.
  4. 4
    Соберите текст запроса, используя МетаОбъект.ПолноеИмя() как имя таблицы.
  5. 5
    Выполните запрос и проверьте, что результат не пустой.

Функциональные опции, права и прочие свойства

Кроме состава объектов, через метаданные доступны и другие разделы конфигурации. Свойство Метаданные.ФункциональныеОпции позволяет узнать, какие объекты связаны с той или иной опцией, а метод ПолучитьФункциональнуюОпцию() — получить её текущее значение и, соответственно, понять, доступен ли объект пользователю.

Для проверки прав доступа к объекту метаданных используется функция ПравоДоступа("Просмотр", МетаОбъект). Это правильный способ скрыть недоступные объекты в универсальных интерфейсах вместо того, чтобы ловить ошибки при обращении к данным.

Также полезны свойства Метаданные.Имя и Метаданные.Версия — они описывают саму конфигурацию. Внешние обработки нередко проверяют совместимость именно через них, прежде чем обращаться к конкретным объектам.

Способы получения метаданных

Прямое обращение (Метаданные.Справочники.Номенклатура)

Самый быстрый и читаемый вариант, когда объект известен на этапе разработки. Не подходит для универсального кода.

Поиск по строке (Найти, индекс коллекции)

Подходит, когда вид объекта известен, а имя приходит параметром. Обязательна проверка на Неопределено.

НайтиПоПолномуИмени / НайтиПоТипу / Ссылка.Метаданные()

Универсальные механизмы, когда неизвестен и вид, и имя объекта. Чуть медленнее, но единственный вариант для произвольных ссылок.

Производительность и ограничения

Обращение к метаданным — относительно «дорогая» операция по сравнению с обычным чтением переменных, особенно в клиент-серверном режиме, когда вызов уходит на сервер. Поэтому в циклах и часто вызываемых функциях объект метаданных стоит получать один раз и сохранять в переменную или кэшировать в структуре.

Основные ограничения, которые нужно учитывать:

  • метаданные доступны только для чтения — изменить структуру из кода нельзя;
  • на тонком и веб-клиенте большинство обращений к метаданным выполняется только в серверных процедурах;
  • в безопасном режиме и при работе расширений доступ к метаданным может быть ограничен профилем безопасности;
  • объекты, скрытые функциональными опциями, в метаданных присутствуют — их доступность нужно проверять отдельно.
Контрольные точки

Как проверить результат

Объект метаданных получен
Норма

Переменная не равна Неопределено, ПолноеИмя() возвращает ожидаемую строку

Тревожный признак

Неопределено — объекта нет в конфигурации или ошибка в имени

Состав реквизитов
Норма

Обход коллекции Реквизиты возвращает все пользовательские поля объекта

Тревожный признак

Не хватает Кода/Наименования/Даты — забыты СтандартныеРеквизиты

Динамический запрос
Норма

Запрос выполняется и возвращает данные для любого переданного объекта

Тревожный признак

Ошибка «поле не найдено» — реквизит не проверен по метаданным перед подстановкой

Частые вопросы

Как получить список всех документов конфигурации?

Переберите коллекцию в цикле: Для Каждого МетаДок Из Метаданные.Документы Цикл Сообщить(МетаДок.Имя); КонецЦикла;. Для вывода пользователю используйте свойство Синоним вместо Имя.

Как узнать, есть ли реквизит у объекта?

Используйте метод Найти: МетаОбъект.Реквизиты.Найти("Комментарий"). Если вернулось Неопределено — реквизита нет. Помните, что стандартные реквизиты (Код, Дата) ищутся в коллекции СтандартныеРеквизиты.

Можно ли получить метаданные на клиенте?

На тонком и веб-клиенте прямой доступ к коллекции Метаданные ограничен. Стандартный подход — вызвать серверную процедуру, которая вернёт нужные сведения (имя, список реквизитов) в виде простых типов: строк, структур, массивов.

Чем отличается Ссылка.Метаданные() от Метаданные.НайтиПоТипу()?

Результат одинаков — объект описания метаданных. Ссылка.Метаданные() короче и удобнее, когда у вас уже есть ссылка; НайтиПоТипу применяют, когда есть только значение произвольного типа, например из поля компоновки данных.

Как получить синоним (представление) объекта для пользователя?

Через свойство Синоним объекта метаданных: Метаданные.Документы.РеализацияТоваровУслуг.Синоним или через функцию ПредставлениеОбъектаМетаданных в типовых конфигурациях БСП. Синоним может быть пустым — тогда используйте Имя.

Влияет ли обращение к метаданным на производительность?

Разовое обращение практически незаметно, но в циклах с тысячами итераций, особенно через клиент-серверные вызовы, накладные расходы ощутимы. Получайте объект метаданных один раз до цикла и переиспользуйте переменную.

Итог

Что важно запомнить

Доступ к метаданным в 1С выполняется через глобальную коллекцию Метаданные: напрямую по имени, через Найти, НайтиПоПолномуИмени или Ссылка.Метаданные(). Метаданные доступны только для чтения, всегда проверяйте результат поиска на Неопределено, не забывайте про СтандартныеРеквизиты и кэшируйте объект метаданных в циклах.