Private Sub TextBox1_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
If Mid(TextBox1.Value, 4, 2) > 12 Then
MsgBox "Invalid date, please re-enter", vbCritical
TextBox1.Value = vbNullString
TextBox1.SetFocus
Exit Sub
End If
StartDate = DateSerial(Year(Date), Month(Date), Day(Date))
TextBox1.Value = Format(TextBox1.Value, "dd.mm.yyyy")
StartDate = TextBox1.Value
End Sub
Этот код хорошо работает для меня и моих коллег, чтобы убедиться, что значение, введенное в текстовое поле, является датой. Однако у коллеги из другой страны (но тоже с форматом даты dd.mm.yyyy) странные результаты.
Например: Если он вводит 01.10.2017, текстовое поле автоматически форматирует дату в 20.03.4917.
Я подозреваю, что в этом случае введенное значение распознается не как дата, а как число, потому что 01102017 преобразуется в 20.03.4917 в Excel, если вы преобразуете его как дату.
У кого-нибудь есть предложение или предположение, как обойти эту проблему?
Спасибо и всего наилучшего


Вы можете разделить дату с помощью . на массив ArrInput, а затем использовать DateSerial, чтобы сделать ее реальной датой, которую вы можете отформатировать.
Dim ArrInput As Variant
ArrInput = Split(TextBox1.Value, ".")
'StartDate = DateSerial(Year(Date), Month(Date), Day(Date)) 'I see no use in this at all
TextBox1.Value = Format$(DateSerial(ArrInput(2), ArrInput(1), ArrInput(0)), "dd.mm.yyyy")
StartDate = TextBox1.Value
Проблема с Format(TextBox1.Value, "dd.mm.yyyy") заключается в том, что здесь вы позволяете Excel угадать, какой формат даты имеет строка в TextBox1.Value. Он автоматически преобразуется в число, которое затем снова преобразуется в строку.
Во избежание недоразумений с датами я рекомендую всегда использовать формат YYYY-MM-DD в соответствии с ИСО 8601. Это единственный формат даты, который удобочитаем и не может быть неправильно понят. Это также имеет преимущества при сортировке по датам, которые на самом деле являются строками.
Чтобы сделать вашу проверку еще более надежной, используйте что-то вроде:
Dim ArrInput As Variant
ArrInput = Split(TextBox1.Value, ".")
Dim ValidDate As Boolean
If UBound(ArrInput) = 2 Then 'make sure there are exactly two dots in the date
If ArrInput(1) > 0 And ArrInput(1) <= 12 And _ 'month <= 12
ArrInput(0) > 0 And ArrInput(0) <= 31 Then 'day <= 31
ValidDate = True
End If
Else
ValidDate = False
End If
If Not ValidDate Then
MsgBox "Invalid date, please re-enter in format dd.mm.yyyy", vbCritical
TextBox1.Value = vbNullString
TextBox1.SetFocus
Exit Sub
End If
TextBox1.Value = Format$(DateSerial(ArrInput(2), ArrInput(1), ArrInput(0)), "dd.mm.yyyy")
StartDate = TextBox1.Value
@Sven, чтобы предотвратить глупый ввод данных пользователем, вы можете сделать проверку даты более надежной. Я также предлагаю сообщить пользователю в msgbox, какой формат даты требуется. Смотрите мою правку.
Почему бы не иметь 3 поля ввода с соответствующим диапазоном чисел, указанным для каждого поля? по одному на год, месяц, дату и т. д.? Избегает отсутствия точек или запятых и т. д., поскольку вы можете «поместить» их или объединить их вместе.
@SolarMike Например, потому что вам нужно много кодировать, чтобы затем принять вставку даты ;( И добавление вставленной даты в поля будет такой же работой, как проверка одного поля.
@Pᴇʜ Хорошо, извините, просто идея - работало, когда я использовал исходный макроязык Excel, мы использовали 3 выпадающих списка ...
@SolarMike Да, конечно, это работает отлично, но вы должны отказаться от возможности вставлять дату, что может быть нокаутом. По крайней мере, для меня это всегда было нокаутом.
@Pᴇʜ Это работает! Спасибо, сэр! А также спасибо за предложения сделать все удобным для пользователя. Обязательно включу в свой инструмент
@ Pᴇʜ Похоже, его настройки даты - дд / мм / гггг. Я преобразовал код с помощью «/» вместо «.» так что это работает сейчас для него. Есть ли решение, в котором я могу определить более одного ArrInput для дат?
@Sven, проблема в том, что вы никогда не знаете, вставит ли кто-то dd/mm/yyyy или mm/dd/yyyy, если вы позволите это. Поэтому заставьте пользователя вводить дату в нужном вам формате dd.mm.yyyy или даже лучше, как я предложил YYYY-MM-DD. Если вы позволите ему поставить дату с косой чертой, вы можете получить неправильную дату.
Я верю, что ваш коллега вводит текстовую строку "01102017" без точек.
Возможно, вы захотите преобразовать такие записи в действительную дату:
' "01102017" => 01.10.2017 - 8 chars variant
' "011017" => 01.10.2017 - 6 chars variant
Это необходимо сделать до преобразования даты.
Добавьте журнал входного значения в свободный диапазон ячеек и
получить рабочую тетрадь обратно к вам:
...
Private Sub TextBox1_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
Range("Z1").value = "'" & TextBox1.Value
If Mid(TextBox1.Value, 4, 2) > 12 Then
...
Проверьте, используются ли только цифры:
Как проверить, содержит ли строка только числа?
и проверьте длину строки (вариант из 6 или 8 символов) и проверьте, находится ли часть года в допустимом диапазоне => попробуйте преобразовать в дату и предложите ее пользователю.
Это тоже была моя первая догадка, но он мне пообещал по телефону, что ввел значения точками
Вы можете создать своего рода журнал в самой рабочей книге и отправить вам рабочую книгу после того, как он введет значение:
Понятно. Спасибо тебе, друг. Это работает хорошо для меня. Я дам вам знать позже, если это сработает и для него. :)