CRMtimes.GIF (8509 bytes)

CRMtimesnav.GIF (22964 bytes)

 

commencerm_logo.gif (2110 bytes)

 

Forms Expert - Logging a History of Changes

bd04972_.wmf (20322 bytes)Have you ever wanted to be able to check back to verify when a change was made to you data and exactly what the change was? Maybe you need to see an old phone number, or find out who altered a price. With a little scripting and a new field in a form, its easy to log the history of changes in commence.

Category Modification

You can log changes in any category, and you can decide exactly what you want to record. In this example, we assume you want to track the date, time, user, original data and new data.

So the first task is to add a new field "History" to your category. As the amount of text to go into this field will be variable, you should make this field type large text.

VBscripting

Next you need to write some VBscript to capture the changes and write to the History field. If you are not already familiar with writing VBscript in Commence detail forms, you might want to review the basics in the Commence Users Guide, in Chapter 12, VBscripting.

To build a log of changes, we are going to use Form_OnEnterField and Form_OnLeaveField events. Here is the code to capture the changes:

Dim enterField, leaveField
Sub Form_OnEnterField(ByVal FldNme)
   '--- Used for history
   enterField = Form.Field(FldNme).Value
End Sub
Sub Form_OnLeaveField (ByVal FldNam)
   '--- Used for history
   Dim history, UserName
   UserName = GetMe("Name")
   leaveField = Form.Field(FldNam).Value
End Sub

Note that enterField and leaveField are defined as global variables, since these have to be accessed from both Sub Form_OnEnterField and Sub Form_OnLeaveField.

Also notice that we have not had to mention any field names at all! We are simply using the field name passed to the Sub - very convenient. But, have you spotted the problem? This works well for all the fields in the category, but does not work for connection fields - more on that later.

Also, GetMe() is a simple utility function that returns the user name defined under preferences.

So now we know the original value and the new value, all we have to do is compare and then update the history. Of course if we have made a change we will have to leave the field, so all this is done in Sub Form_OnLeaveField:

Sub Form_OnLeaveField (ByVal FldNam)
   '--- Used for history
   Dim history, UserName, crlf
   crlf = Chr(13) & Chr(10)
   UserName = GetMe("Name")
   leaveField = Form.Field(FldNam).Value
   If enterField <> leaveField Then
      If IsAdd <> TRUE Then
         'MsgBox("Enter Field = " & enterField & _
            ", Leave Field = " & leaveField)
         history = Form.Field("History").Value
         history = Date & " " & Time & ", " & _
            UserName & ", " & FldNam & ", " & _
            "Original Value: " & enterField & _
            ", New Value: " & leaveField & _
            crlf & history
         Form.Field("History").Value = history
      End If 'IsAdd
   End If
End Sub

If the original value is the same as the new value, then no changes were made and we are done. Likewise, if we are adding a new item, we are probably not interested in logging changes (every entry would be a change).

If we are editing and have made a change, we firstly capture the existing history. Then we add the details we want to track. Finally write the new history out to the history field.

And for completeness, here is the GetMe() function, which uses some simple api calls to get the user name:

Function GetMe(ByVal FieldName)
   '--- Function to return current user details
   '--- Commence Corporation
   Dim lDB, lCursor, lQRowSet, lIndex, lResult
   Set lDB = Application.Database
   Set lCursor = lDB.GetCursor(0, "user", 0)
   lResult = lCursor.SetFilter("[ViewFilter(1, F, _
      , Name, Equal to, ""(-Me-)"")]", 0)
   Set lQRowSet = lCursor.GetQueryRowSet(1, 0)
   lIndex = lQRowSet.GetColumnIndex(FieldName, 0)
   GetMe = lQRowSet.GetRowValue(0, lIndex, 0)
End Function 'GetMe

Tracking Changes to Connections

As mentioned above, this technique does not work for connections. This is because the syntax to get the data from a connection is different; in fact we need to specify the name of the connection and the connected field we are interested in. This is easily handled by explicitly checking each connection field.

So lets assume we wanted to track any changes in the name of the company a person works for. In Form_OnEnterField we just add the lines:

If FldNme = "is employed by Company" Then
   enterField = Form.Connection("is employed by", _
      "Company").Fieldvalue("Name")
End If

And in Form_OnLeaveField

If FldNam = "is employed by Company" Then
   leaveField = Form.Connection("is employed by", _
      "Company").Fieldvalue("Name")
End If 

This does assume there is only one connection. Multiple connections can be handled, but it requires more code and is getting a little complex for this discussion. Contact our consulting services if you need help with this...

Protecting the history

In a corporate situation, you might want to ensure that once the history is logged, staff can't go in and later make changes. This is easily achieved with the CantGoHere utility function.

Add the following to Sub Form_OnEnterField

If FieldName = "History" Then CantGoHere : Exit Sub

Then add the CantGoHere function.

Function CantGoHere
   '--- Check modification details are not changed.
   Dim mb
   mb=MsgBox("Warning: You cannot edit this field. _
      This data is automatically generated by Commence.", _
      0, "Warning")
   enterField = Form.Field("Name").Value 
   'Force setting as it won't be triggered
   Form.MoveToField("Name")
End Function 'CantGoHere

So with a few lines of code, we now have a mechanism to log and track changes. This is ideal for providing an audit trail and to help manage the integrity of your customer information.

blank.GIF (203 bytes)

Last Modified: 11:00, December 04, 2002.
bottomline.gif (4517 bytes)
CRMtimes - eNewsletter for Business Managers implementing CRM

auslogosmall.gif (726 bytes)

This site is sponsored by Advanced User Systems Pty Ltd.

Email: CRMtimes@aus.com.au
http://www.aus.com.au