I really need all of the rules as to how you will know if the date is inserted in the correct format and what range of dates is valid. Is the method of using a list of dates not acceptable because that is the best way I know of ensuring a valid date entry.
My reason for using Min and Max date is that ensures that it is a date within the correct ball park and if number format is used then it should convert to a date within that range.
With a TextBox, the entry is always in text format and to use as a date, it needs to be converted from text to date format. With Text, it is fairly easy to test the entry with VBA code. Possibly you can format the range as Text so that the date is entered
as text.
Then use similar code to what you have used for the TextBox to validate the entry (or my example below)
If valid then use the VBA to then reformat the individual cell to mm-dd-yyyy.
Insert the date as a date.
The problem with the above method is that the cell is then in date format and the validation code will not work if the entry is changed again. However, see my comments where you can simply leave the entry in text format then to use as a date, convert from
text to date with the DateValue function anywhere that it is required.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim arrSplit As Variant
Dim bInvalid As Boolean
Dim dteValid As Date
Dim strMsge As String
Dim lngMaxDay As Long
On Error GoTo InvalidMsge 'To ensure that EnableEvents is turned on again.
If Target.Column <> 1 Then Exit Sub
If Target.Cells.Count <> 1 Then Exit Sub
If Target.Value = "" Then Exit Sub
Application.EnableEvents = False
If Len(Target.Value) <> 10 Then 'Wrong number of characters
bInvalid = True
strMsge = "Invalid number of characters in date." & vbCrLf & _
"Please re-enter in mm-dd-yyyy format."
GoTo InvalidMsge:
End If
arrSplit = Split(Target, "-")
If UBound(arrSplit) <> 2 Then 'Not equal to 2 then hyphens not used
bInvalid = True
strMsge = "Invalid separators in date." & vbCrLf & _
"Please re-enter in mm-dd-yyyy format."
GoTo InvalidMsge:
End If
If arrSplit(0) < 1 Or arrSplit(0) > 12 Then
bInvalid = True
strMsge = "Error! Invalid Month." & vbCrLf & _
"Please re-enter in mm-dd-yyyy format."
GoTo InvalidMsge
End If
'If Month is valid then could test the day for the specific month
Select Case arrSplit(0)
Case 9, 4, 6, 11
lngMaxDay = 30
Case 1, 3, 5, 7, 8, 10, 12
lngMaxDay = 31
Case 2
'Centaury years that are not leap years not included because unlikely to be a problem
If arrSplit(2) Mod 4 = 0 Then
lngMaxDay = 29
Else
lngMaxDay = 28
End If
End Select
If arrSplit(1) > 0 And arrSplit(1) <= lngMaxDay Then
dteValid = DateSerial(arrSplit(2), arrSplit(0), arrSplit(1))
Else
bInvalid = True
strMsge = "Error! Incorrect days for month." & vbCrLf & _
"Please re-enter in mm-dd-yyyy format."
GoTo InvalidMsge
End If
Target.NumberFormat = "mm-dd-yyyy" 'Delete or comment out if using following Alternative method
Target.Value = dteValid 'Delete or comment out if using following Alternative method
'Alternative code to above is to not re-format the cell and
'not write the date back to the cell and leave the entry in text format.
InvalidMsge:
If bInvalid Then
MsgBox strMsge
Target.Select
End If
If Err.Number <> 0 Then
MsgBox "An error occurred in Module " & Me.Name & " Private Sub Worksheet_Change"
End If
Application.EnableEvents = True
End Sub