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