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

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

1. Метод ТИПЗНАЧ() в запросах 1С

Самый универсальный способ проверки типа ссылки непосредственно в тексте запроса — использование функции ТИПЗНАЧ(). Она возвращает строку с именем типа значения, что позволяет фильтровать данные прямо в WHERE или CASE.

Пример запроса, который выбирает только ссылки на справочник Номенклатура:

ВЫБРАТЬ

Ссылка КАК Ссылка,

ТИПЗНАЧ(Ссылка) КАК ТипСсылки

ИЗ

Документ.ПоступлениеТоваров.Товары КАК Товары

ГДЕ

ТИПЗНАЧ(Товары.Ссылка) = "СправочникСсылка.Номенклатура"

Важно учитывать, что ТИПЗНАЧ() возвращает полное имя типа, включая пространство имен. Например, для документа РеализацияТоваровУслуг результат будет "ДокументСсылка.РеализацияТоваровУслуг", а не просто "ДокументСсылка".

  • 🔹 Плюсы метода: работает в любом запросе, не требует доработок конфигурации.
  • 🔹 Минусы: чувствителен к регистру и точному наименованию типа (ошибка в одной букве приведет к пустому результату).
  • 🔹 Особенность: для полиморфных ссылок (например, ЛюбаяСсылка) вернет базовый тип, а не конкретный.
💡

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

2. Проверка через ВЫРАЗИТЬ() для полиморфных типов

Когда ссылка имеет полиморфный тип (например, СправочникСсылка.ЛюбаяСсылка или ДокументСсылка.ЛюбойДокумент), функция ТИПЗНАЧ() вернет только базовый тип. Чтобы получить конкретный тип объекта, используйте конструкцию ВЫРАЗИТЬ() с проверкой на ЕСТЬ NULL.

Пример запроса для фильтрации ссылок на конкретные виды документов:

ВЫБРАТЬ

Ссылка КАК Ссылка

ИЗ

РегистрСведений.ЦеныНоменклатуры КАК Цены

ГДЕ

ВЫРАЗИТЬ(Цены.ДокументОснова КАК ДокументСсылка.ПоступлениеТоваров) ЕСТЬ NULL = ЛОЖЬ

Этот подход работает потому, что ВЫРАЗИТЬ() пытается привести ссылку к указанному типу. Если приведение возможно (т.е. ссылка действительно является документом ПоступлениеТоваров), результат не будет NULL.

Исходный тип ссылки Конструкция для проверки Результат при совпадении
СправочникСсылка.Номенклатура ВЫРАЗИТЬ(Ссылка КАК СправочникСсылка.Товары) ЕСТЬ NULL ЛОЖЬ (если ссылка — Номенклатура)
ДокументСсылка.РеализацияТоваровУслуг ВЫРАЗИТЬ(Ссылка КАК ДокументСсылка.ЗаказПокупателя) ЕСТЬ NULL ИСТИНА (типы не совпадают)
СправочникСсылка.Контрагенты ВЫРАЗИТЬ(Ссылка КАК СправочникСсылка.ЛюбаяСсылка) Ссылка без изменения (универсальное приведение)
📊 Какой метод проверки типов вы используете чаще?
ТИПЗНАЧ() в запросах
ВЫРАЗИТЬ() с ЕСТЬ NULL
Проверка через встроенный язык
Другие способы

3. Альтернативные способы без запросов

Если проверка типа нужна не в запросе, а в модуле (например, в обработке или отчете), удобнее использовать методы встроенного языка. Они дают больше гибкости и позволяют обрабатывать ошибки.

Основные методы:

  • 🔹 ТипЗнч() — аналог функции из запроса, но для кода:
    Тип = ТипЗнч(СсылкаНаОбъект);
    

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

    // Действия для номенклатуры

    КонецЕсли;

  • 🔹 Метаданные().ПолноеИмяТипа() — для получения полного имени типа объекта:
    ПолноеИмя = СсылкаНаОбъект.Метаданные().ПолноеИмяТипа();
  • 🔹 ЭтоТип() — проверка принадлежности к типу с учетом наследования:
    Если ЭтоТип(СсылкаНаОбъект, Тип("ДокументСсылка.ЛюбойДокумент")) Тогда
    

    // Действия для любых документов

    КонецЕсли;

Для массовой обработки ссылок разных типов удобно использовать конструкцию Попытка...Исключение:

Попытка

Артикул = Ссылка.Артикул; // Пытаемся получить реквизит Номенклатуры

Исключение

// Если ошибка — ссылка не Номенклатура

Сообщить("Ошибка: " + ОписаниеОшибки());

КонецПопытки;

Что делать, если ТипЗнч() возвращает неожиданный результат?

Если ТипЗнч() возвращает Неопределено или некорректный тип, проверьте:

1. Что переменная действительно содержит ссылку (а не значение или массив).

2. Что ссылка не пустая (Ссылка.Пустая() = Ложь).

3. Что объект не удален (проверьте через Ссылка.Получена()).

4. Для полиморфных ссылок используйте ЭтоТип() вместо прямого сравнения.

4. Типовые ошибки и как их избежать

Ошибки при работе с типами ссылок часто связаны с неверными предположениями о структуре данных. Рассмотрим самые распространенные случаи:

⚠️ Внимание: Если вы работаете с конфигурацией, где объекты метаданных были переименованы (например, Номенклатура стала ТоварыИУслуги), все проверки типов в запросах и коде нужно обновить! Старые имена типов перестанут работать.
  • 🚫 Ошибка 1: Сравнение с неполным именем типа.

    Неправильно: ТИПЗНАЧ(Ссылка) = "СправочникСсылка" (не хватает имени справочника).

    Правильно: ТИПЗНАЧ(Ссылка) = "СправочникСсылка.Номенклатура".

  • 🚫 Ошибка 2: Игнорирование полиморфных типов.

    Если ссылка объявлена как СправочникСсылка.ЛюбаяСсылка, проверка ТИПЗНАЧ() вернет только базовый тип. Используйте ВЫРАЗИТЬ() или ЭтоТип().

  • 🚫 Ошибка 3: Проверка пустых ссылок.

    Для пустой ссылки ТИПЗНАЧ() вернет "Неопределено", а не тип объекта. Всегда добавляйте проверку Ссылка.Пустая().

Еще одна частая проблема — несоответствие типов при обмене данными. Например, при загрузке данных из XML ссылка на справочник Контрагенты может быть интерпретирована как СправочникСсылка.ЛюбаяСсылка, что приведет к ошибкам при попытке получить специфичные реквизиты. В таких случаях помогает явное приведение типа:

Ссылка = ВЫРАЗИТЬ(ЗагруженнаяСсылка КАК СправочникСсылка.Контрагенты);

5. Практический пример: фильтрация в отчете

Рассмотрим реальную задачу: нужно создать отчет, который показывает все документы, связанные с определенной номенклатурой, но только если это документы ПоступлениеТоваров или РеализацияТоваровУслуг.

Запрос для такого отчета:

ВЫБРАТЬ

Документ.Ссылка КАК Документ,

Документ.Дата КАК Дата,

Документ.Номер КАК Номер

ИЗ

Документ.ПоступлениеТоваров.Товары КАК ТоварыПоступление

ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ПоступлениеТоваров КАК Документ

ПО ТоварыПоступление.Ссылка = Документ.Ссылка

ГДЕ

ТоварыПоступление.Номенклатура = &Номенклатура

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ

Документ.Ссылка КАК Документ,

Документ.Дата КАК Дата,

Документ.Номер КАК Номер

ИЗ

Документ.РеализацияТоваровУслуг.Товары КАК ТоварыРеализация

ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК Документ

ПО ТоварыРеализация.Ссылка = Документ.Ссылка

ГДЕ

ТоварыРеализация.Номенклатура = &Номенклатура

Альтернативный вариант с использованием ВЫРАЗИТЬ() (если нужно проверять тип в одной таблице):

ВЫБРАТЬ

Документ.Ссылка КАК Документ,

Документ.Дата КАК Дата

ИЗ

РегистрСведений.ДвиженияТоваров КАК Движения

ГДЕ

Движения.Номенклатура = &Номенклатура

И (

ВЫРАЗИТЬ(Движения.ДокументОснова КАК ДокументСсылка.ПоступлениеТоваров) ЕСТЬ NULL = ЛОЖЬ

ИЛИ

ВЫРАЗИТЬ(Движения.ДокументОснова КАК ДокументСсылка.РеализацияТоваровУслуг) ЕСТЬ NULL = ЛОЖЬ

)

Убедитесь, что параметр &Номенклатура содержит корректную ссылку

Проверьте наличие прав на чтение документов ПоступлениеТоваров и РеализацияТоваровУслуг

Если используете ОБЪЕДИНИТЬ ВСЕ, добавьте сортировку по Дате для читаемого результата

Тестируйте запрос на небольшом периоде данных перед запуском на полной базе

-->

6. Оптимизация производительности

Проверка типов в запросах может замедлять выполнение, особенно на больших объемах данных. Несколько советов для оптимизации:

  • 🔥 Совет 1: Если возможно, фильтруйте данные по типу на уровне источника (например, используйте отдельные таблицы для разных типов документов вместо ОБЪЕДИНИТЬ ВСЕ).
  • 🔥 Совет 2: Для часто используемых проверок создайте вычисляемые поля в виртуальных таблицах или регистрах сведений.
  • 🔥 Совет 3: Избегайте вложенных ВЫРАЗИТЬ() — они значительно увеличивают время выполнения.

Пример оптимизированного запроса (с предварительной фильтрацией по регистру):

ВЫБРАТЬ

Движения.ДокументОснова КАК Документ,

ВЫБОР

КОГДА ВЫРАЗИТЬ(Движения.ДокументОснова КАК ДокументСсылка.ПоступлениеТоваров) ЕСТЬ NULL = ЛОЖЬ

ТОГДА "Поступление"

КОГДА ВЫРАЗИТЬ(Движения.ДокументОснова КАК ДокументСсылка.РеализацияТоваровУслуг) ЕСТЬ NULL = ЛОЖЬ

ТОГДА "Реализация"

КОНЕЦ КАК ТипДокумента

ИЗ

РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты(&НачалоПериода, &КонецПериода,) КАК Движения

ГДЕ

Движения.Номенклатура = &Номенклатура

⚠️ Внимание: Начиная с версии платформы 1С:Предприятие 8.3.20, появилась возможность использовать оператор ТИП в запросах для упрощения проверок. Пример:
ГДЕ ТИП(Движения.ДокументОснова) = ТИП(ДокументСсылка.ПоступлениеТоваров)

Однако этот синтаксис не поддерживается в более ранних версиях.

7. Работа с внешними источниками данных

При обмене данными между базами или загрузке из внешних систем (например, Excel, JSON, XML) ссылки часто теряют информацию о типе. В таких случаях:

  1. Используйте уникальные идентификаторы (ГУИД) для восстановления ссылок.
  2. При загрузке явно указывайте тип объекта:
    НоваяСсылка = Справочники.Номенклатура.НайтиПоНаименованию(ИмяИзФайла);
    

    Если НоваяСсылка.Пустая() Тогда

    НоваяСсылка = Справочники.Номенклатура.СоздатьЭлемент();

    НоваяСсылка.Наименование = ИмяИзФайла;

    НоваяСсылка.Записать();

    КонецЕсли;

  3. Для документов проверяйте не только тип, но и вид документа (если используется подсистема видов):
    Если Ссылка.ЭтоГруппа() = Ложь И ТипЗнч(Ссылка) = Тип("ДокументСсылка.ЗаказПокупателя") Тогда
    

    ВидДокумента = Ссылка.Вид();

    КонецЕсли;

При работе с HTTP-сервисами или REST API ссылки обычно передаются в виде строк (ГУИД или код+тип). Для восстановления ссылки используйте:

Ссылка = Метаданные.Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор(ГУИДИзJSON));
💡

При обмене данными всегда фиксируйте не только значение ссылки, но и её тип. Это позволит корректно восстановить объекты в другой базе, даже если их структура отличается.

FAQ: Частые вопросы по проверке типов ссылок

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

Используйте базовый тип ДокументСсылка с проверкой через ЭтоТип():

Если ЭтоТип(Ссылка, Тип("ДокументСсылка")) Тогда

// Это документ (любого вида)

КонецЕсли;

В запросе это сделать сложнее — придется перечислять все возможные виды документов через ВЫРАЗИТЬ().

Почему ТИПЗНАЧ() возвращает "СправочникСсылка.ЛюбаяСсылка" вместо конкретного справочника?

Это означает, что ссылка объявлена как полиморфный тип (например, в реквизите документа указан тип СправочникСсылка.ЛюбаяСсылка). В таком случае:

  • В запросе используйте ВЫРАЗИТЬ(Ссылка КАК СправочникСсылка.КонкретныйСправочник) ЕСТЬ NULL.
  • В коде применяйте ЭтоТип(Ссылка, Тип("СправочникСсылка.КонкретныйСправочник")).
Можно ли в одном запросе отфильтровать ссылки по нескольким типам?

Да, используйте оператор ИЛИ с несколькими проверками ВЫРАЗИТЬ():

ГДЕ

ВЫРАЗИТЬ(Ссылка КАК СправочникСсылка.Номенклатура) ЕСТЬ NULL = ЛОЖЬ

ИЛИ ВЫРАЗИТЬ(Ссылка КАК СправочникСсылка.Услуги) ЕСТЬ NULL = ЛОЖЬ

Или через ВЫБОР КОГДА:

ГДЕ

ВЫБОР

КОГДА ВЫРАЗИТЬ(Ссылка КАК СправочникСсылка.Номенклатура) ЕСТЬ NULL = ЛОЖЬ

ТОГДА ИСТИНА

КОГДА ВЫРАЗИТЬ(Ссылка КАК СправочникСсылка.Услуги) ЕСТЬ NULL = ЛОЖЬ

ТОГДА ИСТИНА

ИНАЧЕ ЛОЖЬ

КОНЕЦ = ИСТИНА

Как узнать тип ссылки, если она хранится в строковом поле (например, в JSON)?

Если ссылка была сериализована в строку (например, в формате "Справочник.Номенклатура.000000001"), восстановить её тип можно так:

  1. Разберите строку на части (разделитель — точка).
  2. Первые два элемента дадут тип (например, "Справочник.Номенклатура").
  3. Используйте Метаданные().НайтиПоИмени() для получения объекта метаданных:
Части = СтроковыеФункции.Разделить(СтрокаСсылки, ".");

Если Части[0] = "Справочник" Тогда

Справочник = Метаданные.Справочники.Найти(Части[1]);

Если Справочник <> Неопределено Тогда

Ссылка = Справочник.ПолучитьСсылку(Новый УникальныйИдентификатор(Части[2]));

КонецЕсли;

КонецЕсли;

Почему при проверке типа в запросе получаю ошибку "Недопустимое выражение в предложении WHERE"?

Эта ошибка возникает, если:

  • Вы используете ТИПЗНАЧ() в секции WHERE для поля, которое не участвует в выборке. Решение: добавьте поле в ВЫБРАТЬ.
  • Пытаетесь сравнить с несуществующим типом (опечатка в имени). Проверьте точное название типа в конфигураторе.
  • В запросе используются виртуальные таблицы, не поддерживающие проверку типов. Попробуйте заменить на обычные таблицы.