IN THE SPOTLIGHT: MDE to MDB Conversion Service
(also supports: ACCDE to ACCDB, ADE to ADP, etc)
IN THE SPOTLIGHT: Access Database Repair Service
An in-depth repair service for corrupt Microsoft Access files
IN THE SPOTLIGHT: vbWatchdog
VBA error handling just got easier...
" vbWatchdog is off the chart. It solves a long standing problem of how to consolidate error handling into one global location and avoid repetitious code within applications. "
- Joe Anderson,
Microsoft Access MVP
Meet Shady, the vbWatchdog mascot watching over your VBA code →
(courtesy of Crystal Long, Microsoft Access MVP)
IN THE SPOTLIGHT: vbMAPI
An Outlook / MAPI code library for VBA, .NET and C# projects
Get emails out to your customers reliably, and without hassle, every single time.
Use vbMAPI alongside Microsoft Outlook to add professional emailing capabilities to your projects.
IN THE SPOTLIGHT: Code Protector
Standard compilation to MDE/ACCDE format is flawed and reversible.
Code to accompany the Audit Log article.
' Author: Allen Browne, 2006. ' Purpose: Audit trail, to track Deletes, Edits, and Inserts. ' Does not audit any Cascading Updates/Deletes. ' Requirements: The table to be audited must have an AutoNumber primary key. ' Data entry must be through a form. ' Method: Makes a copy of the record in a temp table, and logs the ' change when it is guaranteed. The temp table copes with: ' - multiple deletes at once (continuous/datasheet view) ' - cancelled deletes or failed updates. ' - requirement for sequential numbering in the audit table. ' On a multi-user split (front-end/back-end) database, the ' temp table may reside in the front end, and the audit log ' in the back-end. ' Result: The audit table will contain one record for each deletion or ' insertion, and two records for each edit (before and after). ' Delete Copy of the deleted record, marked "Delete". ' Insert Copy of the new record, marked "Insert". ' Change: Copy of the record before change, marked "EditFrom". ' Copy of the record after change, marked "EditTo". ' This approach, together with the sequential numbering of the ' AutoNumber in the audit table makes tampering with the audit ' log more detectable. 'Note: Record confirmations need to be on. When opening the database: ' If Not Application.GetOption("Confirm Record Changes") Then ' Application.SetOption ("Confirm Record Changes"), True ' End If Option Compare Database Option Explicit Private Const conMod As String = "ajbAudit" Private Declare Function apiGetUserName Lib "advapi32.dll" Alias _ "GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long Function NetworkUserName() As String 'On Error GoTo Err_Handler 'Purpose: Returns the network login name Dim lngLen As Long Dim lngX As Long Dim strUserName As String NetworkUserName = "Unknown" strUserName = String$(254, 0) lngLen = 255& lngX = apiGetUserName(strUserName, lngLen) If (lngX > 0&) Then NetworkUserName = Left$(strUserName, lngLen - 1&) End If Exit_Handler: Exit Function Err_Handler: Call LogError(Err.Number, Err.Description, conMod & ".NetworkUserName", , False) Resume Exit_Handler End Function Function AuditDelBegin(sTable As String, sAudTmpTable As String, sKeyField As String, lngKeyValue As Long) As Boolean 'On Error GoTo Err_AuditDelBegin 'Purpose: Write a copy of the record to a tmp audit table. ' Copy to be written to real audit table in AfterDelConfirm. 'Arguments: sTable = name of table to be audited. ' sAudTmpTable = the name of the temp audit table. ' sKeyField = name of AutoNumber field in table. ' lngKeyValue = number in the AutoNumber field. 'Return: True if successful. 'Usage: Call from a form's Delete event. Example: ' Call AuditDelBegin("tblInvoice", "audTmpInvoice", "InvoiceID", Me.InvoiceID) 'Note: Must also call AuditDelEnd in the form's AfterDelConfirm event. Dim db As DAO.Database ' Current database Dim sSQL As String ' Append query. ' Append record to the temp audit table. Set db = DBEngine(0)(0) sSQL = "INSERT INTO " & sAudTmpTable & " ( audType, audDate, audUser ) " & _ "SELECT 'Delete' AS Expr1, Now() AS Expr2, NetworkUserName() AS Expr3, " & sTable & ".* " & _ "FROM " & sTable & " WHERE (" & sTable & "." & sKeyField & " = " & lngKeyValue & ");" db.Execute sSQL, dbFailOnError Exit_AuditDelBegin: Set db = Nothing Exit Function Err_AuditDelBegin: Call LogError(Err.Number, Err.Description, conMod & ".AuditDelBegin()", , False) Resume Exit_AuditDelBegin End Function Function AuditDelEnd(sAudTmpTable As String, sAudTable As String, Status As Integer) As Boolean 'On Error GoTo Err_AuditDelEnd 'Purpose: If the deletion was completed, copy the data from the ' temp table to the autit table. Empty temp table. 'Arguments: sAudTmpTable = name of temp audit table ' sAudTable = name of audit table ' Status = Status from the form's AfterDelConfirm event. 'Return: True if successful. 'Usage: Call from form's AfterDelConfirm event. Example: ' Call AuditDelEnd("audTmpInvoice", "audInvoice", Status) Dim db As DAO.Database ' Currrent database Dim sSQL As String ' Append query. ' If the Delete proceeded, copy the record(s) from temp table to delete table. ' Note: Only "Delete" types are copied: cancelled Edits may be there as well. Set db = DBEngine(0)(0) If Status = acDeleteOK Then sSQL = "INSERT INTO " & sAudTable & " SELECT " & sAudTmpTable & ".* FROM " & sAudTmpTable & _ " WHERE (" & sAudTmpTable & ".audType = 'Delete');" db.Execute sSQL, dbFailOnError End If 'Remove the temp record(s). sSQL = "DELETE FROM " & sAudTmpTable & ";" db.Execute sSQL, dbFailOnError AuditDelEnd = True Exit_AuditDelEnd: Set db = Nothing Exit Function Err_AuditDelEnd: Call LogError(Err.Number, Err.Description, conMod & ".AuditDelEnd()", False) Resume Exit_AuditDelEnd End Function Function AuditEditBegin(sTable As String, sAudTmpTable As String, sKeyField As String, _ lngKeyValue As Long, bWasNewRecord As Boolean) As Boolean 'On Error GoTo Err_AuditEditBegin 'Purpose: Write a copy of the old values to temp table. ' It is then copied to the true audit table in AuditEditEnd. 'Arugments: sTable = name of table being audited. ' sAudTmpTable = name of the temp audit table. ' sKeyField = name of the AutoNumber field. ' lngKeyValue = Value of the AutoNumber field. ' bWasNewRecord = True if this was a new insert. 'Return: True if successful 'Usage: Called in form's BeforeUpdate event. Example: ' bWasNewRecord = Me.NewRecord ' Call AuditEditBegin("tblInvoice", "audTmpInvoice", "InvoiceID", Me.InvoiceID, bWasNewRecord) Dim db As DAO.Database ' Current database Dim sSQL As String 'Remove any cancelled update still in the tmp table. Set db = DBEngine(0)(0) sSQL = "DELETE FROM " & sAudTmpTable & ";" db.Execute sSQL ' If this was not a new record, save the old values. If Not bWasNewRecord Then sSQL = "INSERT INTO " & sAudTmpTable & " ( audType, audDate, audUser ) " & _ "SELECT 'EditFrom' AS Expr1, Now() AS Expr2, NetworkUserName() AS Expr3, " & sTable & ".* " & _ "FROM " & sTable & " WHERE (" & sTable & "." & sKeyField & " = " & lngKeyValue & ");" db.Execute sSQL, dbFailOnError End If AuditEditBegin = True Exit_AuditEditBegin: Set db = Nothing Exit Function Err_AuditEditBegin: Call LogError(Err.Number, Err.Description, conMod & ".AuditEditBegin()", , False) Resume Exit_AuditEditBegin End Function Function AuditEditEnd(sTable As String, sAudTmpTable As String, sAudTable As String, _ sKeyField As String, lngKeyValue As Long, bWasNewRecord As Boolean) As Boolean 'On Error GoTo Err_AuditEditEnd 'Purpose: Write the audit trail to the audit table. 'Arguments: sTable = name of table being audited. ' sAudTmpTable = name of the temp audit table. ' sAudTable = name of the audit table. ' sKeyField = name of the AutoNumber field. ' lngKeyValue = Value of the AutoNumber field. ' bWasNewRecord = True if this was a new insert. 'Return: True if successful 'Usage: Called in form's AfterUpdate event. Example: ' Call AuditEditEnd("tblInvoice", "audTmpInvoice", "audInvoice", "InvoiceID", Me.InvoiceID, bWasNewRecord) Dim db As DAO.Database Dim sSQL As String Set db = DBEngine(0)(0) If bWasNewRecord Then ' Copy the new values as "Insert". sSQL = "INSERT INTO " & sAudTable & " ( audType, audDate, audUser ) " & _ "SELECT 'Insert' AS Expr1, Now() AS Expr2, NetworkUserName() AS Expr3, " & sTable & ".* " & _ "FROM " & sTable & " WHERE (" & sTable & "." & sKeyField & " = " & lngKeyValue & ");" db.Execute sSQL, dbFailOnError Else ' Copy the latest edit from temp table as "EditFrom". sSQL = "INSERT INTO " & sAudTable & " SELECT TOP 1 " & sAudTmpTable & ".* FROM " & sAudTmpTable & _ " WHERE (" & sAudTmpTable & ".audType = 'EditFrom') ORDER BY " & sAudTmpTable & ".audDate DESC;" db.Execute sSQL ' Copy the new values as "EditTo" sSQL = "INSERT INTO " & sAudTable & " ( audType, audDate, audUser ) " & _ "SELECT 'EditTo' AS Expr1, Now() AS Expr2, NetworkUserName() AS Expr3, " & sTable & ".* " & _ "FROM " & sTable & " WHERE (" & sTable & "." & sKeyField & " = " & lngKeyValue & ");" db.Execute sSQL ' Empty the temp table. sSQL = "DELETE FROM " & sAudTmpTable & ";" db.Execute sSQL, dbFailOnError End If AuditEditEnd = True Exit_AuditEditEnd: Set db = Nothing Exit Function Err_AuditEditEnd: Call LogError(Err.Number, Err.Description, conMod & ".AuditEditEnd()", , False) Resume Exit_AuditEditEnd End Function
Home | Index of tips | Top |
Rate this article:
This is a cached tutorial, reproduced with permission.
iTech Masters | VAT: GB202994606 | Terms | Sitemap | Newsletter