Ms access 对于在VBA代码中不能正常工作的每个

Ms access 对于在VBA代码中不能正常工作的每个,ms-access,vba,Ms Access,Vba,我几乎完成了我所讨论的应用程序的审计部分。我这样做的方式是在所有文本字段、下拉框和复选框中循环,并将它们的值存储在form_load事件中。然后我在form_afterUpdate事件中做同样的事情,并比较两者。如果有差异,我会记录下来,如果没有,我会继续。代码如下: Dim strValues(1 To 32) As String Private Sub Form_AfterUpdate() Dim strCurrentValue, strSQL As String Dim

我几乎完成了我所讨论的应用程序的审计部分。我这样做的方式是在所有文本字段、下拉框和复选框中循环,并将它们的值存储在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
Dim strValues(1到32)作为字符串
私有子表单_AfterUpdate()
Dim strCurrentValue,strSQL作为字符串
Dim intCurrentField为整数
intCurrentField=1
对于表单中的每个C!FRMVendorsManager.Controls
选择Case C.ControlType
案例acTextBox、acComboBox、acCheckBox
//这样做是因为我不想要NULL,因为它不会在SQL查询中串联,也不想要布尔字段为0或-1
strCurrentValue=IIf(IsNull(C),“”,IIf(C=vbTrue或C=vbFalse,IIf(C=vbTrue,“是”,“否”),C))
如果strValue(intCurrentField)strCurrentValue,则
strSQL=“插入到changesTable(更改时间、受影响的用户、受影响的字段、旧值、新值)值(现在()、”&[id]&“、”&C.ControlSource&“、”&strValue(intCurrentField)&“、”&strCurrentValue&“)”
DoCmd.SetWarnings错误
DoCmd.RunSQL strSQL
//输入框“”,strSQL
strSQL=“WEEEE”
DoCmd.SetWarnings True
strValues(intCurrentField)=strCurrentValue
如果结束
intCurrentField=intCurrentField+1
结束选择
下一个
端接头
私有子表单_打开(取消为整数)
呼叫btnLock\u单击
Dim intCurrentField为整数
intCurrentField=1
对于表单中的每个C!FRMVendorsManager.Controls
选择Case C.ControlType
案例acTextBox、acComboBox、acCheckBox
//这样做是因为我不想要NULL,因为它不会在SQL查询中串联,也不想要布尔字段为0或-1
strValues(intCurrentField)=IIf(IsNull(C),“”,IIf(C=vbTrue或C=vbFalse,IIf(C=vbTrue,“是”,“否”),C))
intCurrentField=intCurrentField+1
结束选择
下一个
端接头
正如您所看到的,有一个注释掉的行,我在其中插入changesTable,它将把查询放在一个输入框中,这样我就可以复制/粘贴它并查看它。当我取消注释那行时,一切都很好。如果对其进行了注释,则会生成第一次更改,但不会对其他控件进行更改。因此,如果我更改字段1和字段2,它将插入字段1更改两次

这是相当令人困惑的,我不知道为什么会发生这种情况


另外,我知道我使用了错误的注释语法,但是如果我使用了正确的语法,“代码颜色”er不会正确显示。

我猜AfterUpdate可能不是正确的事件使用方法

此外,放置inputbox可能会导致现有控件失去焦点(这会使其行为正确)


我建议在select case之后的循环中添加一个msgbox C.name,以检查每个控件是否正在运行。

我猜AfterUpdate可能不是正确的事件

此外,放置inputbox可能会导致现有控件失去焦点(这会使其行为正确)


我建议在select case之后的循环中放入一个msgbox C.name,检查您的每个控件是否正在运行。

我不确定是否有完整的答案,但有几个观察结果

您可以使用CurrentDB.executestrsql消除一些代码行。这减少了对SetWarnings调用的需要。它直接对数据库执行,而不与常用的接口机制交互

出于调试目的,最好使用Debug.Print将SQL字符串放到调试窗口中。它避免了涉及用户界面,但仍然将SQL放在您可以将其复制到剪贴板的位置,如果您想获取它并使用它的话

我认为执行SQL的DoCmd方法调用,即使调用SetWarnnigs,也很有可能会像shahkalpesh所建议的那样,在界面中触发一些东西,从而将焦点从表单上移开。我做过类似的事情,但没有看到您遇到的问题,因此我对问题本身的唯一建议是按照我的做法,切换到CurrentDB。在循环中执行并消除对DoCmd的调用


只是好奇——为什么要对前面的值使用数组,而不是对控件使用OldValue属性?

我不确定我有完整的答案,但有几个观察结果

您可以使用CurrentDB.executestrsql消除一些代码行。这减少了对SetWarnings调用的需要。它直接对数据库执行,而不与常用的接口机制交互

出于调试目的,最好使用Debug.Print将SQL字符串放到调试窗口中。它避免了涉及用户界面,但仍然将SQL放在您可以将其复制到剪贴板的位置,如果您想获取它并使用它的话

我认为执行SQL的DoCmd方法调用,即使调用SetWarnnigs,也很有可能会像shahkalpesh所建议的那样,在界面中触发一些东西,从而将焦点从表单上移开。我做过类似的事情,但没有看到您遇到的问题,因此我对问题本身的唯一建议是按照我的做法,切换到CurrentDB。在循环中执行并消除对DoCmd的调用


只是好奇——为什么要对前面的值使用数组,而不是对控件使用OldValue属性?

是否尝试过使用execute语句(类似这样的语句)


您是否尝试过使用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