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