加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

【重要】VBA中的控件数组

(2017-03-19 15:14:40)
分类: 置顶
VBA中的控件数组 
━━━━━━━━━━━━━━━━━━━━━━━━━ 

大家都知道,和VB不一样,VBA中不能直接创建控件数组。然而可以使用WithEvents来模拟相同的功能。我们需要一个类来处理控件的事件,而每一个控件需要一个类实例。对于不同控件的类实例,我们可以使用一个对象数组或者集合来实现。
这里使用按钮控件做为例子来介绍怎样在窗体和工作表中创建控件数组。

创建类
创建控件数组之前,我们需要一个类来处理控件的事件。
在VBE窗口中,单击菜单“插入” - > “类模块”,在属性窗口中将类的名称改为“cCB”。
在类模块中添加下面这一行:
Private WithEvents m_CB As MSForms.Commanon
这样你就可以从代码栏的顶部左边下拉列表中选择m_CB并选择右边下拉列表中相应的事件。

完整的代码如下:

Private WithEvents m_CB As MSForms.Commanon
初始化,将控件绑定到类
Public Sub Init(ctl As MSForms.Commanon)
    
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


窗体中的控件数组
━━━━━━━━━━━━━━━━━━━━━━━━━

创建一个窗体,在窗体中添加两个Commanon,将这两个按钮控件分别命名为cmd1和cmd2,然后在窗体中的初始化事件中添加代码如下:
Private ctlCB(To 2As cCB
以对象数组保存类的实例
Private Sub UserForm_Initialize()
    
Set ctlCB(1New cCB
    将按钮cmd1赋给类的实例
    
ctlCB(1).Init cmd1
    Set ctlCB(2New cCB
    ctlCB(2).Init cmd2
End Sub

这里使用对象数组ctlCB(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方法添加Commanon控件,再将创建好的控件赋给类实例。

完整代码如下:
Private ctlCB(To 3As cCB
Private Sub UserForm_Initialize()
    
Dim nCtr As MSForms.Commanon
    For To 3
        添加按钮控件
        
Set nCtr Me.Controls.Add("Forms.Commanon.1", "cmdTesti)
        
设置按钮控件标题和位置
        
With nCtr
            .Caption "Commanon_i
            .Move 10, 10 (140, 80, 30
        End With
        
创建cCB类实例
        
Set ctlCB(iNew cCB
        将控件赋给类实例
        
ctlCB(i).Init nCtr
    Next i
End Sub


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

然后在Label控件的Click事件中添加如下代码:
Dim cmdCtl() As cCB
标签控件的Click事件
Private Sub Label1_Click()
    
Dim cmd As OLEObject        所有OLE对象
    
Dim As Integer
    
重新定义数组
    
ReDim cmdCtl(To Sheet2.OLEObjects.CountAs cCB
    1
    循环所有的OLE对象
    
For Each cmd In Sheet2.OLEObjects
        只有Commanon控件才可以加入到控件数组
        
If cmd.progID "Forms.Commanon.1Then
            Set 
cmdCtl(iNew cCB
            cmdCtl(i).Init cmd.Object
            1
        End If
    Next
    MsgBox 
"已经将工作表中所有Commanon控件建成控件数组!", vbInformation
End Sub

值得注意的是使用类cCB的Init方法时,不能直接使用cmd变量,因为cmd变量是OLEObject类型。需要使用cmd变量的Object属性返回MSForms.Commanon变量。
然而在工作表中对于动态创建的控件使用同样的方法创建控件数组时,动态创建的控件并不响应类实例的事件。

代码如下:
Dim cmdCtl(To 5As cCB
标签控件的Click事件
Private Sub Label1_Click()
    
Dim As Integer
    
Dim cmd As OLEObject
    For To 5
        Set cmd Sheet3.OLEObjects.Add(ClassType: = "Forms.Commanon.1", _
Left: = Cells(3, 2).Left, Top: = Cells(3, 2).Top, Width: = Cells(1, 1).Width 2, Height: = Cells(1, 1).Height 1.5)
        
Set cmdCtl(iNew cCB
        cmdCtl(i).Init cmd.Object
    Next i
    MsgBox "已经成功动态创建控件数组!", vbInformation
End Sub

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

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有