Пустая дата в 1С: как распознать её в форме, коде, запросе и отчёте
Содержание
В коде 1С заполненность даты проверяют функцией ЗначениеЗаполнено(Дата): она вернёт Ложь, если в переменной пустая дата '00010101000000', Неопределено или NULL. В запросе то же самое делают сравнением с ДАТАВРЕМЯ(1, 1, 1), а пользователь без программиста находит пустые даты отбором с видом сравнения «Не заполнено» в списке или отчёте.
Для пользователя и для программиста порядок разный, но важнее всего подвохи: поле «только время» со значением 00:00, составной тип, NULL в соединениях и сообщения при проведении документа. Механизмы общие для платформы 1С:Предприятие 8.3, поэтому подходят для Бухгалтерии, ЗУП, УТ и самописных конфигураций.
Что 1С считает пустой датой
У типа «Дата» нет отдельного значения «ничего». Пустая дата — это самая ранняя дата, которую умеет хранить платформа: 1 января 1 года, 00:00:00. Записать её можно тремя способами, и все они равны:
- 📅 литерал
'00010101'или полный'00010101000000'; - 🧮 конструктор
Дата(1, 1, 1); - 🔎 в языке запросов —
ДАТАВРЕМЯ(1, 1, 1).
Рабочий диапазон дат в 1С 8.3 — от 01.01.0001 до 31.12.3999. Всё, что раньше нижней границы, не существует, поэтому «самое начало» и служит признаком незаполненного поля.
Новый реквизит типа «Дата» в справочнике или документе по умолчанию получает именно пустое значение. Поэтому после добавления реквизита в рабочую базу у всех старых объектов он пустой — это не ошибка, а исходное состояние.
Как увидеть незаполненную дату без программиста
Пользователю не нужен код. Платформа показывает пустую дату как пустое поле, а в списках и отчётах есть готовый отбор.
В карточке документа или справочника
Пустое поле даты выглядит как пустая строка с маской . . или вовсе без цифр. Если реквизит обязательный, поле подчёркнуто красной пунктирной линией. Это автоотметка незаполненного — её включают в свойствах элемента формы.
В списке документов
- Откройте журнал нужных документов.
- В меню
Ещёвыберите настройку списка. - На вкладке «Отбор» добавьте поле с датой, например «Дата оплаты».
- В колонке вида сравнения выберите «Не заполнено».
- Нажмите «Завершить редактирование».
Список покажет только документы с пустой датой. Обратный вариант — «Заполнено» — пригодится, когда нужно найти, где дату уже поставили.
В отчёте на системе компоновки
Почти все отчёты в типовых конфигурациях построены на СКД. Откройте настройки отчёта, перейдите к отбору, добавьте поле с датой и выберите «Не заполнено». В самом отчёте пустая дата выводится пустой ячейкой.
Если в списке нет нужного поля, оно может быть не выведено в форму списка. Тогда используйте универсальный отчёт или обработку группового изменения реквизитов — там доступны все реквизиты объекта.
Проверка заполненности даты в коде 1С
Для программиста есть несколько равноценных по результату вариантов. Разница — в читаемости и в том, как они ведут себя со «странными» значениями.
Если Не ЗначениеЗаполнено(Объект.ДатаОплаты) Тогда
// дата не указана
КонецЕсли;
Если Объект.ДатаОплаты = Дата(1, 1, 1) Тогда
// то же самое, но только для типа Дата
КонецЕсли;
Если Объект.ДатаОплаты = '00010101' Тогда
// литерал, результат тот же
КонецЕсли;
| Способ | Что ловит | Когда выбирать |
|---|---|---|
ЗначениеЗаполнено(Д) | пустую дату, Неопределено, NULL | почти всегда, особенно для составного типа |
Д = Дата(1, 1, 1) | только пустую дату | когда тип точно «Дата» и нужно явно показать намерение |
Д = '00010101' | только пустую дату | короче, но хуже читается новичками |
ТипЗнч(Д) = Тип("Дата") | тип, а не заполненность | перед сравнением, если значение пришло извне |
ЗначениеЗаполнено работает и на клиенте, и на сервере, поэтому её можно вызывать в обработчике ПриИзменении поля формы без серверного вызова.
Проверка диапазона дат
Часто важна не только заполненность, но и порядок дат. Сначала проверяйте заполненность, потом сравнение. Иначе пустая дата всегда окажется «раньше» любой реальной.
Если ЗначениеЗаполнено(ДатаНачала) И ЗначениеЗаполнено(ДатаОкончания)
И ДатаОкончания < ДатаНачала Тогда
ВызватьИсключение "Дата окончания раньше даты начала";
КонецЕсли;
Дата пришла строкой
При загрузке из Excel или файла обмена дата приходит строкой. Функция Дата() понимает строку в формате ГГГГММДДччммсс и бросает исключение, если строка не подходит. Пустую строку проверяйте заранее, а преобразование оборачивайте в Попытка:
Функция СтрокаВДату(Знач Стр)
Стр = СокрЛП(Стр);
Если ПустаяСтрока(Стр) Тогда
Возврат Дата(1, 1, 1);
КонецЕсли;
Попытка
Возврат Дата(Стр);
Исключение
Возврат Дата(1, 1, 1);
КонецПопытки;
КонецФункции
Так результат всегда имеет тип «Дата», и дальше работает обычная проверка ЗначениеЗаполнено.
Подвохи типа «Дата»: время, состав и составной тип
Большинство странных багов с пустыми датами связаны не с самой проверкой, а с тем, что лежит в реквизите.
Поле «только время» со значением 00:00
У реквизита типа «Дата» есть квалификатор «Состав даты»: Дата, Время или Дата и время. Поле «Время» хранит дату 01.01.0001 плюс время. Значит, время 00:00:00 технически совпадает с пустой датой.
Для реквизита с составом «Время» полночь неотличима от пустого значения. ЗначениеЗаполнено вернёт Ложь, обязательная проверка заполнения выдаст ошибку. Если полночь — допустимое значение (например, начало смены), заведите отдельный флаг «Время указано» или храните дату и время вместе.
Время в поле «только дата»
Обратная ситуация: реквизит с составом «Дата» получил значение с временем из кода. Форма время не покажет, но сравнение Д1 = Д2 даст Ложь. Перед сравнением дат по дню приводите обе к НачалоДня().
Составной тип
Если реквизит может хранить и дату, и, скажем, строку, то в незаполненном виде в нём лежит Неопределено, а не пустая дата. Сравнение с Дата(1, 1, 1) здесь не сработает — используйте ЗначениеЗаполнено.
Пустая дата при прямом доступе к СУБД
База на MS SQL Server обычно создаётся со смещением дат 2000. Тогда пустая дата 01.01.0001 лежит в таблице СУБД как 01.01.2001. Внутри 1С этого не видно, но при выгрузке данных SQL-запросом мимо платформы пустые даты превратятся в «2001 год». Учитывайте это при выгрузках в BI-системы.
Пустая дата в запросах, отборах и СКД
Условие в запросе
ВЫБРАТЬ
Док.Ссылка КАК Ссылка
ИЗ
Документ.МойДокумент КАК Док
ГДЕ
Док.ДатаОплаты = ДАТАВРЕМЯ(1, 1, 1)
И НЕ Док.ПометкаУдаления
Вместо литерала можно передать параметр: Запрос.УстановитьПараметр("ПустаяДата", Дата(1, 1, 1)) и условие Док.ДатаОплаты = &ПустаяДата. Так проще переиспользовать запрос.
Когда вместо пустой даты приходит NULL
При левом соединении поле из правой таблицы для строк без пары равно NULL, а не пустой дате. Условие = ДАТАВРЕМЯ(1, 1, 1) такие строки пропустит. Надёжный вариант ловит оба случая:
ГДЕ
ЕСТЬNULL(Опл.ДатаОплаты, ДАТАВРЕМЯ(1, 1, 1)) = ДАТАВРЕМЯ(1, 1, 1)
Если нужен флаг, а не отбор, выведите его полем:
ВЫБОР
КОГДА ЕСТЬNULL(Опл.ДатаОплаты, ДАТАВРЕМЯ(1, 1, 1)) = ДАТАВРЕМЯ(1, 1, 1)
ТОГДА ЛОЖЬ
ИНАЧЕ ИСТИНА
КОНЕЦ КАК ДатаОплатыЗаполнена
Отбор в системе компоновки данных
В СКД отбор «Заполнено» и «Не заполнено» есть среди видов сравнения. Программно его добавляют так:
ЭлементОтбора = Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ДатаОплаты");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.НеЗаполнено;
ЭлементОтбора.Использование = Истина;
Тот же код подходит для отбора динамического списка: вместо Настройки.Отбор используйте Список.КомпоновщикНастроек.ФиксированныеНастройки.Отбор или пользовательский отбор списка.
Пустая дата в печатной форме и отчёте
Чтобы вместо пустоты выводить прочерк или текст, используйте параметр форматной строки ДП:
Текст = Формат(ДатаОплаты, "ДЛФ=D; ДП='не указана'");
Ошибки при проведении из-за пустой даты
Чаще всего пустую дату обнаруживают, когда документ не проводится. Платформа выводит сообщение вида Поле "Дата оплаты" не заполнено и подсвечивает поле.
Откуда берётся проверка
- В Конфигураторе у реквизита свойство «Проверка заполнения» = «Выдавать ошибку».
- Для документов платформа выполняет эту проверку при проведении, для справочников — при записи.
- В модуле объекта обработчик
ОбработкаПроверкиЗаполненияможет добавить или убрать реквизиты из проверки.
Условная обязательность даты
Иногда дата обязательна только в одном сценарии. Её добавляют в проверяемые реквизиты по условию и тут же проверяют логику дат:
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
Если ОплатаВРассрочку Тогда
ПроверяемыеРеквизиты.Добавить("ДатаОплаты");
КонецЕсли;
Если ЗначениеЗаполнено(ДатаОплаты) И ДатаОплаты < НачалоДня(Дата) Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Дата оплаты раньше даты документа";
Сообщение.Поле = "ДатаОплаты";
Сообщение.УстановитьДанные(ЭтотОбъект);
Сообщение.Сообщить();
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
ОплатаВРассрочку и ДатаОплаты здесь — имена реквизитов-примеров, подставьте свои. Сообщение с привязкой к полю подсветит именно его, а не просто выведет текст внизу формы.
Как массово найти и заполнить пустые даты
Когда пустых дат десятки или сотни, вручную их не исправить.
Без кода: групповое изменение реквизитов
В конфигурациях на БСП, включая Бухгалтерию 3.0, есть обработка «Групповое изменение реквизитов». В БП 3.0 её путь — Администрирование → Обслуживание → Корректировка данных → Групповое изменение реквизитов.
- Выберите вид объектов, например нужный документ.
- В отборе укажите реквизит даты и вид сравнения «Не заполнено».
- В таблице реквизитов задайте новое значение даты.
- Нажмите «Изменить реквизиты».
Обработка ставит одно значение всем отобранным объектам. Если дата у каждого документа своя, нужен код.
С кодом: запрос и запись объектов
Пример заполняет дату оплаты датой документа плюс 10 дней. Код выполняется на сервере — во внешней обработке или серверной процедуре.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Док.Ссылка КАК Ссылка
|ИЗ
| Документ.МойДокумент КАК Док
|ГДЕ
| Док.ДатаОплаты = ДАТАВРЕМЯ(1, 1, 1)
| И НЕ Док.ПометкаУдаления";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ДокОбъект = Выборка.Ссылка.ПолучитьОбъект();
ДокОбъект.ДатаОплаты = НачалоДня(ДокОбъект.Дата) + 10 * 86400;
ДокОбъект.ОбменДанными.Загрузка = Истина;
Попытка
ДокОбъект.Записать();
Исключение
Сообщить("Не записан: " + Строка(Выборка.Ссылка));
КонецПопытки;
КонецЦикла;
ОбменДанными.Загрузка = Истина отключает обработчики записи и проверки — движения документа не меняются. Если от новой даты зависят движения, документы нужно перепровести отдельно.
Массовая запись меняет данные в рабочей базе. Перед запуском сделайте резервную копию и сначала прогоните обработку на копии базы. Если база используется в обмене, изменённые документы уйдут в следующий пакет.
Как не допустить пустых дат в будущем
- ✅ Включите «Проверку заполнения» у реквизита, если дата обязательна всегда.
- ✅ Для условной обязательности используйте
ОбработкаПроверкиЗаполнения. - ✅ Заполняйте дату по умолчанию в
ОбработкаЗаполненияилиПриСозданииНаСервере, если есть разумное значение. - ✅ При загрузке из файлов проверяйте строку перед преобразованием, как в функции выше.
Частые вопросы
Чем пустая дата отличается от NULL?
NULL бывает только в результате запроса, например при левом соединении без пары. ЗначениеЗаполнено считает пустыми оба.Почему в отчёте вместо пустой даты выводится 01.01.0001?
ДП= с нужным текстом или пробелом — тогда пустая дата выведется так, как задано.Как проверить дату в каждой строке табличной части?
Для Каждого и проверяйте ЗначениеЗаполнено у поля строки. Для привязки сообщения к ячейке укажите путь вида Товары[0].ДатаПоставки, где номер — индекс строки с нуля.Можно ли сделать дату обязательной только в форме, не трогая объект?
ОбработкаПроверкиЗаполненияНаСервере модуля формы. Но при записи объекта из кода такая проверка не сработает.