Пустое значение в 1С 8.3: ЗначениеЗаполнено, ПустаяСтрока, Пустая() и NULL
Содержание
Проверить, пустое ли поле в 1С, проще всего функцией ЗначениеЗаполнено(Поле): она вернёт Ложь для пустой строки, нуля, пустой даты, пустой ссылки, Неопределено и Null. Для строки, где важно отсечь одни пробелы, берите ПустаяСтрока(Поле), для ссылки конкретного типа — Поле.Пустая(), а в тексте запроса — ЕСТЬ NULL и сравнение с ЗНАЧЕНИЕ(...ПустаяСсылка).
Выбор способа зависит от типа поля и от того, где идёт проверка: во встроенном языке или в запросе. Всё сказанное относится к платформе 1С:Предприятие 8.3 и одинаково работает в любой конфигурации: БП, ЗУП, УТ или самописной.
Какие бывают «пустые» значения в 1С
В 1С нет одного универсального «пусто». У каждого типа своё значение по умолчанию, и оно разное по смыслу.
| Тип поля | Что считается пустым | Как выглядит в коде |
|---|---|---|
| Строка | строка без символов | "" |
| Число | ноль | 0 |
| Дата | 1 января 1 года, 00:00:00 | '00010101' или Дата(1, 1, 1) |
| Булево | значение по умолчанию | Ложь |
| Ссылка на справочник, документ | пустая ссылка своего типа | Справочники.Контрагенты.ПустаяСсылка() |
| Перечисление | пустая ссылка перечисления | Перечисления.ВидыДоговоров.ПустаяСсылка() |
| Составной тип | значение не выбрано | Неопределено |
| Результат запроса | данных нет | Null |
Отсюда три разных сущности, которые путают чаще всего:
- 🔹 Пустое значение типа — пустая строка, ноль, пустая ссылка. Тип у поля есть, значение по умолчанию.
- 🔹
Неопределено— значение без типа. Его хранит реквизит составного типа, пока в нём ничего не выбрано, его же возвращает функция, которой нечего вернуть. - 🔹
Null— признак отсутствия данных. Появляется в результате запроса, чаще всего после левого соединения, когда справа нет записи.
Пустая ссылка и Неопределено — не одно и то же. Сравнение Справочники.Контрагенты.ПустаяСсылка() = Неопределено даст Ложь. Поэтому одной проверкой «= Неопределено» пустой реквизит ссылочного типа не поймать.
Пустая строка: ПустаяСтрока, СокрЛП и сравнение с ""
Для строковых реквизитов есть три рабочих способа.
1. Функция ПустаяСтрока(). Возвращает Истина, если в строке нет значащих символов. Строка из одних пробелов, табуляций и переводов строк тоже считается пустой.
Если ПустаяСтрока(Объект.Комментарий) Тогда
Сообщить("Заполните комментарий");
КонецЕсли;
2. Сравнение с пустой строкой. Если Объект.ИНН = "" Тогда сработает только на строку совсем без символов. Три пробела, введённые пользователем, такую проверку пройдут.
3. Сокращение пробелов перед проверкой. Если строку потом всё равно надо записать без пробелов по краям, удобно сделать это сразу:
ИНН = СокрЛП(Объект.ИНН);
Если ИНН = "" Тогда
Сообщить("Не указан ИНН");
ИначеЕсли СтрДлина(ИНН) <> 10 И СтрДлина(ИНН) <> 12 Тогда
Сообщить("ИНН должен содержать 10 или 12 цифр");
КонецЕсли;
| Способ | Пробелы считаются пустотой | Когда брать |
|---|---|---|
ПустаяСтрока(Стр) | да | обычная проверка «пользователь что-то ввёл» |
Стр = "" | нет | нужна точная проверка, пробел — допустимое значение |
СокрЛП(Стр) = "" | да | строку дальше нужно очищать и проверять по длине |
ЗначениеЗаполнено(Стр) | см. ниже | тип поля заранее неизвестен |
ПустаяСтрока() рассчитана на строки. Если у реквизита составной тип и в нём может лежать ссылка, сначала проверьте тип через ТипЗнч() или используйте ЗначениеЗаполнено().
Если важно отсечь строку из пробелов, а поле точно строковое, надёжнее всего ЗначениеЗаполнено(СокрЛП(Стр)) или ПустаяСтрока(Стр). Так результат не зависит от тонкостей поведения функции на пробелах.
Пустая ссылка, ноль и пустая дата
Ссылки на справочники, документы и перечисления
У любой ссылки есть метод Пустая():
Если Объект.Контрагент.Пустая() Тогда
Сообщить("Не выбран контрагент");
КонецЕсли;
Второй вариант — сравнить с пустой ссылкой нужного типа:
Если Объект.Контрагент = Справочники.Контрагенты.ПустаяСсылка() Тогда
// контрагент не выбран
КонецЕсли;
Оба способа работают, но у сравнения есть минус: при смене типа реквизита код придётся править. Метод Пустая() от типа не зависит, но вызывать его можно только у ссылки. Если в реквизите составного типа лежит Неопределено, вызов упадёт с ошибкой «Метод объекта не обнаружен
(Пустая)».
Битая ссылка
Отдельный случай — ссылка, которая не пуста, но указывает на удалённый объект. В форме такое значение показывается как <Объект не найден>, а Пустая() и ЗначениеЗаполнено() вернут для него «заполнено». Проверить, существует ли объект, можно запросом к таблице этого объекта по ссылке. В конфигурациях на БСП для этого есть готовая функция ОбщегоНазначения.СсылкаСуществует(Ссылка).
Числа
Пустое число — ноль. Проверка очевидна: Если Объект.Количество = 0 Тогда. Но подумайте о смысле: ноль бывает законным значением. Нулевая ставка или нулевая цена в акции — не ошибка ввода. Если ноль допустим, не делайте поле обязательным, иначе пользователь не сможет записать документ.
Отрицательные значения пустыми не считаются. Если количество не может быть меньше нуля, проверяйте <= 0, а не равенство нулю.
Даты
Пустая дата — '00010101', то есть 01.01.0001 00:00:00. Варианты проверки:
Если Объект.ДатаДоговора = '00010101' Тогда ...
Если Объект.ДатаДоговора = Дата(1, 1, 1) Тогда ...
Если Не ЗначениеЗаполнено(Объект.ДатаДоговора) Тогда ...
Последний вариант читается лучше всего и не требует помнить литерал пустой даты.
Функция ЗначениеЗаполнено: универсальная проверка
ЗначениеЗаполнено(Значение) проверяет, отличается ли значение от значения по умолчанию своего типа. Возвращает Истина, если поле заполнено, и Ложь, если нет. Функция доступна и на сервере, и на клиенте.
Она считает незаполненными:
- 📌
НеопределеноиNull; - 📌 пустую ссылку любого типа;
- 📌 ноль;
- 📌 пустую строку;
- 📌 пустую дату
'00010101'.
Главный плюс — не нужно знать тип поля. Для реквизита составного типа это вообще единственная короткая проверка без ошибок: она одинаково обработает и Неопределено, и пустую ссылку, и пустую строку.
Если Не ЗначениеЗаполнено(Объект.Субконто1) Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Не заполнено субконто";
Сообщение.Поле = "Объект.Субконто1";
Сообщение.Сообщить();
КонецЕсли;
Свойство Поле подсвечивает реквизит на форме, и пользователь сразу видит, куда смотреть.
Когда ЗначениеЗаполнено не подходит
- ❌ Булево. Для флага «не заполнено» и «Ложь» — одно и то же значение по умолчанию. Проверяйте флаг напрямую:
Если Объект.Оплачено Тогда. - ❌ Число, где ноль допустим. Функция скажет «не заполнено» про законный ноль.
- ❌ Коллекции. Для массива, таблицы значений или табличной части проверяйте количество строк явно:
Если Объект.Товары.Количество() = 0 Тогда. Так код однозначен для любого читателя. - ❌ Битая ссылка. Как сказано выше, удалённый объект функция считает заполненным.
Проверка заполнения без кода
Для обязательных реквизитов код иногда не нужен вовсе. В конфигураторе у реквизита есть свойство «Проверка заполнения» со значением «Выдавать ошибку». Тогда платформа сама не даст записать объект с пустым полем и покажет сообщение.
Если обязательность зависит от условий, используйте обработчик ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты) в модуле объекта. В нём можно убрать реквизит из массива ПроверяемыеРеквизиты или добавить в него новый. Например, поле «Договор» обязательно только для одного вида операции. Вызвать ту же проверку из кода можно методом объекта ПроверитьЗаполнение().
Если вносите такие правки в типовую конфигурацию, делайте их в расширении. Тогда обновление не затрёт изменения, а снять поддержку с конфигурации не придётся.
Неопределено и NULL: значение без типа и отсутствие данных
Неопределено во встроенном языке
Неопределено встречается в трёх типичных местах:
- реквизит составного типа, в котором ничего не выбрано;
- результат функции, которой нечего вернуть, например
Массив.Найти()без совпадений; - значение переменной, объявленной через
Перем, до первого присваивания.
Проверка:
Индекс = СписокКодов.Найти("0042");
Если Индекс = Неопределено Тогда
Сообщить("Код не найден");
КонецЕсли;
То же через тип: Если ТипЗнч(Значение) = Тип("Неопределено") Тогда. Вариант с ТипЗнч удобен, когда в одной ветке разбираете сразу несколько типов составного реквизита.
Для структуры не обращайтесь к ключу напрямую, если не уверены, что он есть. Сначала метод Свойство():
Параметры = Новый Структура("Склад", Неопределено);
Склад = Неопределено;
Если Параметры.Свойство("Склад", Склад) И ЗначениеЗаполнено(Склад) Тогда
// ключ есть и значение заполнено
КонецЕсли;
Обращение Параметры.Склад к несуществующему ключу вызовет ошибку, а Свойство() просто вернёт Ложь.
NULL в запросе
Null появляется в результате запроса, когда поля нет: левое соединение не нашло пары, у реквизита составного типа выбран другой тип, у элемента-группы справочника нет реквизита, который есть только у элементов.
В тексте запроса Поле = NULL не работает
. Нужна конструкция ЕСТЬ NULL:
ВЫБРАТЬ
Номенклатура.Ссылка КАК Номенклатура,
ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток
ИЗ
Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки
ПО Номенклатура.Ссылка = Остатки.Номенклатура
ГДЕ
Остатки.Номенклатура ЕСТЬ NULL
Здесь две разные вещи:
ЕСТЬ NULLв условии отбирает товары, по которым в остатках нет ни одной записи;- функция
ЕСТЬNULL(Поле, 0)подменяетNullнулём, чтобы дальше в коде не возиться с проверками.
Если Null из запроса попал в арифметику во встроенном языке, получите ошибку преобразования типа. Безопаснее всего убирать Null ещё в запросе через ЕСТЬNULL.
Во встроенном языке Null проверяется обычным сравнением: Если Выборка.Остаток = Null Тогда. Либо через ЗначениеЗаполнено(), которая считает Null незаполненным.
Пустые значения в условиях запроса
| Что проверяем | Как писать в запросе |
|---|---|
| Пустая ссылка | Док.Контрагент = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка) |
| Пустое перечисление | Дог.Вид = ЗНАЧЕНИЕ(Перечисление.ВидыДоговоров.ПустаяСсылка) |
| Пустая дата | Док.ДатаОплаты = ДАТАВРЕМЯ(1, 1, 1) |
| Пустая строка | Спр.Комментарий = "" |
| Не выбрано в составном типе | Док.Субконто = НЕОПРЕДЕЛЕНО |
| Нет данных | Поле ЕСТЬ NULL |
Для строк неограниченной длины прямое сравнение в условии не работает. Обрежьте поле до фиксированной длины: ПОДСТРОКА(Спр.Комментарий, 1, 1) = "" или ВЫРАЗИТЬ(Спр.Комментарий КАК СТРОКА(1)) = "".
Частые ошибки при проверке пустого поля
Вызов Пустая() у составного реквизита. Пока в реквизите Неопределено, метода у него нет. Код работает на заполненных документах и падает на новом. Лечится заменой на ЗначениеЗаполнено() или предварительной проверкой типа.
Сравнение ссылки со строкой. Если Объект.Склад = "" Тогда ошибки не выдаст, но всегда вернёт Ложь: ссылка никогда не равна строке. Проверка молча не срабатывает, а документ записывается с пустым складом.
Логическое выражение из ссылки. Если Не Объект.Контрагент Тогда в 1С не работает: ссылка не приводится к булеву типу, будет ошибка выполнения. Такую запись переносят из других языков по привычке.
Null вместо нуля в итоге. Сумма из левого соединения пришла как Null, её сложили с числом — ошибка. Или итог по колонке посчитался неверно. Ставьте ЕСТЬNULL на каждое поле справа от левого соединения, которое участвует в расчётах.
Обращение через точку к пустой ссылке. Объект.Договор.Владелец при пустом договоре не упадёт, а вернёт пустое значение. Ошибки нет, но код может принять решение на пустых данных. Сначала проверьте сам договор, потом его реквизиты. Заодно это экономит лишнее обращение к базе.
Проверка на клиенте реквизитов ссылки. В управляемой форме на клиенте Объект.Контрагент.ИНН недоступен: обращение через точку к реквизитам ссылки на клиенте не работает. Проверку реквизитов ссылки выносите в серверную процедуру или в ОбработкуПроверкиЗаполнения.
Какой способ выбрать: шпаргалка
| Ситуация | Способ |
|---|---|
| Тип поля известен, нужна читаемость | ЗначениеЗаполнено() |
| Строка, пробелы — тоже пусто | ПустаяСтрока() |
| Ссылка одного типа | Ссылка.Пустая() |
| Составной тип | ЗначениеЗаполнено() или ТипЗнч() |
| Результат поиска, необязательный параметр | = Неопределено |
| Поле в запросе после левого соединения | ЕСТЬ NULL / ЕСТЬNULL() |
| Табличная часть, массив | .Количество() = 0 |
| Обязательный реквизит без условий | свойство «Проверка заполнения» |
Частые вопросы о проверке пустых значений
Чем ЗначениеЗаполнено отличается от ПустаяСтрока?
Как проверить, что табличная часть документа пустая?
Если Объект.Товары.Количество() = 0 Тогда. Чтобы сделать табличную часть обязательной без кода, у неё в конфигураторе тоже есть свойство «Проверка заполнения».Почему Null и Неопределено — не одно и то же?
Null = Неопределено даёт Ложь.