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

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

Проверка в 1С, что значение является ссылкой

Как в 1С проверить, что значение является ссылкой: ТипЗнч, ОписаниеТипов, Справочники.ТипВсеСсылки, проверка вида ссылки и заполненности. Примеры кода.

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

Задача «проверить, что это ссылка» встречается в нескольких вариантах: определить, что значение вообще ссылочного типа; убедиться, что это ссылка конкретного вида (например, именно «СправочникСсылка.Номенклатура»); проверить, что ссылка заполнена, а не пустая. Для каждого варианта есть свой инструмент, и смешивать их не стоит.

Что вообще считается ссылкой в 1С

Ссылочные типы в 1С — это типы, значения которых указывают на объект в базе данных, а не хранят данные сами по себе. К ним относятся СправочникСсылка, ДокументСсылка, ПеречислениеСсылка, ПланВидовХарактеристикСсылка, ПланСчетовСсылка, ПланВидовРасчетаСсылка, БизнесПроцессСсылка, ЗадачаСсылка, ПланОбменаСсылка, а также уникальный идентификатор в связке с ними. Примитивные значения — строка, число, дата, булево, Неопределено, NULL — ссылками не являются.

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

Проверка на конкретный вид ссылки через ТипЗнч

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

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

// это именно нужная ссылка

КонецЕсли;

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

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

Универсальная проверка «это любая ссылка»

Единой встроенной функции «ЭтоСсылка()» в платформе нет, поэтому универсальную проверку строят через описание типов. У каждого менеджера объектов есть метод ТипВсеСсылки(), возвращающий описание всех ссылочных типов данного класса. Объединив их, получают полное описание:

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

ОписаниеВсехСсылок = Справочники.ТипВсеСсылки();

ОписаниеВсехСсылок = Новый ОписаниеТипов(ОписаниеВсехСсылок, Документы.ТипВсеСсылки().Типы());

ОписаниеВсехСсылок = Новый ОписаниеТипов(ОписаниеВсехСсылок, Перечисления.ТипВсеСсылки().Типы());

ОписаниеВсехСсылок = Новый ОписаниеТипов(ОписаниеВсехСсылок, ПланыВидовХарактеристик.ТипВсеСсылки().Типы());

ОписаниеВсехСсылок = Новый ОписаниеТипов(ОписаниеВсехСсылок, ПланыСчетов.ТипВсеСсылки().Типы());

ОписаниеВсехСсылок = Новый ОписаниеТипов(ОписаниеВсехСсылок, ПланыВидовРасчета.ТипВсеСсылки().Типы());

ОписаниеВсехСсылок = Новый ОписаниеТипов(ОписаниеВсехСсылок, БизнесПроцессы.ТипВсеСсылки().Типы());

ОписаниеВсехСсылок = Новый ОписаниеТипов(ОписаниеВсехСсылок, Задачи.ТипВсеСсылки().Типы());

ОписаниеВсехСсылок = Новый ОписаниеТипов(ОписаниеВсехСсылок, ПланыОбмена.ТипВсеСсылки().Типы());

Возврат ОписаниеВсехСсылок.СодержитТип(ТипЗнч(Значение));

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

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

Проверка заполненности и пустой ссылки

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

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

Возврат; // ссылка пустая или значение примитивное пустое

КонецЕсли;

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

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

КонецЕсли;

Учтите, что ЗначениеЗаполнено() для примитивных типов проверяет их «непустоту» (ноль, пустая строка), поэтому сама по себе она не доказывает, что значение — ссылка. Правильный порядок: сначала проверить тип, затем заполненность. Также помните про «битые ссылки» — ссылка может быть заполненной, но объект в базе удалён; это выявляется проверкой на NULL в запросе или попыткой чтения реквизита.

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

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

Тип значения
Норма

ТипЗнч вернул ожидаемый ссылочный тип

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

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

Заполненность
Норма

ЗначениеЗаполнено() = Истина

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

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

Существование объекта
Норма

Запрос к реквизиту вернул значение

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

Запрос вернул NULL — битая ссылка, объект удалён

Проверка ссылки в запросе

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

ВЫБРАТЬ

Рег.Объект КАК Объект

ИЗ

РегистрСведений.ДополнительныеСведения КАК Рег

ГДЕ

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

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

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

Частая ошибка — обращение к реквизиту до проверки типа. Код вида Если Параметр.Наименование = "" Тогда упадёт, если в Параметр передали строку или число. Сначала тип, потом реквизиты.

Вторая ошибка — сравнение ссылки со строкой её представления: Если Контрагент = "Иванов" Тогда. Такое сравнение всегда ложно, потому что ссылка не равна строке. Для поиска по наименованию используйте Справочники.Контрагенты.НайтиПоНаименованию() или запрос.

Третья группа ошибок — путаница между объектом и ссылкой. После ПолучитьОбъект() переменная содержит СправочникОбъект, и проверка ТипЗнч() = Тип("СправочникСсылка.Номенклатура") вернёт ложь. Если нужно получить ссылку обратно, используйте свойство Объект.Ссылка.

Типичные ошибки
01
Обращение к реквизитам до проверки типа — падение кода на примитивных значениях
02
Сравнение ссылки со строкой представления — условие никогда не сработает
03
Проверка ТипЗнч после ПолучитьОбъект() — тип уже Объект, а не Ссылка
04
Использование ЗначениеЗаполнено() как единственной проверки — она не доказывает ссылочность типа
05
Перечисление видов ссылок через ИЛИ вместо ТипВсеСсылки() — код ломается при добавлении новых объектов в конфигурацию

Выбор способа проверки под задачу

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

Для реквизитов составного типа полезно смотреть описание типов самого реквизита через метаданные: Метаданные.Документы.Заказ.Реквизиты.Контрагент.Тип — так можно заранее ограничить набор допустимых типов без жёсткого кодирования.

Сравнение способов проверки

ТипЗнч() = Тип("...")

Конкретный вид ссылки; быстро и читаемо, но не подходит для проверки 'любая ссылка'

ТипВсеСсылки() + СодержитТип()

Универсальная проверка ссылочности; требует перечисления менеджеров и чуть медленнее

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

Готовое решение в типовых конфигурациях; недоступно в конфигурациях без БСП

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

Фильтрация по виду объекта в запросе; работает только внутри текста запроса

Итог

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

Проверка «это ссылка» строится на ТипЗнч() и описаниях типов: для конкретного вида — прямое сравнение типа, для любой ссылки — ТипВсеСсылки() или функция ЭтоСсылка из БСП. Сначала проверяйте тип, затем заполненность, и только потом обращайтесь к реквизитам. В запросах используйте оператор ССЫЛКА.

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

Как отличить ссылку от объекта в коде?

Вызовите ТипЗнч() и сравните: для ссылки тип будет вида «СправочникСсылка.Имя», для объекта — «СправочникОбъект.Имя». Универсально можно проверить имя типа через Строка(ТипЗнч(Значение)) и поиск подстроки «Ссылка» / «Объект», но надёжнее сравнение с конкретным типом.

Можно ли проверить ссылку без указания конкретного вида объекта?

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

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

Вероятно, это «битая ссылка»: само значение ссылки непустое, но объект в базе удалён. Проверить можно запросом — выборка реквизита по такой ссылке вернёт NULL, либо сравнением с УникальныйИдентификатор и попыткой чтения.

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

Используйте оператор ССЫЛКА: «ГДЕ Поле ССЫЛКА Справочник.Номенклатура». Альтернатива — ТИПЗНАЧЕНИЯ(Поле) = ТИП(Справочник.Номенклатура), но она медленнее на больших таблицах.

Что вернёт ТипЗнч() для Неопределено и NULL?

Для Неопределено — тип «Неопределено», для NULL — «Null». Оба значения не являются ссылками, и универсальная проверка через ТипВсеСсылки() корректно вернёт для них ложь, дополнительной обработки обычно не требуется.

Нужно ли проверять тип, если реквизит имеет строгий тип ссылки?

Если тип реквизита или параметра жёстко задан в метаданных и значение приходит только оттуда, дополнительная проверка избыточна — достаточно проверки заполненности. Проверка типа обязательна для параметров произвольного типа, значений из хранилища значений, JSON и внешних источников.