ЗначениеЗаполнено, Пустая(), ЕСТЬ NULL: чем и где ловить незаполненные данные в 1С 8.3

· 9 мин

Содержание

Проверить пустое значение в 1С 8.3 проще всего функцией ЗначениеЗаполнено(Значение): она вернёт Ложь для пустой ссылки, нуля, пустой строки, пустой даты, Неопределено и Null. В запросе так не получится — там пустоту проверяют конструкцией Поле ЕСТЬ NULL, функцией ЕСТЬNULL() и сравнением с ЗНАЧЕНИЕ(...ПустаяСсылка).

Остальные способы нужны для частных случаев: строка из пробелов, «битая» ссылка на удалённый объект, реквизит составного типа, пустая табличная часть. Ниже каждый случай с рабочим кодом. Всё описанное относится к платформе 8.3 и не зависит от конфигурации: одинаково работает в БП 3.0, ЗУП 3.1, УТ 11 и самописных базах.

Функции ПустоеЗначение() в 1С 8.3 нет. Она была во встроенном языке 1С 7.7. Если переносите старый код, заменяйте её на ЗначениеЗаполнено() — и инвертируйте условие: ПустоеЗначение(Х) = 1 превращается в Не ЗначениеЗаполнено(Х).

Что 1С считает пустым значением для каждого типа

У каждого типа данных есть значение по умолчанию. Его и называют пустым: именно его получает новый реквизит, пока пользователь ничего не ввёл.

ТипПустое значениеКак записать в коде
Число00
Строкастрока нулевой длины""
Дата01.01.0001 00:00:00'00010101' или Дата(1, 1, 1)
Ссылка на справочник, документпустая ссылкаСправочники.Номенклатура.ПустаяСсылка()
Перечислениепустая ссылкаПеречисления.СтавкиНДС.ПустаяСсылка()
Составной типНеопределеноНеопределено
Отсутствие данных в запросеNullNull

Отдельно стоят два «особых» значения:

  • 🔹 Неопределено — значение не присвоено. Его возвращают, например, Массив.Найти() и ТаблицаЗначений.Найти(), если ничего не нашли. А вот НайтиПоКоду() у менеджера справочника вернёт не Неопределено, а пустую ссылку. Это же пустое значение реквизита составного типа.
  • 🔸 Null — отсутствие значения в базе данных. Чаще всего приходит из запроса: левое соединение не нашло пары, или вы обратились через точку к реквизиту пустой ссылки.

Null и Неопределено — разные значения. Выражение Null = Неопределено даёт Ложь, поэтому проверка «на Неопределено» пропустит Null из запроса.

Пять способов проверить значение на пустоту во встроенном языке

1. ЗначениеЗаполнено() — универсальный способ

Функция работает с любым типом и доступна и на сервере, и на клиенте. Это основной инструмент: в 9 случаях из 10 достаточно его.

Если Не ЗначениеЗаполнено(Объект.Контрагент) Тогда
    Сообщение = Новый СообщениеПользователю;
    Сообщение.Текст = "Не указан контрагент";
    Сообщение.Поле = "Объект.Контрагент";
    Сообщение.Сообщить();
    Возврат;
КонецЕсли;

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

Для чисел ноль — это «не заполнено». Если в поле «Скидка, %» ноль — законное значение, ЗначениеЗаполнено() здесь не подходит. Проверяйте то, что действительно запрещено, например Скидка < 0.

2. Метод Пустая() у ссылки

У любой ссылки (справочник, документ, перечисление, план видов характеристик) есть метод Пустая().

Если Объект.Организация.Пустая() Тогда
    // организация не выбрана
КонецЕсли;

Метод удобен, когда тип точно известен. Но если в переменной окажется Неопределено или Null, получите ошибку Метод объекта не обнаружен (Пустая). Для реквизитов составного типа и данных из запроса берите ЗначениеЗаполнено().

3. Сравнение с пустым значением типа

Прямое сравнение читается однозначно и не зависит от особенностей функции:

Если Объект.ДатаОплаты = Дата(1, 1, 1) Тогда
    // дата не указана
КонецЕсли;

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

На клиенте менеджеры справочников недоступны. Там пустую ссылку получают так: ПредопределенноеЗначение("Справочник.Склады.ПустаяСсылка").

4. ПустаяСтрока() — для текста с пробелами

Строка " " формально непустая: у неё длина 3. Пользователь видит пустое поле, а Строка = "" вернёт Ложь. Глобальная функция ПустаяСтрока() проверяет, есть ли в строке значащие символы, и пробелы с переносами не считает.

Если ПустаяСтрока(Объект.Комментарий) Тогда
    // текста нет, даже если пользователь набил пробелов
КонецЕсли;

Аналог без отдельной функции — СокрЛП(Строка) = "".

5. Проверка типа: ТипЗнач()

Когда важно отличить Null от Неопределено или от пустой ссылки, сравнивайте тип:

Если ТипЗнач(Значение) = Тип("Null") Тогда
    // данных в базе нет — например, левое соединение не нашло строку
ИначеЕсли Значение = Неопределено Тогда
    // значение не присвоено
ИначеЕсли Не ЗначениеЗаполнено(Значение) Тогда
    // пустое значение своего типа: 0, "", пустая дата или ссылка
КонецЕсли;
СпособКогда применятьЧем рискуете
ЗначениеЗаполнено()почти всегданоль у числа считается пустым
.Пустая()тип точно ссылочныйошибка на Неопределено и Null
= ПустаяСсылка() / Дата(1,1,1)нужен конкретный типна клиенте нет менеджеров
ПустаяСтрока()строки из ручного ввода, файловтолько для строк
ТипЗнач()надо различить Null и Неопределеногромоздко

Как проверить на пустое значение в запросе 1С

Язык запросов живёт по своим правилам. Функции ЗначениеЗаполнено() в нём нет, а Null ведёт себя как в SQL: любое сравнение с ним не даёт истины.

ЕСТЬ NULL и функция ЕСТЬNULL()

Чтобы отобрать строки, для которых в присоединённой таблице ничего не нашлось, пишут ЕСТЬ NULL. Запись Поле = NULL не работает .

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

Запрос вернёт товары без остатков, а ЕСТЬNULL(..., 0) подставит ноль вместо Null. Без этой подстановки сложение Остаток + Приход в запросе даст Null, а в коде попытка сложить Null с числом упадёт с ошибкой преобразования типа.

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

Пустые ссылки, даты и строки в условиях

Пустая ссылка в тексте запроса задаётся через ЗНАЧЕНИЕ():

ГДЕ
    Документ.Контрагент = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)
    ИЛИ Документ.ДатаОплаты = ДАТАВРЕМЯ(1, 1, 1)
    ИЛИ Документ.НомерВходящий = ""

Тот же результат через параметр — если пустое значение приходит из кода:

Запрос.УстановитьПараметр("ПустойКонтрагент", Справочники.Контрагенты.ПустаяСсылка());

Для реквизита составного типа одной проверки на пустую ссылку мало: пустым он может быть как Неопределено. Надёжное условие — Поле = НЕОПРЕДЕЛЕНО ИЛИ Поле ЕСТЬ NULL плюс сравнение с пустыми ссылками тех типов, что в него входят.

Строки неограниченной длины

Реквизит типа «Строка» без ограничения длины нельзя сравнивать в запросе напрямую — платформа выдаст ошибку о недопустимом сравнении. Обрежьте значение до фиксированной длины:

ГДЕ
    ПОДСТРОКА(Документ.Комментарий, 1, 1) = ""

Или приведите тип: ВЫРАЗИТЬ(Документ.Комментарий КАК СТРОКА(10)) = "". Если таких проверок много, имеет смысл задать реквизиту длину в конфигураторе.

Пустые и «битые» ссылки: в чём разница

Пустая ссылка ни на что не указывает. «Битая» ссылка хранит идентификатор объекта, которого в базе больше нет: его удалили напрямую, минуя контроль ссылочной целостности, или данные пришли из обмена без самого объекта. На форме такая ссылка выглядит как <Объект не найден> (...).

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

  1. В конфигурациях на БСП (БП 3.0, ЗУП 3.1, УТ 11) — функцией ОбщегоНазначения.СсылкаСуществует(Ссылка) на сервере.
  2. Методом ПолучитьОбъект(): для несуществующего объекта он вернёт Неопределено. Способ тяжёлый — читает объект целиком, в циклах его не используйте.
  3. Запросом к таблице объекта:
Запрос = Новый Запрос(
"ВЫБРАТЬ ПЕРВЫЕ 1
|    ИСТИНА
|ИЗ
|    Справочник.Контрагенты КАК Т
|ГДЕ
|    Т.Ссылка = &Ссылка");
Запрос.УстановитьПараметр("Ссылка", Ссылка);
ОбъектЕсть = Не Запрос.Выполнить().Пустой();

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

Приёмы для составных типов, структур и коллекций

Свойство структуры может отсутствовать

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

Организация = Неопределено;
Если Не Параметры.Свойство("Организация", Организация)
    Или Не ЗначениеЗаполнено(Организация) Тогда
    Организация = ЗначениеПоУмолчанию; // ваша логика
КонецЕсли;

Одна строка закрывает оба случая: ключа нет и ключ есть, но значение пустое.

Пустая табличная часть и коллекция

Для таблиц, массивов и списков значений проверяйте количество элементов — так условие однозначно для любого читателя кода:

Если Объект.Товары.Количество() = 0 Тогда
    // табличная часть пуста
КонецЕсли;

Найти незаполненные строки табличной части удобнее циклом с ЗначениеЗаполнено() по нужной колонке. Номер строки берите из Строка.НомерСтроки, а не считайте сами.

Пустой результат с точкой через реквизит

Объект.Договор.Владелец при пустом договоре во встроенном языке вернёт пустое значение типа реквизита, а в запросе — Null. Код, который одинаково обрабатывает данные из объекта и из запроса, должен учитывать оба варианта. Здесь снова выручает ЗначениеЗаполнено(): ей всё равно, что пришло.

Проверка пустых значений на управляемой форме

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

Декларативная. В конфигураторе у реквизита объекта есть свойство «Проверка заполнения» со значением «Выдавать ошибку». Платформа сама не даст провести или записать объект с пустым реквизитом и подсветит поле. Писать код не нужно.

Программная — в модуле объекта. Условные проверки («КПП обязателен только для юрлиц») пишут в обработчике ОбработкаПроверкиЗаполнения. Он получает массив ПроверяемыеРеквизиты, из которого можно убрать лишнее:

Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
    Если ВидКонтрагента <> Перечисления.ВидыКонтрагентов.ЮридическоеЛицо Тогда
        Индекс = ПроверяемыеРеквизиты.Найти("КПП");
        Если Индекс <> Неопределено Тогда
            ПроверяемыеРеквизиты.Удалить(Индекс);
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

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

Визуальная — подсветка поля. У поля формы есть свойства АвтоОтметкаНезаполненного и ОтметкаНезаполненного. Первое включает красное подчёркивание пустого поля автоматически, второе позволяет управлять им из кода. Отметка ничего не запрещает — это только подсказка пользователю.

Пустые значения без программирования

Пользователю код не нужен. В отборе любого списка и в настройках отчёта на СКД есть виды сравнения «Заполнено» и «Не заполнено». Откройте настройки списка через меню Ещё, на закладке отбора добавьте поле и выберите «Не заполнено» — список покажет, например, все документы без указанного договора.

Перед выпуском кода с проверкой на пустоту
Выполнено: 0 / 5

Ошибки, на которых чаще всего спотыкаются

  • ❌ Метод объекта не обнаружен (Пустая). В переменной Неопределено или Null, а не ссылка. Замените .Пустая() на ЗначениеЗаполнено().
  • ❌ Условие Поле = NULL в запросе ничего не отбирает. Пишите Поле ЕСТЬ NULL или НЕ Поле ЕСТЬ NULL.
  • ❌ Документ с нулевой суммой не проходит проверку. Для числа ноль — пустое значение. Если ноль допустим, ЗначениеЗаполнено() по этому полю не используйте.
  • ❌ Проверка = Неопределено пропускает данные из запроса. Из запроса пришёл Null. Используйте ЗначениеЗаполнено() или ЕСТЬNULL() прямо в тексте запроса.
  • ❌ Справочники.Склады.ПустаяСсылка() в клиентской процедуре. На клиенте менеджеров нет — используйте ПредопределенноеЗначение() или передайте проверку на сервер.
  • ❌ Ссылка «заполнена», а объекта нет. Это битая ссылка; ищите её через СсылкаСуществует() или запрос, а не через ЗначениеЗаполнено().

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

Чем ЗначениеЗаполнено() отличается от проверки на Неопределено?
ЗначениеЗаполнено() считает пустыми и Неопределено, и Null, и пустые значения конкретных типов: 0, пустую строку, пустую дату и ссылку. Сравнение = Неопределено ловит только одно из них.
Можно ли использовать ЗначениеЗаполнено() в запросе?
Нет, это функция встроенного языка. В запросе пустоту проверяют через ЕСТЬ NULL, ЕСТЬNULL() и сравнение с ЗНАЧЕНИЕ(...ПустаяСсылка), пустой датой или пустой строкой.
Как проверить, что запрос ничего не вернул?
Вызовите Пустой() у результата: Если Запрос.Выполнить().Пустой() Тогда. Выгружать результат и считать строки для этого не нужно.
Работает ли ЗначениеЗаполнено() на клиенте?
Да, функция доступна на тонком клиенте и в веб-клиенте. Недоступны на клиенте менеджеры справочников, поэтому пустую ссылку там получают через ПредопределенноеЗначение().
Как найти все документы с незаполненным реквизитом без кода?
Откройте список документов, через меню Ещё откройте настройки списка и добавьте отбор по реквизиту с видом сравнения «Не заполнено».