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

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

Как проверить на пустую ссылку в 1С

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

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

Главная сложность в том, что способов проверки несколько, и они не всегда взаимозаменяемы: сравнение через «=» работает не для всех типов, функция ЗначениеЗаполнено() имеет свои нюансы, а в запросах логика отличается от кода модуля. Ниже разобраны все рабочие варианты с примерами и границами применения.

Что такое пустая ссылка и чем она отличается от NULL

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

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

Сравнение с ПустаяСсылка() — основной способ

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

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

Сообщить("Контрагент не заполнен");

КонецЕсли;

Для перечислений синтаксис аналогичный: Перечисления.СтавкиНДС.ПустаяСсылка(). Способ хорош тем, что явно показывает, какой тип ожидается, и легко читается при ревью кода. Ограничение очевидно: нужно заранее знать тип проверяемого значения. Если реквизит составного типа (например, контрагент может быть справочником «Контрагенты» или «Организации»), одного сравнения недостаточно.

Универсальная функция ЗначениеЗаполнено()

Функция ЗначениеЗаполнено(Значение) возвращает Истина, если значение заполнено, и Ложь — если оно пустое. Для ссылок пустым считается значение, равное пустой ссылке своего типа. Главное достоинство — функция работает с любым типом: ссылками, строками, числами, датами, булево.

Если НЕ ЗначениеЗаполнено(ДокументОснование) Тогда

Возврат;

КонецЕсли;

Именно этот вариант рекомендуется, когда тип значения заранее неизвестен или реквизит составного типа: функция сама определит пустую ссылку нужного вида. Она же корректно обработает Неопределено — вернёт Ложь.

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

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

= Менеджер.ПустаяСсылка()

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

ЗначениеЗаполнено()

Универсально для любых типов и составных реквизитов, обрабатывает Неопределено. Чуть медленнее в массовых циклах.

Ссылка.Пустая()

Метод самого значения, удобен когда тип неизвестен. Не работает для Неопределено и NULL — вызовет ошибку.

Метод Пустая() и проверка составных реквизитов

У самого значения ссылочного типа есть метод Пустая(), который возвращает Истина для пустой ссылки. Это удобно, когда тип неизвестен и нет желания вызывать менеджер:

Если ТипЗнч(Объект.Владелец) = Тип("СправочникСсылка.Контрагенты")

И Объект.Владелец.Пустая() Тогда

// обработка

КонецЕсли;

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

Типичные ошибки
01
Вызов Ссылка.Пустая() без проверки на Неопределено — падение кода с ошибкой типа
02
Сравнение ссылки с пустой строкой "" или числом 0 — условие никогда не сработает либо даст ошибку сравнения типов
03
Проверка результата левого соединения через ПустаяСсылка() вместо ЕСТЬ NULL — пустая ссылка и NULL не равны
04
Обращение к реквизитам через точку (Ссылка.Наименование) до проверки на пустоту — лишнее обращение к базе и риск ошибки

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

В языке запросов своя логика. Пустая ссылка конкретного типа задаётся литералом ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка):

ВЫБРАТЬ

Товары.Номенклатура

ИЗ

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

ГДЕ

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

Альтернатива — передать пустую ссылку параметром: Запрос.УстановитьПараметр("ПустаяНоменклатура", Справочники.Номенклатура.ПустаяСсылка()) и в тексте писать ГДЕ Номенклатура = &ПустаяНоменклатура. Это гибче, когда тип определяется в коде динамически.

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

bsl
Если НЕ ЗначениеЗаполнено(Ссылка) Тогда
    ВызватьИсключение "Не заполнен обязательный реквизит";
КонецЕсли;

// В запросе:
// ГДЕ Таб.Контрагент <> ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)
// ГДЕ НЕ Таб.Контрагент ЕСТЬ NULL

Проверка в СКД, на форме и в типовых механизмах

В схеме компоновки данных условие на пустую ссылку добавляется в отбор: поле сравнивается со значением, которое задаётся через тот же литерал ЗНАЧЕНИЕ(...) в выражении языка запросов, либо в пользовательских настройках отбора выбирается вариант «Не заполнено» — СКД сама сформирует корректное условие для ссылочного типа.

На управляемой форме проверку заполнения реквизита лучше не писать вручную, а использовать стандартный механизм: установить у реквизита свойство «Проверка заполнения» = «Выдавать ошибку». Тогда платформа сама подсветит незаполненное поле и не даст провести документ. Ручная проверка через ЗначениеЗаполнено() нужна только для нестандартной логики — например, когда обязательность зависит от других полей.

Порядок действий при выборе способа

Как выбрать проверку
  1. 1
    Определите, где выполняется проверка: в коде модуля или в запросе
  2. 2
    Если в коде и тип реквизита известен и единственный — используйте сравнение с Менеджер.ПустаяСсылка()
  3. 3
    Если реквизит составного типа или тип неизвестен — используйте ЗначениеЗаполнено()
  4. 4
    Если в запросе — литерал ЗНАЧЕНИЕ(Тип.ПустаяСсылка) или параметр; для полей левого соединения добавьте проверку ЕСТЬ NULL
  5. 5
    Проверьте результат: выполните код на записи с пустым и заполненным реквизитом, убедитесь, что ветки условия срабатывают корректно
Контрольные точки

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

Реквизит не заполнен
Норма

Условие срабатывает, выполняется ветка обработки пустого значения

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

Условие пропускается или возникает ошибка сравнения типов

Реквизит заполнен реальной ссылкой
Норма

Проверка возвращает 'заполнено', логика продолжается штатно

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

Заполненная ссылка ошибочно считается пустой — значит сравниваете с пустой ссылкой другого типа

Поле из левого соединения без пары
Норма

Отрабатывает условие ЕСТЬ NULL

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

Проверка на пустую ссылку не ловит значение — это NULL, а не пустая ссылка

Итог

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

В коде используйте сравнение с ПустаяСсылка() конкретного типа или универсальную ЗначениеЗаполнено(). В запросах — ЗНАЧЕНИЕ(...ПустаяСсылка) и не забывайте про NULL в соединениях. Пустая ссылка, NULL и Неопределено — три разных состояния, и смешивать их проверки нельзя.

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

Чем пустая ссылка отличается от битой ссылки?

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

Почему сравнение Ссылка = Неопределено не ловит пустую ссылку?

Потому что это разные значения. Неопределено — отсутствие значения вообще, а пустая ссылка — вполне определённое значение конкретного типа. Реквизит ссылочного типа, который никогда не заполняли, обычно содержит именно пустую ссылку, а не Неопределено.

Как проверить на пустую ссылку реквизит составного типа?

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

Работает ли ЗначениеЗаполнено в запросах?

Нет, в языке запросов этой функции нет. В запросе используйте сравнение с ЗНАЧЕНИЕ(Тип.ПустаяСсылка), параметр с пустой ссылкой или проверку ЕСТЬ NULL для полей соединений.

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

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

Как найти в базе все документы с незаполненным контрагентом?

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