本帖最后由 hyefeifei 于 2013-11-10 23:28 编辑
接着来,因为用数组构造集合类的局限性,我经常用的是collection,在论坛看了哪位朋友转贴的《字典与集合(Dictionary与Collection)》(这篇文章在主贴的附件里已经放在其中的一个工作表里了)才感觉到用字典的好处,大家弄明白了三种方式后,可以自己比较选择用哪种。 下面咱们用字典构造一个集合类,首先,咱们保留用数组建的那个类模块,新建一个类模块构造集合。把新建的类模块起名为:rngFormatDS
然后,需要在类模块的顶部声明一个字典
Private csDic AsObject 然后在类模块的初始化事件中,把字典对象实例化。
Private SubClass_Initialize() Set csDic =CreateObject("Scripting.Dictionary") End Sub
这里用了后期绑定,改为前期绑定,我想大家都会处理。
下面为类添加Add方法:
Public Sub Add(rng AsRange) Dim rF As rngFormat
Set rF = New rngFormat
Set rF.Cell = rng
rF.WhatType
Set csDic(rF.Cell.Address) = rF
End Sub
这里,我们用单元格地址(rF.Cell.Address)做为索引关键字,在实际应用中,我们可以根据情况,选适合的关键字。 下面添加count属性
Public Property GetCount() As Long Count = csDic.Count
End Property
下面添加item属性
Public Property GetItems(i As Variant) As rngFormat Dim arr
arr = csDic.Items
If IsNumeric(i) Then
Set Items = arr(i - 1)
Else
Set Items = csDic(i)
End If
End Property
这段代码简单讲一下,因为字典是用关键字索引的,而我们构造的集合类,希望不仅用关键字索引,而且还能用自然序数(0123……)索引,所以,我们要先声明一个数组,把字典的item放到数组里,再用自然序数索引数组。
这个属性的参数i是一可变类型,当其为数字时,则item=arr(i-1)
当其不为数字时,item用字典的key索引 item=csDic(i)
但这里有一个问题,就是当字典的关键字也是数字时,就会出现错误,在我们这里,因为是用单元格地址做为字典关键字的,不可能是数字,所以避免了错误,大家使用时,要注意这一点。
现在返回标准模块:在顶部加一个声明
Public rngDAs rngFormatDS
运行:
Sub 测试字典()
Dim rng As Range, i As Long
Set rngD = New rngFormatDS '实例化类,形成对象
For Each rng In Range("a1:a41")
rngD.Add rng
Next
For i = 1 To rngD.Count
Cells(i, "b") =rngD.Items(i).DataType
rngD.Items(i).rColor
Next
End Sub
即可看到程序正常运行。
下面在引入事件之前,先对rngFormat增加一个属性,大家可以看到,自把DataType属性声明为枚举类型后,我们得到的是01234的数字,很不直观,我们还是希望得到字符串表示的属性。我们当然不能变回去,重新把DataType声明为字符串的,而是增加一个字符串属性值。
增加一这个属性很容易,打开类模块加入如下代码即可:
PublicProperty Get strDataType() As String
Select Case mDatatype
Case 文本: strDataType = "文本"
Case 数字: strDataType = "数字"
Case 日期: strDataType = "日期"
Case 空值: strDataType = "空值"
Case 公式: strDataType = "公式"
End Select
EndProperty
另外,我们可以看到,a1:a41中有一些单元格是错误值,我们希望把错误值单独弄成一个类型,这怎么办?很简单,在rngFormat类模块中,
1.修改enumcType 声明,在最后加上 “错误”,不带引号
2.在whattype方法中,加入iserror判断
3.在getstrDataType中,加入:Case 错误:strDataType = "错误"
4.在rColor方法中,加入一个颜色值3(红色)
改过的代码在附件中,就不列全了。
现在来说一下事件
首先要明白捕获事件与引发事件之分
捕获事件大家知道,图表,工作表,工作簿等都有各自的事件,当我们在类模块中,用
WithEvents关键字声明 图表、 工作表、 工作簿这些对象时,就可以捕获这些对象的事件。
举例如下:
在类模块顶部输入如下代码:
PrivateWithEvents wks as Worksheet
你也可以用Public关键字声明这个模块级变量,如果用Public声明,就到此为止了,但我不主张使用Public声明,所以还得在类模块中加下一个可读写属性,代码如下:
Public Property Set Sheet(msh As Worksheet)
Set wks = msh
End Property
Public Property Get Sheet()
Set Sheet=wks
End Property
此时,就可以在模块左上方下拉列表框里,选择wks,而在右上方下拉列表框里,就可以看到所有相关的事件了。
引发事件引发事件就是我们可以建立类模块自有的事件,然后,在其他的类模块中,捕获我们自建的事件。要做到这点,第一步是声明一个自定义的事件
举例如下:
Event Aaa(xx,xx)
Aaa是事件的名字,括号里是事件的参数,也可以没有参数
第二步,使用raiseevent引发事件
这个Aaa事件何时发生呢?
当然是根据我们的需要,在需要它发生的时候发生,比如说,我们需要它在一个YYY方法的最后发生,就可以这样做:
Sub YYY
……
……
RaiseEvent Aaa(xx,xx)
End sub
当然也可以这个类所捕获的事件中引发它,随着我们给rngFormatDS类,及Rngformat类加入事件,大家就会越来越清楚了。
待续……
类_4.rar
(31.03 KB, 下载次数: 167)
|