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