【发布时间】:2020-03-04 02:15:39
【问题描述】:
我有一个包含多个表的 MS Access 数据库,每个表都有不同的字段(每个表都有一个主键)。每当有人更改现有记录时,我希望将之前/之后的状态记录到“历史”表中,但我试图避免为每个表创建 20 多个字段的 DataMacro,因为这看起来很麻烦且难以管理。
为了实现这一点,我添加了“更改前”和“更新后”宏,每个宏都有一个 SetLocalVar 调用来运行驻留在本地模块中的公共 vba 函数。 "before" 函数循环遍历当前表中存在的任何字段以构建更改前值的字典。 “after”函数重复该过程以识别更改的字段,以便可以将信息添加到历史表中(包含表名、字段名、前/后值、用户、时间戳等)。
我遇到的问题是“更新后”功能仅显示更改前的数据。我不知道新值是什么或更改了哪个字段。我无法将 [Old].[FieldName],[FieldName] 作为 SetLocalVar 的输入,因为我事先不知道哪些字段将被更新(并且表之间的字段名称不同)。而且我无法调用 Requery 或 Refresh,因为它与“更新后”过程发生冲突。
在我在这里和其他地方可以找到的所有类似问题中,他们要么从明确知道哪个字段将更改开始,要么在日志事件中不提供该级别的详细信息。或者我的 google-fu 很弱。
这是我所拥有的:
SetLocalVar 表达式之前(每个表的输入表名不同):
=SetupLogEvent("Table01",[KeyName])
SetLocalVar表达式后:
=SubmitLogEvent("Table01",[KeyName])
模块代码
Public BeforeFields As Scripting.Dictionary
Public Function SetupLogEvent(ByVal TableName As String, ByVal KeyName As String)
Set BeforeFields = New Scripting.Dictionary
Set rs = CurrentDb.OpenRecordset("SELECT * FROM [" & TableName & "] WHERE KeyName='" & KeyName & "'")
Dim i As Long
With rs
.MoveLast
.MoveFirst
For i = 0 To rs.Fields.Count - 1
fName = rs.Fields(i).Name
fVal = rs.Fields(i).Value
BeforeFields.Add fName, fVal
Next i
End With
rs.Close
SetupLogEvent = True
End Function
Public Function SubmitLogEvent(ByVal TableName As String, ByVal KeyName As String)
DoEvents
Dim MakeUpdate As Boolean
MakeUpdate = False
Set rs = CurrentDb.OpenRecordset("SELECT * FROM [" & TableName & "] WHERE KeyName='" & KeyName & "'")
With rs
.MoveLast
.MoveFirst
For i = 0 To rs.Fields.Count - 1
fName = rs.Fields(i).Name
fVal = rs.Fields(i).Value
If fVal <> BeforeFields(fName) Then
Debug.Print ("Modified field is " & fName)
MakeUpdate = True
Exit For
End If
Next i
End With
rs.Close
If MakeUpdate = True Then
'Run SQL code to update the history table with the relevant information
'DoCmd.RunSQL <SQL code here>
End If
Set BeforeFields = Nothing
SubmitLogEvent = True
End Function
我怀疑我应该使用其他方法而不是循环浏览记录集,但我不确定我应该做什么。我想我可以在 after 函数中添加几十个可选输入,并手动将每个表的每个 [FieldName] 输入到每个表的 SetLocalVar 表达式中,但我无法想象系统如此不灵活以至于需要这样做。一定有更好的方法吧?
编辑:我已经更新了这个问题的标题以及我避免为每个字段编写 DataMacro 以供该主题的未来读者阅读的原因。
【问题讨论】:
-
搜索
DataMacro,也许这可以帮助你scottgem.wordpress.com/2012/10/18/… -
您可以从
After Update宏中访问旧值,因此您可能会通过同时使用宏之前和之后使事情变得比需要的更难,并且可能会产生一些奇怪的时序问题,可能解释你正在经历的行为。尝试只使用After Update进行现场比较。