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

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

Как в 1С определить, что тип является справочником

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

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

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

Что нужно определить: значение, ссылку или тип

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

Также различают две постановки задачи: проверить, что значение относится к справочникам вообще (любому виду), или что оно относится к конкретному виду справочника, например только к «Номенклатуре». Вторая задача решается проще — прямым сравнением типа.

Проверка через ТипЗнч и конкретный вид справочника

Если известно, с каким справочником вы работаете, самый быстрый и надёжный способ — сравнить тип значения с типом конкретного вида:

Если ТипЗнч(Значение) = Тип("СправочникСсылка.Номенклатура") Тогда

// Это ссылка на элемент справочника "Номенклатура"

КонецЕсли;

Обратите внимание на различие СправочникСсылка и СправочникОбъект. Если в переменной лежит объект (после ПолучитьОбъект()), сравнение со ссылочным типом вернёт Ложь. Для объектов используйте Тип("СправочникОбъект.Номенклатура"). На практике в большинстве сценариев (параметры запросов, реквизиты документов, результаты выборок) передаются именно ссылки.

Если нужно принять и ссылку, и объект одного вида, проверяйте оба типа или приводите объект к ссылке через свойство Ссылка.

Универсальная проверка через ТипВсеСсылки

Когда вид справочника заранее неизвестен, удобен предопределённый тип-коллекция Справочники.ТипВсеСсылки(). Метод СодержитТип() возвращает Истина, если переданный тип — ссылка любого справочника конфигурации:

Если Справочники.ТипВсеСсылки().СодержитТип(ТипЗнч(Значение)) Тогда

// Значение — ссылка на какой-то справочник

КонецЕсли;

Аналогичные коллекции существуют для других видов объектов: Документы.ТипВсеСсылки(), Перечисления.ТипВсеСсылки(), ПланыВидовХарактеристик.ТипВсеСсылки(). Такой подход удобен в универсальных обработках, где тип значения приходит динамически — например, из таблицы значений с составным типом колонки.

Определение через метаданные

Самый универсальный способ, работающий и для ссылок, и для объектов, — получить описание метаданных по типу и проверить, входит ли оно в коллекцию справочников:

Функция ЭтоСправочник(Значение) Экспорт

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

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

Возврат Ложь; // примитивный тип или значение без метаданных

КонецЕсли;

Возврат Метаданные.Справочники.Содержит(ОбъектМетаданных);

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

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

Если на входе не значение, а тип (например, из описания типов колонки), передавайте его напрямую: Метаданные.НайтиПоТипу(ТипКолонки).

bsl
Функция ЭтоСсылкаНаСправочник(Ссылка)
    Возврат Справочники.ТипВсеСсылки().СодержитТип(ТипЗнч(Ссылка));
КонецФункции

Определение справочника по имени типа в строковом виде

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

ИмяТипа = XMLТипЗнч(Значение).ИмяТипа; // "CatalogRef.Номенклатура"

Если СтрНачинаетсяС(ИмяТипа, "CatalogRef.") Тогда

// Ссылка на справочник

КонецЕсли;

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

Проверка в запросе

Иногда тип нужно определить прямо в тексте запроса — например, чтобы отфильтровать составное поле. Для этого используется оператор ССЫЛКА в условии или функция ТИПЗНАЧЕНИЯ():

ВЫБРАТЬ

Взаиморасчеты.Сделка

ИЗ

РегистрНакопления.Взаиморасчеты КАК Взаиморасчеты

ГДЕ

Взаиморасчеты.Сделка ССЫЛКА Справочник.ДоговорыКонтрагентов

Оператор ССЫЛКА проверяет принадлежность к конкретному виду. Универсальной проверки «любой справочник» в языке запросов нет — при необходимости перечисляйте виды через ИЛИ или фильтруйте уже на стороне кода после выполнения запроса.

Сравнение способов

Сравнение с конкретным типом

Самый быстрый. Подходит, когда вид справочника известен заранее. Не работает для произвольных справочников.

Справочники.ТипВсеСсылки()

Универсально для всех ссылок на справочники. Не распознаёт объекты СправочникОбъект.

Метаданные.НайтиПоТипу()

Самый гибкий: работает со ссылками и объектами, даёт имя и свойства вида. Чуть медленнее и требует проверки на Неопределено.

ССЫЛКА в запросе

Единственный вариант внутри запроса. Требует перечисления конкретных видов.

Частые ошибки и как их избежать

Самая распространённая ошибка — путаница между ссылкой и объектом. Код, написанный под ссылку, молча не срабатывает на объекте, и наоборот. Второй типичный промах — забыть проверку на Неопределено после Метаданные.НайтиПоТипу() для примитивных значений. Третья — сравнение типов через строковое представление (Строка(ТипЗнч(Значение)) = "Номенклатура"): такой код ломается при переименовании объекта и работает медленнее.

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

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

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

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

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

Ссылка на элемент справочника
Норма

Функция возвращает Истина

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

Ложь или исключение — проверьте, не сравниваете ли вы с типом объекта

Число или строка на входе
Норма

Возвращается Ложь без ошибок

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

Исключение «Метод объекта не обнаружен» — нет проверки на Неопределено

Ссылка на документ
Норма

Возвращается Ложь

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

Истина — проверка слишком широкая, например анализируется только наличие метаданных

FAQ

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

Вызовите Ссылка.Метаданные().Имя — у любой ссылки есть метод Метаданные(), возвращающий объект описания. Свойство Имя даст имя вида справочника, как оно задано в конфигураторе, а Свойство Синоним — представление для пользователя.

Чем отличается СправочникСсылка от СправочникОбъект?

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

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

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

Работает ли ТипВсеСсылки() на тонком клиенте и в веб-клиенте?

Да, менеджеры справочников и метод ТипВсеСсылки() доступны на тонком и веб-клиенте. Ограничения касаются серверных методов вроде ПолучитьОбъект(), а не проверок типа.

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

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

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

Да — через Справочники.ТипВсеСсылки().СодержитТип(). Это быстрее анализа метаданных и не требует проверки на Неопределено, но работает только со ссылочными типами. Для объектов без метаданных обойтись нельзя.

Итог

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

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