大家都知道,和VB不一樣,VBA中不能直接創(chuàng)建控件數(shù)組。然而可以使用WithEvents來模擬相同的功能。我們需要一個類來處理控件的事件,而每一個控件需要一個類實例。對于不同控件的類實例,我們可以使用一個對象數(shù)組或者集合來實現(xiàn)。
這里使用按鈕控件做為例子來介紹怎樣在窗體和工作表中創(chuàng)建控件數(shù)組。
創(chuàng)建類
創(chuàng)建控件數(shù)組之前,我們需要一個類來處理控件的事件。
在VBE窗口中,單擊菜單“插入”->“類模塊”,在屬性窗口中將類的名稱改為“cCB”。
在類模塊中添加下面這一行:
Private WithEvents m_CB As MSForms.CommandButton
這樣你就可以從代碼欄的頂部左邊下拉列表中選擇m_CB并選擇右邊下拉列表中相應(yīng)的事件。
完整的代碼如下:
Private WithEvents m_CB As MSForms.CommandButton' 初始化,將控件綁定到類Public Sub Init(ctl As MSForms.CommandButton)Set m_CB = ctlEnd Sub' 控件的Click事件Private Sub m_CB_Click()MsgBox "你點擊了:" & m_CB.CaptionEnd Sub' 注銷類Private Sub Class_Terminate()Set m_CB = NothingEnd Sub
窗體中的控件數(shù)組
然后創(chuàng)建一個窗體,在窗體中添加兩個CommandButton,將這兩個按鈕控件分別命名為cmd1和cmd2,然后在窗體中的初始化事件中添加代碼如下:
Private ctlCB(1 To 2) As cCB' 以對象數(shù)組保存類的實例Private Sub UserForm_Initialize()Set ctlCB(1) = New cCB' 將按鈕cmd1賦給類的實例 ctlCB(1).Init cmd1Set ctlCB(2) = New cCBctlCB(2).Init cmd2End Sub
這里使用對象數(shù)組ctlCB(1 to 2)來保存類實例。每當使用Set語句創(chuàng)建一個類實例,然后使用類的Init方法將按鈕控件賦給這個實例。
也可以使用集合來保存這個類的實例。代碼如下:
Private colCB As New Collection
Private ctlCB As cCB
‘ 以集合保存類的實例
Private Sub UserForm_Initialize()Set ctlCB = New cCB' 將按鈕cmd1賦給類的實例 ctlCB.Init cmd1' 將類的實例加入到集合中 colCB.Add ctlCBSet ctlCB = New cCBctlCB.Init cmd2colCB.Add ctlCBEnd Sub
點擊按鈕,將彈出對應(yīng)的消息框。

上面的例子是將手動添加的控件添加到控件數(shù)組中。也可以動態(tài)創(chuàng)建控件數(shù)組。
創(chuàng)建一個新的窗體,然后在窗體的初始化事件中使用Controls集合的Add方法添加CommandButton控件,再將創(chuàng)建好的控件賦給類實例。完整代碼如下:
Private ctlCB(1 To 3) As cCBPrivate Sub UserForm_Initialize()Dim nCtr As MSForms.CommandButtonFor i = 1 To 3' 添加按鈕控件 Set nCtr = Me.Controls.Add("Forms.CommandButton.1", "cmdTest" & i)' 設(shè)置按鈕控件標題和位置 With nCtr.Caption = "CommandButton_" & i.Move 10, 10 + (i - 1) * 40, 80, 30End With' 創(chuàng)建cCB類實例 Set ctlCB(i) = New cCB' 將控件賦給類實例 ctlCB(i).Init nCtrNext iEnd Sub
工作表中的控件數(shù)組
同樣,在工作表中也可以創(chuàng)建控件數(shù)組(但和窗體有些不同)。在工作表中分別創(chuàng)建一個Label控件和三個CommandButton控件,如下圖:

然后在Label控件的Click事件中添加如下代碼:
Dim cmdCtl() As cCB' 標簽控件的Click事件Private Sub Label1_Click()Dim cmd As OLEObject ' 所有OLE對象 Dim i As Integer' 重新定義數(shù)組 ReDim cmdCtl(1 To Sheet2.OLEObjects.Count) As cCBi = 1' 循環(huán)所有的OLE對象 For Each cmd In Sheet2.OLEObjects' 只有CommandButton控件才可以加入到控件數(shù)組 If cmd.progID = "Forms.CommandButton.1" ThenSet cmdCtl(i) = New cCBcmdCtl(i).Init cmd.Objecti = i + 1End IfNextMsgBox "已經(jīng)將工作表中所有CommandButton控件建成控件數(shù)組!", vbInformationEnd Sub
值得注意的是使用類cCB的Init方法時,不能直接使用cmd變量,因為cmd變量是OLEObject類型。需要使用cmd變量的Object屬性返回MSForms.CommandButton變量。
然而在工作表中對于動態(tài)創(chuàng)建的控件使用同樣的方法創(chuàng)建控件數(shù)組時,動態(tài)創(chuàng)建的控件并不響應(yīng)類實例的事件。代碼如下:
Dim cmdCtl(1 To 5) As cCB' 標簽控件的Click事件Private Sub Label1_Click()Dim i As IntegerDim cmd As OLEObject For i = 1 To 5Set cmd = Sheet3.OLEObjects.Add(ClassType:="Forms.CommandButton.1", _Left:=Cells(i * 3 + 3, 2).Left, Top:=Cells(i * 3 + 3, 2).Top, Width:=Cells(1, 1).Width * 2, Height:=Cells(1, 1).Height * 1.5)Set cmdCtl(i) = New cCBcmdCtl(i).Init cmd.ObjectNext iMsgBox "已經(jīng)成功動態(tài)創(chuàng)建控件數(shù)組!", vbInformationEnd Sub
類的實例應(yīng)該是創(chuàng)建成功了(可以在Init方法中添加一些語句來驗證),但就是不響應(yīng)Click事件,不知道是什么原因,那位知道的同學(xué)幫忙解釋解釋一下,多謝了。