Разработка и Конфигурация · 10 мин
Как в 1С определить, что тип является справочником
Как в 1С определить, что тип значения или метаданных является справочником: ТипЗнч, Метаданные.НайтиПоТипу, Справочники.ТипВсеСсылки и проверка ссылок.
При разработке универсальных обработок, обменов и печатных форм в 1С регулярно возникает задача: понять, относится ли переданное значение или тип к справочникам. Платформа предлагает несколько способов — от прямого сравнения типа с конкретным видом справочника до анализа метаданных через Метаданные.НайтиПоТипу(). Выбор зависит от того, что у вас есть на входе: ссылка, объект, строковое имя типа или само значение типа «Тип».
Ошибка в определении типа приводит к падению кода с сообщениями вида «Поле объекта не обнаружено» или к некорректной обработке данных: например, обмен попытается записать документ по алгоритму справочника. Поэтому проверку типа стоит делать явно, до обращения к реквизитам объекта.
Что нужно определить: значение, ссылку или тип
Прежде чем выбирать метод, уточните, какие данные у вас есть. В 1С «справочник» может фигурировать в трёх ипостасях: ссылка (значение типа СправочникСсылка.Имя), объект (СправочникОбъект.Имя, полученный методом ПолучитьОбъект()) и тип как значение (результат функции Тип("СправочникСсылка.Номенклатура")). Для каждого случая есть свой рабочий приём.
Также различают две постановки задачи: проверить, что значение относится к справочникам вообще (любому виду), или что оно относится к конкретному виду справочника, например только к «Номенклатуре». Вторая задача решается проще — прямым сравнением типа.
Проверка через ТипЗнч и конкретный вид справочника
Если известно, с каким справочником вы работаете, самый быстрый и надёжный способ — сравнить тип значения с типом конкретного вида:
Если ТипЗнч(Значение) = Тип("СправочникСсылка.Номенклатура") Тогда
// Это ссылка на элемент справочника "Номенклатура"
КонецЕсли;
Обратите внимание на различие СправочникСсылка и СправочникОбъект. Если в переменной лежит объект (после ПолучитьОбъект()), сравнение со ссылочным типом вернёт Ложь. Для объектов используйте Тип("СправочникОбъект.Номенклатура"). На практике в большинстве сценариев (параметры запросов, реквизиты документов, результаты выборок) передаются именно ссылки.
Если нужно принять и ссылку, и объект одного вида, проверяйте оба типа или приводите объект к ссылке через свойство Ссылка.
Универсальная проверка через ТипВсеСсылки
Когда вид справочника заранее неизвестен, удобен предопределённый тип-коллекция Справочники.ТипВсеСсылки(). Метод СодержитТип() возвращает Истина, если переданный тип — ссылка любого справочника конфигурации:
Если Справочники.ТипВсеСсылки().СодержитТип(ТипЗнч(Значение)) Тогда
// Значение — ссылка на какой-то справочник
КонецЕсли;
Аналогичные коллекции существуют для других видов объектов: Документы.ТипВсеСсылки(), Перечисления.ТипВсеСсылки(), ПланыВидовХарактеристик.ТипВсеСсылки(). Такой подход удобен в универсальных обработках, где тип значения приходит динамически — например, из таблицы значений с составным типом колонки.
Определение через метаданные
Самый универсальный способ, работающий и для ссылок, и для объектов, — получить описание метаданных по типу и проверить, входит ли оно в коллекцию справочников:
Функция ЭтоСправочник(Значение) Экспорт
ОбъектМетаданных = Метаданные.НайтиПоТипу(ТипЗнч(Значение));
Если ОбъектМетаданных = Неопределено Тогда
Возврат Ложь; // примитивный тип или значение без метаданных
КонецЕсли;
Возврат Метаданные.Справочники.Содержит(ОбъектМетаданных);
КонецФункции
Метод Метаданные.НайтиПоТипу() возвращает Неопределено для примитивных типов (число, строка, дата), поэтому проверка на Неопределено обязательна — иначе следующая строка вызовет ошибку. Получив объект метаданных, вы можете дополнительно узнать имя справочника (ОбъектМетаданных.Имя), синоним, иерархичность и другие свойства.
Если на входе не значение, а тип (например, из описания типов колонки), передавайте его напрямую: Метаданные.НайтиПоТипу(ТипКолонки).
Функция ЭтоСсылкаНаСправочник(Ссылка)
Возврат Справочники.ТипВсеСсылки().СодержитТип(ТипЗнч(Ссылка));
КонецФункцииОпределение справочника по имени типа в строковом виде
В обменах и сериализации тип часто представлен строкой вида «СправочникСсылка.Номенклатура». Получить строковое представление можно через XMLТипЗнч(Значение) или простым преобразованием типа к строке. Для проверки достаточно анализа префикса:
ИмяТипа = XMLТипЗнч(Значение).ИмяТипа; // "CatalogRef.Номенклатура"
Если СтрНачинаетсяС(ИмяТипа, "CatalogRef.") Тогда
// Ссылка на справочник
КонецЕсли;
Обратное преобразование из строки в тип выполняется функцией Тип("СправочникСсылка.Номенклатура"), но она вызывает исключение, если такого объекта в конфигурации нет. Поэтому при разборе строк из внешних источников оборачивайте вызов в попытку или предварительно проверяйте наличие объекта через Метаданные.Справочники.Найти(Имя).
Проверка в запросе
Иногда тип нужно определить прямо в тексте запроса — например, чтобы отфильтровать составное поле. Для этого используется оператор ССЫЛКА в условии или функция ТИПЗНАЧЕНИЯ():
ВЫБРАТЬ
Взаиморасчеты.Сделка
ИЗ
РегистрНакопления.Взаиморасчеты КАК Взаиморасчеты
ГДЕ
Взаиморасчеты.Сделка ССЫЛКА Справочник.ДоговорыКонтрагентов
Оператор ССЫЛКА проверяет принадлежность к конкретному виду. Универсальной проверки «любой справочник» в языке запросов нет — при необходимости перечисляйте виды через ИЛИ или фильтруйте уже на стороне кода после выполнения запроса.
Сравнение способов
Самый быстрый. Подходит, когда вид справочника известен заранее. Не работает для произвольных справочников.
Универсально для всех ссылок на справочники. Не распознаёт объекты СправочникОбъект.
Самый гибкий: работает со ссылками и объектами, даёт имя и свойства вида. Чуть медленнее и требует проверки на Неопределено.
Единственный вариант внутри запроса. Требует перечисления конкретных видов.
Частые ошибки и как их избежать
Самая распространённая ошибка — путаница между ссылкой и объектом. Код, написанный под ссылку, молча не срабатывает на объекте, и наоборот. Второй типичный промах — забыть проверку на Неопределено после Метаданные.НайтиПоТипу() для примитивных значений. Третья — сравнение типов через строковое представление (Строка(ТипЗнч(Значение)) = "Номенклатура"): такой код ломается при переименовании объекта и работает медленнее.
Проверка результата
После внедрения функции проверьте её на контрольном наборе: ссылка на справочник, объект справочника, ссылка на документ, перечисление, число, строка, Неопределено. Функция должна вернуть Истина только для первых двух случаев (или только для первого, если проверяются именно ссылки) и не выбрасывать исключений ни на одном из значений.
Как проверить результат
Функция возвращает Истина
Ложь или исключение — проверьте, не сравниваете ли вы с типом объекта
Возвращается Ложь без ошибок
Исключение «Метод объекта не обнаружен» — нет проверки на Неопределено
Возвращается Ложь
Истина — проверка слишком широкая, например анализируется только наличие метаданных
FAQ
Как определить имя справочника по ссылке?
Вызовите Ссылка.Метаданные().Имя — у любой ссылки есть метод Метаданные(), возвращающий объект описания. Свойство Имя даст имя вида справочника, как оно задано в конфигураторе, а Свойство Синоним — представление для пользователя.
Чем отличается СправочникСсылка от СправочникОбъект?
Ссылка — лёгкий идентификатор элемента, при обращении к реквизитам через неё выполняются обращения к базе. Объект — полная копия данных элемента в памяти, получаемая через ПолучитьОбъект(); только объект можно модифицировать и записывать. Это разные типы, и проверки типа для них пишутся отдельно.
Как проверить, что значение — пустая ссылка на справочник?
Используйте Значение.Пустая() или сравнение Значение = Справочники.Номенклатура.ПустаяСсылка(). Метод Пустая() универсален и не требует знания конкретного вида справочника, но применим только к ссылочным значениям.
Работает ли ТипВсеСсылки() на тонком клиенте и в веб-клиенте?
Да, менеджеры справочников и метод ТипВсеСсылки() доступны на тонком и веб-клиенте. Ограничения касаются серверных методов вроде ПолучитьОбъект(), а не проверок типа.
Как проверить тип в составном поле формы без кода запроса?
Получите описание типов колонки или реквизита через свойство ТипЗначения и вызовите у него метод СодержитТип() для нужного типа справочника. Это позволяет заранее узнать, какие виды значений допустимы в поле, и построить соответствующую логику выбора.
Есть ли способ определить справочник без обращения к метаданным?
Да — через Справочники.ТипВсеСсылки().СодержитТип(). Это быстрее анализа метаданных и не требует проверки на Неопределено, но работает только со ссылочными типами. Для объектов без метаданных обойтись нельзя.
Что важно запомнить
Для конкретного вида справочника сравнивайте ТипЗнч(Значение) с Тип("СправочникСсылка.Имя"). Для произвольных ссылок используйте Справочники.ТипВсеСсылки().СодержитТип(). Для максимальной гибкости — Метаданные.НайтиПоТипу() с обязательной проверкой на Неопределено. Всегда различайте ссылку и объект — это разные типы.