Как в 1С отличить введенную дату 01.01 от пустого значения в поле ввода?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В разработке на платформе 1С:Предприятие 8.3 часто возникают задачи, связанные с нестандартным отображением данных. Одной из таких проблем является работа с полями ввода типа Дата, для которых установлен формат «ДФ=dd.MM». В этом случае год скрыт от пользователя, и система по умолчанию подставляет первый год нашей эры (0001 год). В результате возникает критическая неоднозначность: пустое поле (которое в 1С всегда равно 01.01.0001) и поле, в которое пользователь осознанно ввел «01.01», для системы выглядят абсолютно одинаково.

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

Причина проблемы: Особенности типа Дата

Проанализируем ситуацию: тип данных Дата в 1С всегда содержит год, месяц, день, час, минуту и секунду. Если мы используем формат ДФ=dd.MM, мы лишь «маскируем» год в интерфейсе. Когда поле ввода очищается, его значение становится равным '00010101000000'. Однако, если пользователь вводит «01.01», система, не видя года, также может интерпретировать это как 1-й год, что приводит к совпадению значений. Стандартная логика 1С считает дату 01.01.0001 «пустой», поэтому обычная проверка на заполненность возвращает Ложь в обоих случаях.

Способ 1. Анализ свойства ТекстРедактирования

Самый эффективный метод решения проблемы — «перехватить» тот текст, который пользователь фактически набрал в поле, прежде чем платформа преобразует его в объект типа Дата. Для этого мы будем использовать свойство элемента формы ТекстРедактирования.

Рассмотрим по шагам, как это реализовать:

  1. Создадим на форме реквизит (например, ДатаВведенаПользователем с типом Булево).
  2. Для поля ввода создадим обработчик события ОкончаниеВводаТекста или ПриИзменении.
  3. В обработчике проверим содержимое текста, который находится в поле в момент фокуса.

Пример кода для реализации этой логики:


&НаКлиенте
Процедура ИмяПоляДатыОкончаниеВводаТекста(Элемент, Текст, ДанныеВыбора, ПараметрыПолученияДанных, СтандартнаяОбработка)
    
    // Получаем то, что реально написано в поле ввода
    ВведенныйТекст = Элемент.ТекстРедактирования;
    
    // Если текст содержит цифры (например, "01.01"), значит поле не пустое
    Если СтрНайти(ВведенныйТекст, "0") > 0 Или СтрНайти(ВведенныйТекст, "1") > 0 Тогда 
        // Здесь можно установить флаг или выполнить логику
        Сообщить("Пользователь ввел данные: " + ВведенныйТекст);
    КонецЕсли;

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

Важный нюанс: свойство ТекстРедактирования доступно только тогда, когда элемент управления находится в фокусе. Поэтому проверку нужно делать именно в событиях, связанных с изменением текста или потерей фокуса.

Способ 2. Использование маски ввода

Для того чтобы сделать проверку текста более стабильной, мы рекомендуем использовать свойство Маска у элемента формы. Если установить маску 99.99, то поле ввода всегда будет содержать разделитель (точку). Это позволит нам легко отличить пустое значение от заполненного.

Проанализируем ситуацию: если поле пустое, ТекстРедактирования будет выглядеть как " . ". Если пользователь ввел «01.01», текст будет "01.01". Простая проверка на наличие цифр в строке даст нам точный ответ о заполнении реквизита.

Способ 3. Автоматическая подстановка текущего года

Если бизнес-логика позволяет, можно уйти от использования 0001 года. Мы можем программно подставлять текущий год, как только пользователь ввел день и месяц. Это сразу сделает дату «заполненной» с точки зрения системы (например, 01.01.2024).

Разберем пример кода в событии ПриИзменении:


&НаКлиенте
Процедура ИмяПоляДатыПриИзменении(Элемент)
    
    ТекущаяДатаПоля = Объект.ИмяРеквизита;
    
    // Если год равен 1, значит пользователь ввел только день/месяц или поле пустое
    Если Год(ТекущаяДатаПоля) = 1 Тогда
        
        // Проверяем через ТекстРедактирования, было ли что-то введено
        Если ЗначениеЗаполнено(Элемент.ТекстРедактирования) Тогда
            // Подставляем текущий год, чтобы дата стала "реальной"
            Объект.ИмяРеквизита = Дата(Год(ТекущаяДата()), Месяц(ТекущаяДатаПоля), День(ТекущаяДатаПоля));
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

Способ 4. Использование альтернативных типов данных

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

Подведем итоги

Мы выяснили, что стандартными средствами (функцией ЗначениеЗаполнено) отличить пустую дату от введенного значения 01.01 в сокращенном формате невозможно. Однако, комбинируя использование свойства ТекстРедактирования, установку Маски и обработку события ОкончаниеВводаТекста, можно добиться точного определения действий пользователя.

Рекомендация: Если для вашей задачи год действительно не важен, рассмотрите переход на строковое хранение данных. Если же тип Дата обязателен — используйте проверку текста в момент редактирования, как описано в первом способе.

← На главную