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