Wednesday, December 1, 2004

More fun with dates in LotusScript

While the application we were working on won't have such values, we were very leery of treating such a date as a null date. We needed to find a way around this issue. And this is what we came up with -- a sub to copy date values from one field to another, preserving null values along the way.

Let me call out a few items in this code.

1       Function CopyDate(fromdoc As NotesDocument, fromfieldname As String, todoc As notesdocument, tofieldname As String, debug as variant, nlog As NotesLog)
                On Error Goto genericerrors
                'Mick Moignard Oct 2004: copy date field from one doc to another and preserve null date values
                'Also avoid any string conversions, so that there cannot be any problems with date format translations between DMY and MDY
5               'NotesDocument.CopyAllItems and NotesDocument.CopyToDatabase preserve items as is.

                If fromdoc.HasItem(fromfieldname) Then
                        Dim dt As notesitem
                        Set dt = fromdoc.GetFirstItem(fromfieldname)
10                      If dt.Text = "" Then 'genuinely null date field, or a text field with no value
                                Dim ndt As New NotesDateTime(Today)
                                Call ndt.setanydate
                                Call ndt.setanytime
                                Call todoc.ReplaceItemValue(tofieldname, ndt)
15                      Else
                                Call todoc.ReplaceItemValue(tofieldname, dt)
                        End If
                Else
                        If debug Then Call nlog.LogError(Err,"CopyDate - From document does not have field specified. " & _ "
20                      Fieldname = " & fromfieldname & ", Doc = " & fromdoc.UniversalID)
                End If

                Exit Function  'skip the error block
        genericerrors:
25              Call nlog.LogError(Err,"CopyDate - " & Error$ & " - " & Cstr(Erl)& ", Doc = " & fromdoc.UniversalID)
        End Function

Lines 1, 19, and 25 show how we've managed debugging and error reporting in the whole of the code. We use a NotesLog to report activity and errors, and can turn on and off debugging reporting by use of the debug variant, which is also passed to all subs and functions in the application.

Lines 2 and 24/25 show how we report errors in every sub and function. It's very important in an application of any size to ensure that you have decent error trapping and reporting. 'Script makes this pretty easy, so there really is no excuse.

However, none of these are the problem we're trying to solve. That starts in line 1, where we pass in the name of the field to be copied, the document that contains the field, and the field name and document to be copied to.

The work starts in line 7 with some defensive code that checks to ensure the field we're to work on actually exists in the document passed. If so, we get it into a NotesItem. In line 10, we look to see if that NotesItem has a null value, and we do that by examining its text value, looking for "".

If it's null, we then create a new datetime field and set it to an all-null value in lines 12 and 13, with NotesDateTime.SetAnyDate and SetAnyTime, and write the results back to the new field in the destination document in line 14. Line 16 merely copies the non-null date/time to the new document.

And with this, our problems with rogue dates of 31/12/1899 disappeared. Whew.