好吧,我差不多完成了我讨论的here应用程序的审核部分。我这样做的方法是循环遍历所有文本字段,下拉框和复选框,并将它们的值存储在form_load事件中。然后我在form_afterUpdate事件中做同样的事情并比较两者。如果有差异我正在记录它,如果不是我继续前进。这是代码:
Dim strValues(1 To 32) As String
Private Sub Form_AfterUpdate()
Dim strCurrentValue, strSQL As String
Dim intCurrentField As Integer
intCurrentField = 1
For Each C In Forms!frmVendorsManageVendors.Controls
Select Case C.ControlType
Case acTextBox, acComboBox, acCheckBox
//Doing this because I don't want a NULL as it won't concatenate in the SQL query and don't want 0 or -1 for the boolean fields
strCurrentValue = IIf(IsNull(C), "", IIf(C = vbTrue Or C = vbFalse, IIf(C = vbTrue, "Yes", "No"), C))
If strValues(intCurrentField) <> strCurrentValue Then
strSQL = "INSERT INTO changesTable (change_time,user_affected,field_affected,old_value,new_value) VALUES (NOW()," & [id] & ",'" & C.ControlSource & "','" & strValues(intCurrentField) & "','" & strCurrentValue & "')"
DoCmd.SetWarnings False
DoCmd.RunSQL strSQL
//InputBox "", "", strSQL
strSQL = "WEEEE"
DoCmd.SetWarnings True
strValues(intCurrentField) = strCurrentValue
End If
intCurrentField = intCurrentField + 1
End Select
Next
End Sub
Private Sub Form_Open(Cancel As Integer)
Call btnLock_Click
Dim intCurrentField As Integer
intCurrentField = 1
For Each C In Forms!frmVendorsManageVendors.Controls
Select Case C.ControlType
Case acTextBox, acComboBox, acCheckBox
//Doing this because I don't want a NULL as it won't concatenate in the SQL query and don't want 0 or -1 for the boolean fields
strValues(intCurrentField) = IIf(IsNull(C), "", IIf(C = vbTrue Or C = vbFalse, IIf(C = vbTrue, "Yes", "No"), C))
intCurrentField = intCurrentField + 1
End Select
Next
End Sub
正如你所看到的那样,我在插入的changesTable中有一个注释掉的行,它会将查询放在一个输入框中,这样我就可以复制/粘贴它并查看它。当我取消注释该行时,一切都很好。如果它被注释,它会生成第一个更改,但不会为其他控件更改它。因此,如果我更改field1和field2,它将插入字段1更改两次。
这很令人困惑,我对于为什么会这样做没有任何反对意见。
此外,我知道我使用了错误的注释语法,但如果我使用正确的语法,则“代码颜色”无法正确显示。
答案 0 :(得分:1)
我不确定我是否有完整的答案,但有几点意见。
您可以使用CurrentDB.Execute strSQL消除一些代码行。这消除了对SetWarnings调用的需求。它直接针对数据库执行,而不与通常的接口机制交互。
出于调试目的,最好使用Debug.Print将SQL字符串输出到Debug窗口。它避免涉及用户界面仍然将SQL放在可以将其复制到剪贴板的地方,如果你想抓住它并使用它。
我认为DoCmd方法调用执行SQL的可能性很小,即使调用了SetWarnnigs,也可能会在界面中倾斜一些东西以便将焦点从表单中拉出来,就像shahkalpesh建议的那样。我已经完成了这样的事情而没有看到你遇到的问题,所以我对问题本身的唯一建议是按照我的方式做,切换到CurrentDB.Execute并消除循环内对DoCmd的调用。
好奇 - 你为什么使用数组代替以前的值而不是在控件上使用OldValue属性?
答案 1 :(得分:0)
我猜测AfterUpdate可能不适合使用。
此外,放置inputbox可能会导致现有控件失去焦点(这使其行为正常)。
我建议通过在select case之后将msgbox C.name放在循环中来检查每个控件是否正在运行。
答案 2 :(得分:0)
您是否尝试过使用execute语句(类似这样)?
Dim db As DAO.Database 'Inside the transaction.
Set db = CurrentDB
strSQL = "INSERT INTO changesTable (change_time, user_affected, " & _
"field_affected, old_value, new_value) VALUES (NOW()," & [id] & _
",'" & C.ControlSource & "','" & strValues(intCurrentField) & _
"','" & strCurrentValue & "')"
db.Execute strSql