一起学Excel专业开发24:使用类模块创建对象3

2019-11-11 15:58:45 浏览数 (1)

在阅读本文之前,建议先阅读下面2篇文章:

1.一起学Excel专业开发22:使用类模块创建对象1

2.一起学Excel专业开发23:使用类模块创建对象2

自定义集合类存在的不足

在《一起学Excel专业开发23:使用类模块创建对象2》中,我们自定义的集合类存在两个方面的不足:

1.不能在For Each循环语句中直接处理集合中的成员,否则会导致出错,如下图1所示,只能通过索引和Item属性来处理。

图1

2.自定义的集合没有默认的属性,因此不能使用标准的集合语法如gclsCells(1)来简化Item属性,在访问集合中的成员时,必须显示地指定Item属性。

解决方法

方法1:使用Visual Basic 6

在VB6中,可以指定一个属性为某个类的默认属性。如果将Item属性指定为默认属性,则当需要访问集合中的某个成员时,就可以使用简写的方式,例如gclsCells(1)。

步骤1:在Excel VBE中,将CCells类模块导出,导出文件名为CCells.cls。

步骤2:在VB6中打开CCells.cls。

步骤3:将鼠标放置在Item属性过程中的任何地方,单击菜单“工具——过程属性”。

步骤4:在“过程属性”对话框中,单击“高级”按钮,选择“过程标识符”组合框中的“(缺省)项,如下图2所示。这样,将Item属性设置成了该类的默认属性。

图2

步骤5:添加代码以访问集合中的成员:

代码语言:javascript复制
Public Function NewEnum() As IUnknown
   Set NewEnum = mcolCells.[_NewEnum]
End Function

设置该过程的属性如下图3所示。

图3

这样,就可以使用For Each循环来直接处理自定义集合类中的成员了。

步骤6:保存修改。

步骤7:将CCells.cls导回到Excel VBE中。此时,在VB6中对该类模块所作的修改生效。

方法2:使用文本编辑器

如果没有安装VB6,可以通过文本编辑器如记事本来创建这些过程及其属性。

步骤1:在Excel VBE中,将CCells类模块导出,导出文件名为CCells.cls。

步骤2:在记事本中打开CCells.cls。

步骤3:将Item过程属性修改为:

代码语言:javascript复制
Property Get Item(ByVal vID As Variant)As CCell
   Attribute Item.VB_UserMemId = 0
   Set Item = mcolCells(vID)
End Property

步骤4:添加NewEnum过程:

代码语言:javascript复制
Public Function NewEnum() As IUnknown
   Attribute NewEnum.VB_UserMemId = -4
   Set NewEnum = mcolCells.[_NewEnum]
End Function

步骤5:保存并关闭记事本。

步骤6:将CCells.cls导回到Excel VBE中。

使用上述任一方法修改将CCells.cls类模块后,就可以使用gclsCells(1)的方式来获取集合中的成员,也可以使用For Each循环来直接处理自定义集合中的成员。此时,我们将CreateCellsCollection过程修改为:

代码语言:javascript复制
Public Sub CreateCellsCollection()
   Dim clsCell As CCell
   Dim lIndex As Long
   Dim lCount As Long
   Dim rngCell As Range
   
    '创建新的Cells集合
   Set gclsCells = New CCells
   
    '对当前工作表中已使用区域中的每个单元格创建Cell对象
   For Each rngCell In Application.ActiveSheet.UsedRange
       gclsCells.Add rngCell
   Next rngCell
   
    '统计集合中公式单元格的数量
   For Each clsCell In gclsCells
       If clsCell.CellType = anlCellTypeFormula Then
            lCount = lCount   1
       End If
   Next clsCell
   
   MsgBox "公式单元格数量:" & CStr(lCount)
End Sub

就不会出现本文开头的图1所示的错误了。

0 人点赞