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

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

Как в 1С проверить, что значение — это ссылка

Как в 1С проверить, что значение является ссылкой: функции СсылкаСуществует, ТипЗнч, ЭтоСсылка, проверка в запросе. Примеры кода и типичные ошибки.

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

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

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

Что такое ссылка в 1С и чем она отличается от объекта

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

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

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

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

Функция ТипЗнч(Значение) возвращает тип переданного значения. Сравнив результат с конкретным типом ссылки, вы одновременно проверяете и «ссылочность», и вид объекта. Это самый частый и самый надёжный вариант:

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

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

КонецЕсли;

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

Если нужно проверить принадлежность к одному из нескольких типов, сравнения записывают через «Или» либо используют ОписаниеТипов:

ТекТип = ТипЗнч(Значение);

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

Или ТекТип = Тип("ДокументСсылка.ВозвратТоваровПоставщику") Тогда

// обработка документов отгрузки и возврата

КонецЕсли;

Проверка «ссылочности» без привязки к виду объекта

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

Первый — использование общего модуля или функции-обёртки, которая проверяет тип через метаданные. В типовых конфигурациях на БСП есть функция ОбщегоНазначения.ЭтоСсылка(Тип), которая определяет, является ли переданный тип ссылочным, по метаданным. Вызов выглядит так:

Если ОбщегоНазначения.ЭтоСсылка(ТипЗнч(Значение)) Тогда

// Значение — ссылка любого вида

КонецЕсли;

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

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

Если Значение = Неопределено Тогда

Возврат Ложь;

КонецЕсли;

МетаданныеЗначения = Значение.Метаданные();

Возврат Метаданные.Справочники.Содержит(МетаданныеЗначения)

Или Метаданные.Документы.Содержит(МетаданныеЗначения)

Или Метаданные.ПланыВидовХарактеристик.Содержит(МетаданныеЗначения)

Или Метаданные.Перечисления.Содержит(МетаданныеЗначения);

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

Проверка в запросе: ССЫЛКА и ВЫРАЗИТЬ

В запросах проверка «это ссылка нужного вида» выполняется оператором ССЫЛКА. Он сравнивает тип поля с указанной таблицей и особенно полезен для реквизитов составного типа, где в одном поле могут лежать ссылки разных видов:

ВЫБРАТЬ

Отбор.Значение КАК Значение

ИЗ

РегистрСведений.ЗначенияСвойств КАК Отбор

ГДЕ

Отбор.Значение ССЫЛКА Справочник.Номенклатура

Если требуется обратиться к реквизитам составного поля, используют ВЫРАЗИТЬ — оператор приводит значение к конкретному типу, а для несоответствующих значений даёт NULL:

ВЫБРАТЬ

ВЫРАЗИТЬ(Отбор.Значение КАК Справочник.Номенклатура).Артикул КАК Артикул

ИЗ

РегистрСведений.ЗначенияСвойств КАК Отбор

Обращение к реквизитам составного поля через точку без ВЫРАЗИТЬ приводит к неявным соединениям со всеми таблицами возможных типов — это резко замедляет запрос. Проверка через ССЫЛКА в условии ГДЕ такой проблемы не создаёт и работает быстро.

Сравнение вариантов

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

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

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

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

ВЫРАЗИТЬ в запросе

Подходит, когда нужно добраться до реквизитов составного поля. Для несоответствующих типов даёт NULL, что нужно учитывать.

ЭтоСсылка через метаданные

Подходит для универсальных проверок любой ссылки. Требует серверного контекста и аккуратной обработки примитивов.

Проверка существования ссылки в базе

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

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

Если Не ОбщегоНазначения.СсылкаСуществует(НоменклатураСсылка) Тогда

ВызватьИсключение "Элемент номенклатуры не найден в базе";

КонецЕсли;

Вне БСП аналог пишется запросом вида «ВЫБРАТЬ ПЕРВЫЕ 1 Ссылка ИЗ Справочник.Номенклатура ГДЕ Ссылка = &Ссылка». Также признаком битой ссылки служит её строковое представление вида «<Объект не найден> (...)», но парсить строку для проверки нельзя — представление зависит от локали и настроек, такой код ненадёжен.

Проверка на пустую ссылку

Частая смежная задача — определить, что ссылка не заполнена. Пустая ссылка имеет корректный тип, но нулевой уникальный идентификатор. Проверяют её функцией ЗначениеЗаполнено() или сравнением с пустой ссылкой конкретного вида:

Если Не ЗначениеЗаполнено(Контрагент) Тогда

// реквизит не заполнен

КонецЕсли;

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

// то же самое, но с привязкой к виду

КонецЕсли;

Важно различать три состояния: Неопределено (типа нет вообще), пустая ссылка (тип есть, записи нет) и битая ссылка (тип есть, запись была, но удалена). ЗначениеЗаполнено(Неопределено) вернёт Ложь, как и для пустой ссылки, поэтому, если различие важно, проверки комбинируют с ТипЗнч.

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

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

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

Возвращает Истина только для ссылок этого справочника

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

Исключение при выполнении — опечатка в имени типа

ЗначениеЗаполнено(Ссылка)
Норма

Ложь для пустой ссылки и Неопределено

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

Истина для битой ссылки — её существование проверяется отдельно

ССЫЛКА в условии запроса
Норма

Отбираются только записи нужного вида

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

Пустой результат при корректных данных — проверьте имя таблицы в операторе

СсылкаСуществует(Ссылка)
Норма

Ложь для удалённых объектов

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

Истина, но реквизиты недоступны — проверьте, не перепутаны ли объект и ссылка

Типичные ошибки при проверке ссылок

Большинство проблем возникает не из-за сложности механизмов, а из-за смешения разных проверок. Ниже — ошибки, которые встречаются чаще всего.

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

FAQ

Чем отличается проверка ТипЗнч от проверки через ССЫЛКА в запросе?

ТипЗнч работает в коде встроенного языка и сравнивает тип конкретного значения. Оператор ССЫЛКА применяется только внутри запроса и фильтрует записи по виду ссылки на уровне СУБД. Для отбора данных в выборках используйте ССЫЛКА, для логики в коде — ТипЗнч.

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

В запросе перечислить все виды документов нельзя компактно, поэтому обычно проверяют нужные виды через ССЫЛКА с ИЛИ. В коде можно получить тип значения через ТипЗнч, найти его метаданные и проверить вхождение в Метаданные.Документы — это универсально и не требует перечисления видов.

Почему ЗначениеЗаполнено возвращает Истина, а при обращении к реквизиту ошибка?

Это признак битой ссылки: тип корректен, идентификатор заполнен, но запись удалена из базы. ЗначениеЗаполнено проверяет только пустоту, а не существование. Добавьте проверку СсылкаСуществует (в БСП) или лёгкий запрос к таблице по этой ссылке.

Можно ли проверить «ссылочность» на клиенте без вызова сервера?

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

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

Перечисления тоже являются ссылочными типами. Используйте сравнение ТипЗнч(Значение) = Тип("ПеречислениеСсылка.ИмяПеречисления") или проверку вхождения метаданных значения в Метаданные.Перечисления. Учтите, что у перечислений нет ПолучитьОбъект() в привычном смысле и проверка существования им обычно не нужна.

Итог

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

Проверка «это ссылка» в 1С делается через ТипЗнч и Тип() в коде и через оператор ССЫЛКА в запросах. Проверка типа, проверка заполненности и проверка существования — три разные задачи: битая ссылка проходит первые две. Не используйте ПолучитьОбъект() и строковые представления для проверок — это медленно и ненадёжно.