分享

VBA中的控件数组

 yuxinrong 2010-01-12

VBA中的控件数组

2009年2月28日

大家都知道,和VB不一样,VBA中不能直接创建控件数组。然而可以使用WithEvents来模拟相同的功能。我们需要一个类来处理控件的事件,而每一个控件需要一个类实例。对于不同控件的类实例,我们可以使用一个对象数组或者集合来实现。

这里使用按钮控件做为例子来介绍怎样在窗体和工作表中创建控件数组。

创建类
创建控件数组之前,我们需要一个类来处理控件的事件。
在VBE窗口中,单击菜单“插入”->“类模块”,在属性窗口中将类的名称改为“cCB”。
在类模块中添加下面这一行:

Private WithEvents m_CB As MSForms.CommandButton

这样你就可以从代码栏的顶部左边下拉列表中选择m_CB并选择右边下拉列表中相应的事件。
完整的代码如下:

Private WithEvents m_CB As MSForms.CommandButton
' 初始化,将控件绑定到类
Public Sub Init(ctl As MSForms.CommandButton)
Set m_CB = ctl
End Sub
' 控件的Click事件
Private Sub m_CB_Click()
MsgBox "你点击了:" & m_CB.Caption
End Sub
' 注销类
Private Sub Class_Terminate()
Set m_CB = Nothing
End Sub

窗体中的控件数组
然后创建一个窗体,在窗体中添加两个CommandButton,将这两个按钮控件分别命名为cmd1和cmd2,然后在窗体中的初始化事件中添加代码如下:

Private ctlCB(1 To 2) As cCB
' 以对象数组保存类的实例
Private Sub UserForm_Initialize()
Set ctlCB(1) = New cCB
' 将按钮cmd1赋给类的实例
    ctlCB(1).Init cmd1
Set ctlCB(2) = New cCB
ctlCB(2).Init cmd2
End Sub

这里使用对象数组ctlCB(1 to 2)来保存类实例。每当使用Set语句创建一个类实例,然后使用类的Init方法将按钮控件赋给这个实例。

也可以使用集合来保存这个类的实例。代码如下:
Private colCB As New Collection
Private ctlCB As cCB
‘ 以集合保存类的实例

Private Sub UserForm_Initialize()
Set ctlCB = New cCB
' 将按钮cmd1赋给类的实例
    ctlCB.Init cmd1
' 将类的实例加入到集合中
    colCB.Add ctlCB
Set ctlCB = New cCB
ctlCB.Init cmd2
colCB.Add ctlCB
End Sub

点击按钮,将弹出对应的消息框。

上面的例子是将手动添加的控件添加到控件数组中。也可以动态创建控件数组。
创建一个新的窗体,然后在窗体的初始化事件中使用Controls集合的Add方法添加CommandButton控件,再将创建好的控件赋给类实例。完整代码如下:

Private ctlCB(1 To 3) As cCB
Private Sub UserForm_Initialize()
Dim nCtr As MSForms.CommandButton
For i = 1 To 3
' 添加按钮控件
        Set nCtr = Me.Controls.Add("Forms.CommandButton.1", "cmdTest" & i)
' 设置按钮控件标题和位置
        With nCtr
.Caption = "CommandButton_" & i
.Move 10, 10 + (i - 1) * 40, 80, 30
End With
' 创建cCB类实例
        Set ctlCB(i) = New cCB
' 将控件赋给类实例
        ctlCB(i).Init nCtr
Next i
End Sub

工作表中的控件数组
同样,在工作表中也可以创建控件数组(但和窗体有些不同)。在工作表中分别创建一个Label控件和三个CommandButton控件,如下图:

然后在Label控件的Click事件中添加如下代码:

Dim cmdCtl() As cCB
' 标签控件的Click事件
Private Sub Label1_Click()
Dim cmd As OLEObject        ' 所有OLE对象
    Dim i As Integer
' 重新定义数组
    ReDim cmdCtl(1 To Sheet2.OLEObjects.Count) As cCB
i = 1
' 循环所有的OLE对象
    For Each cmd In Sheet2.OLEObjects
' 只有CommandButton控件才可以加入到控件数组
        If cmd.progID = "Forms.CommandButton.1" Then
Set cmdCtl(i) = New cCB
cmdCtl(i).Init cmd.Object
i = i + 1
End If
Next
MsgBox "已经将工作表中所有CommandButton控件建成控件数组!", vbInformation
End Sub

值得注意的是使用类cCB的Init方法时,不能直接使用cmd变量,因为cmd变量是OLEObject类型。需要使用cmd变量的Object属性返回MSForms.CommandButton变量。

然而在工作表中对于动态创建的控件使用同样的方法创建控件数组时,动态创建的控件并不响应类实例的事件。代码如下:

Dim cmdCtl(1 To 5) As cCB
' 标签控件的Click事件
Private Sub Label1_Click()
Dim i As Integer
Dim cmd As OLEObject
 
For i = 1 To 5
Set 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 cCB
cmdCtl(i).Init cmd.Object
Next i
MsgBox "已经成功动态创建控件数组!", vbInformation
End Sub

类的实例应该是创建成功了(可以在Init方法中添加一些语句来验证),但就是不响应Click事件,不知道是什么原因,那位知道的同学帮忙解释解释一下,多谢了。

示范文件下载:Box.Net | SkyDrive

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多