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

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

Как обращаться к метаданным в 1С

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

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

Доступ к метаданным осуществляется через глобальный объект Метаданные и метод Метаданные(), который есть у большинства объектов платформы. Через них можно получить имя объекта, его синоним, состав реквизитов, признаки использования и многое другое — всё это доступно только для чтения, изменить конфигурацию из кода нельзя.

Материал рассчитан на разработчиков, которые уже знакомы со встроенным языком 1С и хотят уверенно работать с коллекциями метаданных в управляемом приложении и обычных формах.

Глобальный объект Метаданные и навигация по конфигурации

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

Обратиться к конкретному объекту можно по имени как к свойству или через метод Найти(), когда имя хранится в строковой переменной:

// Прямое обращение по имени

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

// Поиск по строковому имени

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

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

Если МД = Неопределено Тогда

Сообщить("Объект с именем " + ИмяОбъекта + " не найден");

КонецЕсли;

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

Получение метаданных конкретного объекта

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

МД = СсылкаНаОбъект.Метаданные();

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

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

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

Сообщить("Представление: " + МД.Представление());

Метод ПолноеИмя() особенно полезен: он возвращает строку вида «Документ.РеализацияТоваровУслуг», которую можно сохранить в базе, а потом по ней восстановить объект метаданных через Метаданные.НайтиПоПолномуИмени():

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

Обратная задача — определить, к какому виду относится значение — решается проверкой Метаданные.Документы.Содержит(МД) или анализом полного имени по точке.

Перебор коллекций метаданных

Коллекции метаданных можно перебирать в цикле — так строятся списки всех документов конфигурации, обработчики обмена и универсальные отчёты:

Для Каждого МДДокумент Из Метаданные.Документы Цикл

Сообщить(МДДокумент.Имя + " — " + МДДокумент.Синоним);

КонецЦикла;

У коллекций есть методы Количество() и Получить(Индекс), поэтому возможен и обход по индексу, но цикл «Для Каждого» читается проще и меньше подвержен ошибкам. Порядок элементов в коллекции соответствует порядку объектов в конфигураторе.

Как вывести список всех документов конфигурации
  1. 1
    Откройте общий модуль или обработку, где нужен код
  2. 2
    Напишите цикл: Для Каждого МД Из Метаданные.Документы Цикл
  3. 3
    Внутри цикла обратитесь к МД.Имя и МД.Синоним
  4. 4
    Проверьте результат в режиме Предприятия — список должен совпадать с веткой «Документы» в конфигураторе

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

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

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

// Реквизиты шапки

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

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

КонецЦикла;

// Табличные части и их колонки

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

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

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

Сообщить(" " + Колонка.Имя);

КонецЦикла;

КонецЦикла;

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

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

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

Метаданные регистров: измерения, ресурсы, реквизиты

У регистров сведений и накопления структура описывается тремя коллекциями: Измерения, Ресурсы и Реквизиты. Разделение принципиально: измерения определяют разрез хранения, ресурсы — хранимые значения, реквизиты — дополнительную информацию.

МД = Метаданные.РегистрыНакопления.ТоварыНаСкладах;

Для Каждого Измерение Из МД.Измерения Цикл

Сообщить("Измерение: " + Измерение.Имя);

КонецЦикла;

Для Каждого Ресурс Из МД.Ресурсы Цикл

Сообщить("Ресурс: " + Ресурс.Имя);

КонецЦикла;

Дополнительно у регистров доступны свойства вида: для регистра сведений — РежимЗаписи и ПериодичностьРегистраСведений, для регистра накопления — ВидРегистраНакопления (остатки или обороты). Эти признаки важно учитывать в универсальных механизмах выгрузки, потому что от них зависит, есть ли у регистра поле «Период» и как формируются итоги.

Проверка прав доступа и функциональных опций

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

Если ПравоДоступа("Чтение", Метаданные.Документы.РеализацияТоваровУслуг) Тогда

// можно выполнять запрос к документу

КонецЕсли;

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

Практические сценарии и ограничения

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

Пример универсальной проверки наличия реквизита перед обращением — защищает код от падения при различиях конфигураций:

Функция ЕстьРеквизит(ИмяРеквизита, МД)

Возврат МД.Реквизиты.Найти(ИмяРеквизита) <> Неопределено;

КонецФункции;

Если ЕстьРеквизит("Организация", Ссылка.Метаданные()) Тогда

Организация = Ссылка.Организация;

КонецЕсли;

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

Контрольные точки

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

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

Переменная содержит объект, ПолноеИмя() возвращает строку вида «Вид.Имя»

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

Переменная равна Неопределено — объект с таким именем не найден

Перебор реквизитов объекта
Норма

В списке есть прикладные реквизиты; стандартные поля получены отдельно через СтандартныеРеквизиты

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

В списке нет полей Ссылка, Дата, Номер — вы смотрите только Реквизиты

Работа под пользователем с ограниченными правами
Норма

ПравоДоступа проверено, недоступные объекты пропускаются

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

Код падает с ошибкой нарушения прав доступа

Итог

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

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

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

Как узнать тип значения, если оно может быть любым объектом конфигурации?

Получите метаданные значения через Значение.Метаданные() и сравните с нужным объектом: Если МД = Метаданные.Документы.РеализацияТоваровУслуг Тогда. Для проверки принадлежности к виду в целом используйте Метаданные.Документы.Содержит(МД). Для примитивных типов метод Метаданные() отсутствует — их проверяют через ТипЗнч().

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

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

Можно ли изменить метаданные программно из кода 1С?

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

Как получить список объектов, у которых есть конкретный реквизит?

Пройдите циклом по нужным коллекциям (Справочники, Документы и др.) и для каждого объекта проверьте МД.Реквизиты.Найти(ИмяРеквизита) <> Неопределено. Такой подход используется, например, для поиска всех документов с реквизитом «Организация» при настройке разграничения данных.

Работает ли обращение к метаданным на клиенте в управляемых формах?

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

Чем ПолноеИмя() лучше простого Имя при сохранении настроек?

Имя без вида объекта неоднозначно: справочник и документ могут называться одинаково. ПолноеИмя() возвращает строку «Вид.Имя», которая однозначно идентифицирует объект и восстанавливается через Метаданные.НайтиПоПолномуИмени(), поэтому именно её сохраняют в настройках универсальных механизмов.