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

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

Как в 1С получить метаданные по типу значения

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

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

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

Ниже разобраны рабочие способы с примерами кода, ограничения каждого подхода и типичные ошибки, которые приводят к значению Неопределено там, где разработчик ожидал объект метаданных.

Получение метаданных через Метаданные.НайтиПоТипу

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

ТипЗначения = ТипЗнч(СсылкаНаОбъект);

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

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

Сообщить("Имя объекта: " + МетаданныеОбъекта.Имя);

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

КонецЕсли;

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

Важно понимать границу метода: для примитивных типов (Число, Строка, Дата, Булево) он вернёт Неопределено, потому что эти типы не имеют представления в дереве конфигурации. То же произойдёт для типов вида «ОписаниеТипов», «УникальныйИдентификатор» и подобных служебных.

Определение типа значения: ТипЗнч и Тип

Прежде чем искать метаданные, нужно получить сам тип. Функция ТипЗнч(Значение) возвращает тип переданного значения. Если значение — ссылка на документ «ПоступлениеТоваровУслуг», результатом будет тип «ДокументСсылка.ПоступлениеТоваровУслуг».

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

Попытка

ИскомыйТип = Тип(ИмяТипаСтрокой);

Исключение

ИскомыйТип = Неопределено;

КонецПопытки;

Также тип можно взять из описания типов реквизита: Метаданные.Документы.РеализацияТоваровУслуг.Реквизиты.Контрагент.Тип вернёт ОписаниеТипов, а через его метод Типы() доступен массив всех типов, допустимых для этого реквизита. Это полезно при построении универсальных форм выбора и проверках составного типа.

Получение метаданных по полному имени и обход дерева

Если известно полное имя объекта строкой (например, из JSON-настройки или плана обмена), метаданные ищут через Метаданные.НайтиПоПолномуИмени():

МД = Метаданные.НайтиПоПолномуИмени("Справочник.Номенклатура");

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

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

КонецЕсли;

Когда вид объекта известен заранее, быстрее обратиться напрямую к коллекции: Метаданные.Справочники.Найти("Номенклатура"), Метаданные.Документы.Найти("РеализацияТоваровУслуг"). Метод Найти() у коллекции возвращает объект метаданных или Неопределено без исключения — это безопаснее прямого обращения через точку.

Для перебора всех объектов одного вида используется цикл по коллекции:

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

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

КонецЦикла;

Порядок действий
  1. 1
    Получите тип значения: ТипЗнч(Значение)
  2. 2
    Передайте тип в Метаданные.НайтиПоТипу()
  3. 3
    Проверьте результат на Неопределено
  4. 4
    Прочитайте нужные свойства: Имя, ПолноеИмя(), Реквизиты
  5. 5
    При строковом имени используйте НайтиПоПолномуИмени() или Найти() в коллекции

Практические сценарии использования

Универсальная обработка ссылок

Типовая задача — обработчик, принимающий произвольную ссылку и выводящий её представление вместе с видом объекта. Здесь связка ТипЗнч + НайтиПоТипу решает задачу полностью:

Функция ОписаниеСсылки(Ссылка) Экспорт

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

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

Возврат "Примитивный тип: " + ТипЗнч(Ссылка);

КонецЕсли;

Возврат МД.ПолноеИмя() + ": " + Строка(Ссылка);

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

Проверка принадлежности к виду объектов

Часто нужно не имя, а ответ на вопрос «это документ или нет?». Для этого объект метаданных сравнивают с коллекцией через Метаданные.Документы.Содержит(МД):

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

Если МД <> Неопределено И Метаданные.Документы.Содержит(МД) Тогда

// работаем как с документом

КонецЕсли;

Альтернатива без метаданных — функции ЭтоСсылка() из общих модулей БСП или проверка ТипЗнч(Значение) = Тип("ДокументСсылка.КонкретныйВид"), когда вид известен заранее. Для универсального кода вариант с метаданными предпочтительнее.

Построение списка реквизитов объекта

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

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

Ограничения и нюансы платформы

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

Производительность: обращения к метаданным не бесплатны, особенно в циклах по большим выборкам. Если тип объекта внутри цикла не меняется, получите объект метаданных один раз до цикла и переиспользуйте. Для массовых проверок «является ли ссылка документом» быстрее работает сравнение типа напрямую, без обращения к дереву метаданных.

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

Маршрут решения

Как выбрать действие

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

Проверка результата и отладка

Надёжный код всегда проверяет результат поиска на Неопределено до обращения к свойствам. Обращение МД.Имя при МД = Неопределено вызывает ошибку «Поле объекта не обнаружено», которая в фоновых заданиях и обменах может остаться незамеченной и оборвать процесс.

Для отладки удобно выводить ПолноеИмя() — оно однозначно идентифицирует объект, в отличие от Имя, которое не содержит вида. В консоли кода или отладчике проверяйте цепочку целиком: сначала ТипЗнч, затем результат поиска, затем свойства.

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

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

Результат НайтиПоТипу
Норма

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

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

Неопределено — тип примитивный или не связан с конфигурацией

Поиск по полному имени
Норма

Найден объект с ожидаемым видом

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

Неопределено — проверьте точность строки и регистр не важен, но вид должен совпадать

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

Нужные поля найдены в Реквизиты или СтандартныеРеквизиты

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

Поле не найдено — возможно, оно стандартное или принадлежит табличной части

Часто задаваемые вопросы

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

Метод возвращает Неопределено для примитивных типов (Число, Строка, Дата, Булево), служебных типов (ТаблицаЗначений, Запрос, УникальныйИдентификатор) и любых типов, не связанных с объектами конфигурации. Это штатное поведение — перед обращением к свойствам результата всегда делайте проверку на Неопределено.

Как получить метаданные, если известна только строка с именем типа?

Два пути: сконструировать тип через Тип("ДокументСсылка.ИмяДокумента") и передать его в НайтиПоТипу, либо сразу вызвать Метаданные.НайтиПоПолномуИмени("Документ.ИмяДокумента"). Второй вариант проще и не требует приставки «Ссылка» в строке. Конструктор Тип() при неверном имени выбрасывает исключение — оборачивайте его в Попытка/Исключение.

Чем отличается Имя от ПолноеИмя() у объекта метаданных?

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

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

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

Как проверить, что ссылка относится к справочникам, без перечисления всех видов?

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

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

Обращение к дереву метаданных — не самая дешёвая операция. Если внутри цикла обрабатываются значения одного типа, получите объект метаданных один раз до цикла. Для простых проверок типа в массовых операциях быстрее прямое сравнение ТипЗнч(Значение) = Тип("ДокументСсылка.НужныйВид").

Итог

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

Основной инструмент — Метаданные.НайтиПоТипу(ТипЗнч(Значение)): он возвращает объект метаданных для ссылок и объектов конфигурации и Неопределено для примитивных типов. Для строковых имён используйте НайтиПоПолномуИмени() или Найти() в коллекциях. Всегда проверяйте результат на Неопределено и помните, что стандартные реквизиты лежат в отдельной коллекции.