2008-12-24 43 views
1

那么我几乎完成了我的应用程序的审计部分,我讨论了here。我这样做的方式是遍历所有文本字段,下拉框和复选框,并将它们的值存储在form_load事件中。然后我在form_afterUpdate事件中做同样的事情并比较两者。如果有差别,我会记录它,如果没有,我继续前进。下面是代码:对于VBA代码中的每个工作不正确

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更改两次。

这是相当混乱,我没有CLUE为什么发生这种情况。

另外我知道我使用错误的评论语法,但如果我使用正确的语法SO“代码颜色”呃不能正确显示。

+0

通过在注释末尾放置另一个撇号/单引号,可以在代码降级中使用正确的注释语法。这招使colorer认为评论是一个字符串,但它也将允许任何人复制/粘贴你的代码,并让它开箱即用 – 2008-12-24 18:41:21

+0

两件事:1. //不是VBA的注释分隔符,它是撇号。当我在Access代码中使用//时,它会引发编译错误。 2.您似乎没有将C声明为变量,这表明您在所有代码模块中都没有OPTION EXPLICIT。这是* TERRIBLE *编码练习。 – 2008-12-27 04:08:03

回答

0

我猜测AfterUpdate可能不是正确的事件使用。

此外,放入inputbox可能会导致现有的控件松散焦点(这使它的行为正确)。

我会建议通过在选择大小写后在循环中放置msgbox C.name来检查每个控件是否正在运行。

1

我不确定我是否有全部答案,但有几点意见。

你可以通过使用CurrentDB.Execute strSQL来消除一些代码行。这最终需要SetWarnings调用。它直接针对数据库执行,而无需与通常的接口机制进行交互。

出于调试目的,最好使用Debug.Print将SQL字符串输出到调试窗口。它避免了涉及用户界面的问题,如果你想抓住它并且使用它,你仍然可以将SQL复制到剪贴板。

我认为DoCmd方法调用执行SQL即使调用SetWarnnigs也可能会降低界面中的某些功能以将焦点从窗体中拉出,如shahkalpesh建议的。我做了这样的事情,并没有看到你遇到的问题,所以我对问题本身的唯一建议就是像我这样做,并切换到CurrentDB.Execute并消除循环内部对DoCmd的调用。

只是好奇 - 为什么你使用数组而不是在控件上使用OldValue属性?

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 
相关问题