I just wrote this little gem which is dynamic enough to withstand all the fields that I am yet to add to my form. It records changes to textboxes and comboboxes. It even takes the displayed content of the comboboxes rather than the bound data so that is end-user friendly.
Steps are:
1. Create the table (mine is in SQL then linked in Access hence the difference in name).
CREATE TABLE [dbo].[tbl_Members_ChangeLog](
[ChangeLog_ID] [int] IDENTITY(1,1) NOT NULL,
[Store_ID] [int] NOT NULL,
[ChangedBy] [varchar](50) NULL,
[DateTime] [smalldatetime] NULL,
[Field] [varchar](50) NULL,
[OldValue] [varchar](500) NULL,
[NewValue] [varchar](500) NULL,
CONSTRAINT [PK_Members_ChangeLog] PRIMARY KEY CLUSTERED
(
[ChangeLog_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[tbl_Members_ChangeLog] ADD CONSTRAINT [DF_Members_ChangeLog_DateTime] DEFAULT (getdate()) FOR [DateTime]
GO
2. Added the fOSUserName() function to your VBA module to get the windows user from here: http://access.mvps.org/access/api/api0008.htm
3. Add this code to catch the changes. You can call it from your form’s BeforeUpdate Sub:
Sub UpdateChangeLog()
Dim sSql As String
Dim rs As Recordset
Dim OldVal As String, NewVal As String
Debug.Print “—-”
‘cycle through text and combo boxes
For Each ctl In Me.Controls
If ctl.ControlType = acTextBox Or ctl.ControlType = acComboBox Then
If (ctl.Value <> ctl.OldValue) Or (Nz(ctl.OldValue, “”) = “” And ctl.Value <> “”) Then
If ctl.ControlType = acTextBox Then
OldVal = Nz(ctl.OldValue, “”)
NewVal = Nz(ctl.Value, “”)
ElseIf ctl.ControlType = acComboBox Then
‘get text for combobox lookup old value
If Nz(ctl.OldValue, “”) = “” Then
OldVal = “”
Else
Set rs = CurrentDb.OpenRecordset(ctl.RowSource, dbOpenSnapshot)
rs.MoveFirst
rs.FindFirst rs.Fields(0).Name & ” = ” & ctl.OldValue
OldVal = rs.Fields(1)
rs.Close
End If
‘get text for combobox lookup new value
Set rs = CurrentDb.OpenRecordset(ctl.RowSource, dbOpenSnapshot)
rs.MoveFirst
rs.FindFirst rs.Fields(0).Name & ” = ” & ctl.Value
NewVal = rs.Fields(1)
rs.Close
End If
Debug.Print ctl.Name
sSql = “INSERT INTO dbo_tbl_Members_ChangeLog (Store_ID, ChangedBy, Field, OldValue, NewValue) ” & _
“VALUES (” & Me.Store_ID & “, ‘” & fOSUserName() & “‘, ‘” & ctl.ControlSource & “‘, ‘” & OldVal & “‘, ‘” & NewVal & “‘);”
DoCmd.RunSQL sSql
End If
End If
Next ctl
Set rs = Nothing
End Sub