
Submission to VB Tech Journal

Title:    Validating dates in Visual Basic

By:       Jose Gonzalez
          12645 Heming Lane, Bowie, MD 20716-1118
          telephone:  301-805-9469
          email:  72271.474@compuserve.com

Attached are the following files:
                              
    VALDATE.DOC               This document formatted as Word for
                              Windows 6.0c
                              
    VALDATE.TXT               This document formatted as ASCII.
                              
    VALDATE.BMP               Screen capture formatted as Windows
                              BMP.
                              
    PROJECT1.MAK, FORM1.FRM,  Visual Basic files.
    MODULE1.BAS, VALDATE.MDB

*** BEGIN SUBMISSION ***

Microsoft Access lets you type in date/time values in any common
date/time format.  For example, the following are equivalent entries
in a date field:  "1 Jan. 95", "1/1/95", and "January 1, 1995". After
validation, Access displays the date using the setting stored in the
International section of Windows Control Panel.  The date entry
flexibility is also available in Microsoft Visual Basic for Windows
(VB) because VB uses the same database engine as Access;  Microsoft
calls the database engine Jet.

Jet issues a trappable error if an end user types in an invalid date
format;  for example, 30 February.  But validation occurs only when
the record is saved, not immediately after you type in the date
field.  In the following figure the date field is the second of three
input fields.

FIGURE 1 IS IN ATTACHED FILE VALDATE.BMP

If a user enters an invalid date Jet traps it after the user
completes the third field. The user would then have to back track to
the date field and correct the entry.  For this reason it is good
programming practice to inform your user about an invalid error
immediately after entry.  A good place to test for invalid entries is
in a controls LostFocus event.  There we can test for errors and
provide immediate feedback.

The flexibility that permits our end users to enter dates in various
formats makes programming error traps for dates a complicated task,
unless you ask Jet to give you a hand.  I wrote a short function
called ffnValidTimeDate that tests date entries;  if the entry is
valid the function returns True.  My programs calls function
ffnValidTimeDate from the date field's LostFocus event.  If
ffnValidTimeDate returns False the LostFocus resets the focus back to
the text control so the user can correct the entry.

SEE LISTING 1 BELOW

ffnValidTimeDate uses the record set of the data control associated
with the text control, and the field edited by the text control, to
test the date entry.  The actual check is accomplished by creating a
temporary record and setting the date to the value entered by the
program user.  If the program detects an error the function displays
a message and exits with a False value.  Adding a temporary record to
the database may move the database record pointer;  most times you
should try to avoid this while you are editing a record.
ffnValidTimeDate avoids moving the record pointer by cloning the
recordset. The Clone method duplicates a given recordset but
maintains a separate record pointer.  This allows you to add and
delete records from the database without disturbing the record
pointer in the original dynaset.  There is one drawback - the Clone
method is only available in the Professional Edition of Visual Basic.

SEE LISTING 2 BELOW



 LISTING 1
Sub Text2_LostFocus ()

    Dim fIsDateValid As Integer
    Dim vInputDate As Variant
    Dim dynDataSetToTest As Dynaset
    Dim zFieldName As String

    vInputDate = Text2.Text

    ' the next line copies a data control record set into a dynaset
    Set dynDataSetToTest = Data1.Recordset

    zFieldName = Text2.DataField
    Const fSayWhyItFailed = True

    fIsDateValid = ffnValidTimeDate(vInputDate, dynDataSetToTest, zFieldName, fSayWhyItFailed)

    Set dynDataSetToTest = Nothing

    If fIsDateValid = False Then
        ' Go back to the field to get new date
        Text2.SetFocus
    Else
        ' Nothing to do!
    End If

End Sub



LISTING 2
Function ffnValidTimeDate (vTime2Check As Variant, dynDataSet As 
Dynaset, zFieldNameToCheck As String, fSayMessage As Integer) As
Integer
' Returns true if time value is valid.

    ' Data expected:
    ' vTime2Check has time to validate
    ' dynDataSet is the dynaset we will use to validate the date
    ' zFieldNameToCheck is the name of the dynaset field we will use to test the date
    ' If fSayMessage is true display a message

    ' This function uses the database itself to validate the date.
    ' A clone of the incomming dynaset is used so that the record pointer of
    ' the original dynaset is not disturbed.

    Dim dynDynasetClone As Dynaset
    Dim zMsgText As String

    Set dynDynasetClone = dynDataSet.Clone()

    ' the function only returns false if an error is triggered.
    ffnValidTimeDate = True

    dynDynasetClone.AddNew
    On Error GoTo ErrorffnValidTimeDate

    ' Attempt to set the date field to the date supplied to the function.
    ' An error indicates that the date was not valid.
    dynDynasetClone.Fields(zFieldNameToCheck) = vTime2Check
    On Error GoTo 0

    ' a second addnew clears the new record buffer
    dynDynasetClone.AddNew

    ' because the close occurs without an update, no new records will be added.
    dynDynasetClone.Close

    Set dynDynasetClone = Nothing
    GoTo ExitffnValidTimeDate

ErrorffnValidTimeDate:

    ffnValidTimeDate = False
    If fSayMessage = True Then
        If Err = 13 Then
            ' Err 13 is a type mismatch error
            zMsgText = "The date you entered does not appear to be correct.  "
            zMsgText = zMsgText & "Please try again."
        Else
            ' Always a good idea to provide for the unknown
            zMsgText = "An unexpected error occur while validating the date.  "
            zMsgText = zMsgText & "Please try again."
        End If
    End If
    MsgBox zMsgText
    Resume Next

ExitffnValidTimeDate:

End Function


