对于每个在VBA代码中无法正常工作

时间:2008-12-24 18:29:22

标签: vba ms-access access-vba

好吧,我差不多完成了我讨论的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更改两次。

这很令人困惑,我对于为什么会这样做没有任何反对意见。

此外,我知道我使用了错误的注释语法,但如果我使用正确的语法,则“代码颜色”无法正确显示。

3 个答案:

答案 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