Пустая дата в 1С: как распознать её в форме, коде, запросе и отчёте

· 9 мин

Содержание

В коде 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. Откройте журнал нужных документов.
  2. В меню Ещё выберите настройку списка.
  3. На вкладке «Отбор» добавьте поле с датой, например «Дата оплаты».
  4. В колонке вида сравнения выберите «Не заполнено».
  5. Нажмите «Завершить редактирование».

Список покажет только документы с пустой датой. Обратный вариант — «Заполнено» — пригодится, когда нужно найти, где дату уже поставили.

В отчёте на системе компоновки

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

Если в списке нет нужного поля, оно может быть не выведено в форму списка. Тогда используйте универсальный отчёт или обработку группового изменения реквизитов — там доступны все реквизиты объекта.

Проверка заполненности даты в коде 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; ДП='не указана'");

Ошибки при проведении из-за пустой даты

Чаще всего пустую дату обнаруживают, когда документ не проводится. Платформа выводит сообщение вида Поле "Дата оплаты" не заполнено и подсвечивает поле.

Откуда берётся проверка

  1. В Конфигураторе у реквизита свойство «Проверка заполнения» = «Выдавать ошибку».
  2. Для документов платформа выполняет эту проверку при проведении, для справочников — при записи.
  3. В модуле объекта обработчик ОбработкаПроверкиЗаполнения может добавить или убрать реквизиты из проверки.

Условная обязательность даты

Иногда дата обязательна только в одном сценарии. Её добавляют в проверяемые реквизиты по условию и тут же проверяют логику дат:

Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)

	Если ОплатаВРассрочку Тогда
		ПроверяемыеРеквизиты.Добавить("ДатаОплаты");
	КонецЕсли;

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

КонецПроцедуры

ОплатаВРассрочку и ДатаОплаты здесь — имена реквизитов-примеров, подставьте свои. Сообщение с привязкой к полю подсветит именно его, а не просто выведет текст внизу формы.

Диагностика: выберите симптом

Как массово найти и заполнить пустые даты

Когда пустых дат десятки или сотни, вручную их не исправить.

Без кода: групповое изменение реквизитов

В конфигурациях на БСП, включая Бухгалтерию 3.0, есть обработка «Групповое изменение реквизитов». В БП 3.0 её путь — Администрирование → Обслуживание → Корректировка данных → Групповое изменение реквизитов.

  1. Выберите вид объектов, например нужный документ.
  2. В отборе укажите реквизит даты и вид сравнения «Не заполнено».
  3. В таблице реквизитов задайте новое значение даты.
  4. Нажмите «Изменить реквизиты».

Обработка ставит одно значение всем отобранным объектам. Если дата у каждого документа своя, нужен код.

С кодом: запрос и запись объектов

Пример заполняет дату оплаты датой документа плюс 10 дней. Код выполняется на сервере — во внешней обработке или серверной процедуре.

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
|	Док.Ссылка КАК Ссылка
|ИЗ
|	Документ.МойДокумент КАК Док
|ГДЕ
|	Док.ДатаОплаты = ДАТАВРЕМЯ(1, 1, 1)
|	И НЕ Док.ПометкаУдаления";

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
	ДокОбъект = Выборка.Ссылка.ПолучитьОбъект();
	ДокОбъект.ДатаОплаты = НачалоДня(ДокОбъект.Дата) + 10 * 86400;
	ДокОбъект.ОбменДанными.Загрузка = Истина;
	Попытка
		ДокОбъект.Записать();
	Исключение
		Сообщить("Не записан: " + Строка(Выборка.Ссылка));
	КонецПопытки;
КонецЦикла;

ОбменДанными.Загрузка = Истина отключает обработчики записи и проверки — движения документа не меняются. Если от новой даты зависят движения, документы нужно перепровести отдельно.

Массовая запись меняет данные в рабочей базе. Перед запуском сделайте резервную копию и сначала прогоните обработку на копии базы. Если база используется в обмене, изменённые документы уйдут в следующий пакет.

Как не допустить пустых дат в будущем

  • ✅ Включите «Проверку заполнения» у реквизита, если дата обязательна всегда.
  • ✅ Для условной обязательности используйте ОбработкаПроверкиЗаполнения.
  • ✅ Заполняйте дату по умолчанию в ОбработкаЗаполнения или ПриСозданииНаСервере, если есть разумное значение.
  • ✅ При загрузке из файлов проверяйте строку перед преобразованием, как в функции выше.

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

Чем пустая дата отличается от NULL?
Пустая дата — значение типа «Дата», его можно хранить в реквизите. NULL бывает только в результате запроса, например при левом соединении без пары. ЗначениеЗаполнено считает пустыми оба.
Почему в отчёте вместо пустой даты выводится 01.01.0001?
Значит, дата форматируется без параметра пустого значения. Добавьте в форматную строку ДП= с нужным текстом или пробелом — тогда пустая дата выведется так, как задано.
Как проверить дату в каждой строке табличной части?
Обойдите строки циклом Для Каждого и проверяйте ЗначениеЗаполнено у поля строки. Для привязки сообщения к ячейке укажите путь вида Товары[0].ДатаПоставки, где номер — индекс строки с нуля.
Можно ли сделать дату обязательной только в форме, не трогая объект?
Да. Создайте проверку для реквизита формы или поля в обработчике ОбработкаПроверкиЗаполненияНаСервере модуля формы. Но при записи объекта из кода такая проверка не сработает.
Влияет ли пустая дата на сортировку?
Да. Пустая дата — самая ранняя, поэтому при сортировке по возрастанию такие записи окажутся в начале списка, а при сортировке по убыванию — в конце.