В разработке на платформе 1С:Предприятие 8.3 часто возникают задачи, связанные с нестандартным отображением данных. Одной из таких проблем является работа с полями ввода типа Дата, для которых установлен формат «ДФ=dd.MM». В этом случае год скрыт от пользователя, и система по умолчанию подставляет первый год нашей эры (0001 год). В результате возникает критическая неоднозначность: пустое поле (которое в 1С всегда равно 01.01.0001) и поле, в которое пользователь осознанно ввел «01.01», для системы выглядят абсолютно одинаково.
В данной статье мы разберем, почему стандартная функция ЗначениеЗаполнено() в этой ситуации не помогает, и проанализируем несколько надежных способов, как программно определить, вводил ли пользователь данные.
Проанализируем ситуацию: тип данных Дата в 1С всегда содержит год, месяц, день, час, минуту и секунду. Если мы используем формат ДФ=dd.MM, мы лишь «маскируем» год в интерфейсе. Когда поле ввода очищается, его значение становится равным '00010101000000'. Однако, если пользователь вводит «01.01», система, не видя года, также может интерпретировать это как 1-й год, что приводит к совпадению значений. Стандартная логика 1С считает дату 01.01.0001 «пустой», поэтому обычная проверка на заполненность возвращает Ложь в обоих случаях.
Самый эффективный метод решения проблемы — «перехватить» тот текст, который пользователь фактически набрал в поле, прежде чем платформа преобразует его в объект типа Дата. Для этого мы будем использовать свойство элемента формы ТекстРедактирования.
Рассмотрим по шагам, как это реализовать:
ДатаВведенаПользователем с типом Булево).ОкончаниеВводаТекста или ПриИзменении.Пример кода для реализации этой логики:
&НаКлиенте
Процедура ИмяПоляДатыОкончаниеВводаТекста(Элемент, Текст, ДанныеВыбора, ПараметрыПолученияДанных, СтандартнаяОбработка)
// Получаем то, что реально написано в поле ввода
ВведенныйТекст = Элемент.ТекстРедактирования;
// Если текст содержит цифры (например, "01.01"), значит поле не пустое
Если СтрНайти(ВведенныйТекст, "0") > 0 Или СтрНайти(ВведенныйТекст, "1") > 0 Тогда
// Здесь можно установить флаг или выполнить логику
Сообщить("Пользователь ввел данные: " + ВведенныйТекст);
КонецЕсли;
КонецПроцедуры
Важный нюанс: свойство ТекстРедактирования доступно только тогда, когда элемент управления находится в фокусе. Поэтому проверку нужно делать именно в событиях, связанных с изменением текста или потерей фокуса.
Для того чтобы сделать проверку текста более стабильной, мы рекомендуем использовать свойство Маска у элемента формы. Если установить маску 99.99, то поле ввода всегда будет содержать разделитель (точку). Это позволит нам легко отличить пустое значение от заполненного.
Проанализируем ситуацию: если поле пустое, ТекстРедактирования будет выглядеть как " . ". Если пользователь ввел «01.01», текст будет "01.01". Простая проверка на наличие цифр в строке даст нам точный ответ о заполнении реквизита.
Если бизнес-логика позволяет, можно уйти от использования 0001 года. Мы можем программно подставлять текущий год, как только пользователь ввел день и месяц. Это сразу сделает дату «заполненной» с точки зрения системы (например, 01.01.2024).
Разберем пример кода в событии ПриИзменении:
&НаКлиенте
Процедура ИмяПоляДатыПриИзменении(Элемент)
ТекущаяДатаПоля = Объект.ИмяРеквизита;
// Если год равен 1, значит пользователь ввел только день/месяц или поле пустое
Если Год(ТекущаяДатаПоля) = 1 Тогда
// Проверяем через ТекстРедактирования, было ли что-то введено
Если ЗначениеЗаполнено(Элемент.ТекстРедактирования) Тогда
// Подставляем текущий год, чтобы дата стала "реальной"
Объект.ИмяРеквизита = Дата(Год(ТекущаяДата()), Месяц(ТекущаяДатаПоля), День(ТекущаяДатаПоля));
КонецЕсли;
КонецЕсли;
КонецПроцедуры
В некоторых случаях (например, при хранении дат дней рождений без года или праздников) использование типа Дата является избыточным и создает лишние сложности. Разберем альтернативные варианты хранения данных:
Строка(5). Формат «01.01» отлично сортируется и позволяет однозначно определить пустое значение (пустая строка).Мы выяснили, что стандартными средствами (функцией ЗначениеЗаполнено) отличить пустую дату от введенного значения 01.01 в сокращенном формате невозможно. Однако, комбинируя использование свойства ТекстРедактирования, установку Маски и обработку события ОкончаниеВводаТекста, можно добиться точного определения действий пользователя.
Рекомендация: Если для вашей задачи год действительно не важен, рассмотрите переход на строковое хранение данных. Если же тип Дата обязателен — используйте проверку текста в момент редактирования, как описано в первом способе.