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

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

Как определить тип ссылки в 1С

Как определить тип ссылки в 1С: ТипЗнч, метод Метаданные(), сравнение типов, проверка в запросе. Примеры на встроенном языке, типичные ошибки и FAQ.

Ссылка в 1С — это значение, которое указывает на объект базы данных: элемент справочника, документ, план счетов и так далее. При разработке нередко нужно понять, объект какого именно вида скрывается за ссылкой: например, чтобы по-разному обработать документы в общей процедуре или подставить правильное представление в отчёт. Встроенный язык даёт для этого несколько инструментов, и выбор зависит от задачи.

Базовый подход — функция ТипЗнч(), которая возвращает тип значения, и метод Метаданные(), доступный у любой ссылки. Они решают похожие, но не одинаковые задачи: первый отвечает на вопрос «какой тип у значения», второй — «какому объекту конфигурации соответствует ссылка». Ниже разобраны оба способа, работа с типом в запросах и типичные ошибки, из-за которых сравнение типов «не срабатывает».

Что такое тип ссылки и когда его нужно определять

Каждый прикладной объект в 1С имеет ссылочный тип вида СправочникСсылка.Номенклатура, ДокументСсылка.РеализацияТоваровУслуг, ПеречислениеСсылка.СтавкиНДС и т.д. Ссылка сама по себе не содержит реквизитов объекта — это указатель, по которому платформа при необходимости считывает данные из базы.

Определять тип ссылки приходится в нескольких типовых ситуациях:

  • в универсальных процедурах, принимающих параметр произвольного типа (например, обработчик заполнения или подписка на событие по нескольким видам документов);
  • при работе с полями составного типа, где в одной колонке могут лежать ссылки на разные объекты;
  • при построении отчётов, где для разных видов документов нужен разный текст или отбор;
  • при обмене данными, когда тип объекта влияет на правила конвертации.

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

Определение типа через ТипЗнч() и Тип()

Функция ТипЗнч(Значение) возвращает объект типа Тип, описывающий тип переданного значения. Чтобы проверить, является ли ссылка ссылкой на конкретный вид объекта, результат сравнивают с конструктором Тип("ИмяТипа"):

Если ТипЗнч(Ссылка) = Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда

// обработка реализации

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

// обработка поступления

КонецЕсли;

Имя типа в строке строится по шаблону: категория объекта (СправочникСсылка, ДокументСсылка, ПланСчетовСсылка, ПланВидовХарактеристикСсылка и т.п.) плюс точка и имя объекта метаданных, как оно задано в конфигураторе. Регистр букв в строке не важен, но опечатка в имени приведёт к ошибке выполнения — конструктор Тип() не проверяет строку на этапе компиляции.

Такой способ оптимален, когда вариантов немного и они известны заранее. Сравнение типов — быстрая операция, не обращающаяся к базе данных, поэтому его можно без опасений использовать в циклах.

Получение типа через метод Метаданные()

У любой ссылки есть метод Метаданные(), который возвращает объект описания метаданных. Через него можно узнать имя объекта, его синоним, полное имя и принадлежность к категории:

МетаданныеСсылки = Ссылка.Метаданные();

ИмяОбъекта = МетаданныеСсылки.Имя; // "Номенклатура"

ПолноеИмя = МетаданныеСсылки.ПолноеИмя(); // "Справочник.Номенклатура"

Представление = МетаданныеСсылки.Представление(); // "Номенклатура"

Проверка принадлежности к категории выполняется через коллекцию метаданных конфигурации:

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

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

ИначеЕсли Метаданные.Документы.Содержит(Ссылка.Метаданные()) Тогда

// это ссылка на документ

КонецЕсли;

Этот подход удобен, когда нужно не сравнить с конкретным видом, а классифицировать ссылку или получить её описание динамически — например, сформировать строку «Документ "Реализация товаров и услуг"» для журнала. Минус: конструкция чуть громоздче и при массовых вызовах в цикле по тысячам строк работает медленнее прямого сравнения типов.

Сравнение подходов

ТипЗнч() + Тип()

Быстро и лаконично; подходит, когда виды объектов известны заранее. Не подходит для обхода произвольных типов.

Ссылка.Метаданные()

Гибко: даёт имя, синоним, категорию. Чуть медленнее и многословнее; идеально для универсальных механизмов.

Запрос с ТИПЗНАЧЕНИЯ()

Единственный вариант, когда проверка нужна в отборе или группировке запроса без обхода выборки в коде.

Определение типа ссылки в запросе

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

ВЫБРАТЬ

СоставнойРеквизит

ИЗ

РегистрСведений.СвязанныеОбъекты

ГДЕ

СоставнойРеквизит ССЫЛКА Справочник.Номенклатура

Альтернатива — функция ТИПЗНАЧЕНИЯ() в сочетании со значением типа:

ГДЕ

ТИПЗНАЧЕНИЯ(СоставнойРеквизит) = ТИП(Справочник.Номенклатура)

Дополнительно в запросе тип можно вывести как поле и использовать в итогах или группировках. Учтите: в параметрах виртуальных таблиц и в СКД синтаксис проверки типа аналогичен, но в схеме компоновки для отбора по типу обычно удобнее использовать «Вид сравнения — В списке» с перечислением конкретных ссылок или параметр-тип.

Порядок определения типа ссылки в коде
  1. 1
    Убедитесь, что переменная заполнена: отсеките Неопределено и при необходимости проверьте ссылку на пустоту через Ссылка.Пустая().
  2. 2
    Если вид объекта известен — сравните ТипЗнч(Ссылка) с Тип("Вид.Имя").
  3. 3
    Если нужна универсальная классификация — получите Ссылка.Метаданные() и проверьте принадлежность через Метаданные.Справочники.Содержит() и аналоги.
  4. 4
    Если проверка должна выполняться в выборке — перенесите условие в запрос через ССЫЛКА или ТИПЗНАЧЕНИЯ().
  5. 5
    Проверьте результат на тестовых данных каждого ожидаемого вида, включая пустую ссылку.

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

Самый быстрый способ убедиться, что тип определяется правильно, — вывести его в сообщение или посмотреть в отладчике. В отладчике достаточно добавить переменную в табло: рядом со значением ссылки отображается и её тип. Программно тип можно представить строкой:

Сообщить(Строка(ТипЗнч(Ссылка)));            // "ДокументСсылка.РеализацияТоваровУслуг"

Сообщить(Ссылка.Метаданные().ПолноеИмя()); // "Документ.РеализацияТоваровУслуг"

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

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

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

Сравнение типов в коде
Норма

Условие срабатывает для всех тестовых ссылок нужного вида, включая пустую

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

Условие не срабатывает — вероятна опечатка в имени типа или сравнение строк

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

В выборку попадают только ссылки нужного вида

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

Попадают лишние значения или выборка пуста при заведомо подходящих данных

Универсальная классификация
Норма

Метаданные().ПолноеИмя() возвращает ожидаемое «Категория.Имя»

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

Ошибка «Метод не обнаружен» — значение не является ссылкой

Типичные ошибки при определении типа

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

Вторая ошибка — сравнение строк вместо типов: Строка(ТипЗнч(Ссылка)) = "Номенклатура" никогда не выполнится, потому что строковое представление включает категорию. Третья — забыть про составной тип: если реквизит может хранить несколько видов ссылок, проверка только одного вида молча пропустит остальные, и ветка «Иначе» получит непредусмотренные данные. Наконец, в запросах путают ССЫЛКА и ТИПЗНАЧЕНИЯ с ВЫРАЗИТЬ(): приведение типа через ВЫРАЗИТЬ не фильтрует данные, а лишь меняет интерпретацию поля.

Типичные ошибки
01
Вызов Ссылка.Метаданные() без проверки, что значение — ссылка: ошибка выполнения на примитивных типах и Неопределено.
02
Опечатка в строке Тип("СправочникСсылка.Имя"): ошибка возникает только в момент выполнения, а не при проверке модуля.
03
Сравнение строковых представлений типа и метаданных: форматы различаются («ДокументСсылка.Имя» против «Документ.Имя»), сравнение даёт ложный результат.
04
Использование ВЫРАЗИТЬ() в запросе вместо отбора по типу: лишние строки не отфильтровываются.
05
Игнорирование пустых ссылок: пустая ссылка проходит проверку типа, но обращение к её реквизитам даёт пустые значения.

Ограничения и особенности платформы

Перечисления ведут себя иначе, чем другие ссылочные объекты: для значения перечисления ТипЗнч() вернёт ПеречислениеСсылка.Имя, а Метаданные() также доступен. Но у перечислений нет таблицы в базе в привычном смысле, поэтому в запросах к ним обращаются через литералы ЗНАЧЕНИЕ(Перечисление.Имя.Значение).

В тонком и веб-клиенте перечисленные методы работают на сервере; на клиенте доступ к метаданным ограничен, поэтому определение типа через Метаданные() в клиентском коде может быть недоступно в зависимости от директив компиляции. Практическое правило: выполняйте такие проверки в серверных процедурах, а на клиент передавайте уже готовый результат — строку с именем типа или признак вида объекта.

Ещё одно ограничение касается производительности: в циклах по большим выборкам предпочтительнее определить тип один раз в запросе (полем ТИПЗНАЧЕНИЯ()) или сравнивать типы напрямую, а не вызывать Метаданные() для каждой строки.

Итог

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

В коде тип ссылки определяют через ТипЗнч() со сравнением с Тип("Вид.Имя") или через Ссылка.Метаданные() для универсальной классификации. В запросах — через ССЫЛКА и ТИПЗНАЧЕНИЯ(). Перед вызовом Метаданные() убедитесь, что значение ссылочное, и не сравнивайте строковые представления вместо самих типов.

Частые вопросы

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

Используйте встроенную функцию ЭтоСсылка(ТипЗнч(Значение)) — в типовых конфигурациях часто есть аналог в общих модулях. Самодельный вариант: попытаться получить Значение.Метаданные() в попытке/исключении или проверить тип через перечень ссылочных категорий. Простая проверка ТипЗнч() на конкретный ссылочный тип тоже косвенно подтверждает ссылочность.

Чем отличается ТипЗнч() от Метаданные()?

ТипЗнч() возвращает тип значения и работает с любыми данными, включая числа и строки. Метаданные() — метод только ссылочных значений, он возвращает описание объекта конфигурации: имя, синоним, состав реквизитов. Для сравнения «это реализация?» достаточно ТипЗнч(); для «как называется этот объект и к какой категории он относится» нужен Метаданные().

Как определить тип ссылки в СКД?

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

Почему сравнение ТипЗнч() = Тип("...") не срабатывает, хотя вид объекта верный?

Чаще всего причина в опечатке в строке имени типа или в том, что проверяется объект, а не ссылка: у объектов (например, ДокументОбъект) тип другой — ДокументОбъект.Имя. Если в переменной объект, сравнивайте с Тип("ДокументОбъект.Имя") или берите его ссылку и проверяйте её.

Можно ли получить список всех видов документов и определить тип по строке?

Да: переберите коллекцию Метаданные.Документы и сравните Ссылка.Метаданные() с каждым элементом либо сопоставьте имена. Обратная задача — получить тип по строке — решается конструктором Тип("ДокументСсылка." + Имя), но строку нужно получать из надёжного источника, чтобы избежать ошибок выполнения.

Работает ли определение типа на клиенте?

ТипЗнч() доступен и на клиенте, а вот Метаданные() и коллекции метаданных — только на сервере. Поэтому в клиент-серверном коде определяйте тип в серверной процедуре и передавайте на клиент результат в виде строки или булева признака.