2008-12-24 52 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