2009-05-28 37 views
3

在VBA中,我改變了Access窗體中幾個控件的值。我喜歡這樣做後運行這些控件的更新前的事件,因爲它會檢查字段之間的連貫性:有沒有辦法在VBA(MS Access 2002或2003)中調用任何控件的BeforeUpdate事件過程?

Private Sub ExampleProc1() 
    Dim intCancel as Integer 

    intCancel = False 

    Me.Controls("Date1").Value=Null 
    Me.Controls("Textfield1").Value=Null 

    Call Date1_BeforeUpdate(intCancel) 
    Call Textfield1_BeforeUpdate(intCancel) 
End Sub 

我想使它通用,但我不能找到一種方法來運行事件程序。我想這樣的事情:

Private Sub ExampleProc2(ParamArray Fields()) 
    Dim intCancel as Integer, varV as Variant 

    For Each varV in Fields 
    Me.Controls(varV).value=Null 
    intCancel = False 
    Call Me.Controls(varV).BeforeUpdate(intCancel) 
    Next 
End Sub 

這是可能的嗎?也許與DoCmd.RunMacro的東西是要走的路?

回答

3

其實你可以使用CallByName

CallByName Me, Me.Controls(varV).Name & "_BeforeUpdate", VbMethod, intCancel 
+0

+1使用示例。 – Oorang 2009-05-29 04:45:30

+0

這就是我正在尋找的。 兩個備註: - 在EventProcPrefix性質似乎更爲合適: CallByName我,Me.Controls(天花病毒).EventProcPrefix& 「_BeforeUpdate」,VbMethod,intCancel - 所調用的方法必須是公開的,即使CallByName從內部被稱爲表單對象。 – raph82 2009-08-07 16:44:50

0

顯然可以在Access中執行CallByName,但是您也可以將所有控件的BeforeUpdate邏輯放在集中式子集中,根據傳遞的參數改變其行爲。然後,您在BeforeUpdate事件處理程序中的所有內容都將是對您的集中式子例程的調用。

+0

你可以做到 - 看我的文章 – 2009-05-28 17:46:54

1

你可能要考慮創建自定義集合,然後通過那些你的功能。我廣泛使用它們來驗證控件。在窗體的onload事件

Dim mcolDateFields As New Collection 

然後,你可以這樣做:說在窗體的模塊級你定義這個集合

mcolDateFields.Add Me!txtDateEntered, "txtDateEntered" 
    mcolDateFields.Add Me!txtDatePrinted, "txtDatePrinted" 
    mcolDateFields.Add Me!txtDateArchived, "txtDateArchived" 

要通過收集走,你會做這樣的事情:

Dim varItem As Variant 
    Dim ctl As Control 

    For Each varItem In mcolDateFields 
    Set ctl = varItem 
    Debug.Print ctl.Name & ": " & ctl.Value 
    Next varItem 
    Set ctl = Nothing 

...在那裏你會用一些實際有用的東西替換Debug.Print。

然後你也可以通過控制到取一個集合作爲一個參數的其他代碼的程序和用它做什麼:

Public Sub (mcolCollection As Collection) 
    Dim varItem As Variant 
    Dim ctl As Control 

    For Each varItem In mcolCollection 
     Set ctl = varItem 
     Debug.Print ctl.Name & ": " & ctl.Value 
    Next varItem 
    Set ctl = Nothing 
    End Sub 

這可以讓你通過,你要驗證控件的集合。由於您將控件引用存儲在集合中,而不是控件名稱或控件值,因此不需要傳遞父表單名稱。如果你需要它,你可以用此得到它:

Dim varItem As Variant 
    Dim ctl As Control 

    For Each varItem In mcolCollection 
    Set ctl = varItem 
    Debug.Print ctl.Parent.Name & "!" & ctl.Name & ": " & ctl.Value 
    Next varItem 
    Set ctl = Nothing 

同樣,如果你想使用的表格你會使用窗體本身的模塊中的Me關鍵字以同樣的方式,只是使用CTL。 Parent,如果控件位於表單本身(而不是在選項卡控件上),則返回表單引用。

你的代碼示例一些評論 - 你的第一個看起來是這樣的:

Private Sub ExampleProc1() 
    Dim intCancel as Integer 

    intCancel = False 

    Me.Controls("Date1").Value=Null 
    Me.Controls("Textfield1").Value=Null 

    Call Date1_BeforeUpdate(intCancel) 
    Call Textfield1_BeforeUpdate(intCancel) 
    End Sub 

雖然它定義爲當你創建一個撤消事件的整數,這真的不是在所有 - 這是一個布爾值,並取消該事件,您必須將其設置爲True(-1)。我認爲這實際上是Access VBA之前Access VBA中的一種緩衝,當Access Basic缺少布爾型數據類型時。通常,我只使用布爾變量來使用與Cancel參數一起使用的變量。

Me.Controls("Date1").Value=Null 

我不知道你爲什麼要這樣做。我的代碼,因爲這:

Me!Date1 = Null 

你的代碼是在過於冗長你已經兩次指定的默認值:控件集合的形式爲默認集合。實際上,默認集合是控件和字段集合的連接,因此可能有充分的理由指定您想要使用控件,例如,如果您使用相應字段缺少的控件的屬性。但是爲了操縱這些值,如果有一個與字段名稱相同的控件,那麼使用哪個值並不重要,因爲它們將是相同的,除非極不可能的事件中該控件實際上並未綁定到該字段同名。

同樣,.Value是控件的默認屬性,所以沒有理由指定它。你可能想要這樣做的唯一情況是,如果你將它用作參數調用另一個參數是ByRef而不是ByVal的例程的參數。但總的來說,僅僅爲控件分配一個值就是浪費了輸入。

要做你正在努力完成的任務,控制參考的集合在我看來是一個很好的解決方案。不過,我不知道這些控件的事件是否需要公開。

相關問題