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