设为首页 加入收藏 网站搜索 繁體中文 中国建站网 — 站长资源平台

集合类:VBA集合对象的安全包装

来源网络收集 作者:佚名 时间:2007-4-26 15:48:57 该文得分0
你迟早都要管理一组由VBA类模块创建的自定义对象,VBACollection对象是实现这一目的的理想工具。我们在该杂志的Premiere期刊中曾经介绍过Collections,并且阐述了如何使用Collection对象来存储其他对象。虽然该项技术十分有用,但它确实还存在一些局限。在本文中,我们讨论了这些局限,并向你展示如何通过使用(你猜是什么)类模块来克服这些局限。


Collections中遇到的麻烦


Collections对象中到底有什么问题呢?它似乎存储对象存储得非常好。事实上,它工作起来的确是太好了。Collections对象得最大问题是它可以存储到任何数据类型得引用,例如Integer,String,Long,Variant,等(见图1)。


当然,如果你能保证每个对象都具有相同得类型,并且具有相同得属性何方法的话,那么在Collection中处理对象就变得异常简单。例如,作为本月范例ExcelVBA项目的组成部分,我们创建一个自定义的File类来代表一个磁盘文件。这个File类有几个属性,其中包括Path,Size,和ShortName。如果你创建了一个File对象的Collection,那么你将希望这个Collection中的每个对象都具有这些属性。你可以毫无异议地使用与下面类似的代码:


'PrintthesizeofthefirstfileintheCollection.
Debug.PrintcolFiles.Item(1).Size


但是,如果colFilesCollection中的第一个对象不是File,将会出现什么情况呢?如果它是一个Form或Control对象,又会怎样呢?如果它根本就不是一个对象呢?当然,当它试图执行该代码的时候,VBA将生成运行时间错误。




图1(左)VBACollection对象可以容纳任何类型的对象



图2(右)创建一个Collection类来防止不想要的对象进入集合


输入Collection类


Collection类可以充当Collection对象的过滤器,限制你可以在里面存储的对象类型(如图2所示)。通过与你的应用程序中的Collection类(二不是Collection对象本身)的互相作用,你可以防止不想要的对象的进入。创建和使用Collection类允许你扩展Collection对象的属性和方法(后面我们将举例说明)。


为了说明Collection类以及如何创建一个Collection类,我们将使用带有通过扫描磁盘目录创建的文件集合的Excel97项目。图3显示了一个表单,它用你选择了路径之后存储在自定义Collection类中的文件信息使得列表框通俗化。


这个表单使用一个叫做Files的Collection类来通俗化列表框。在创建Collection的时候,以向你的VBA项目添加一个新的类模块作为开始,然后在这个新模块的声明段声明一个PrivateCollection对象。下面是来自Files类模块的声明:


'Collectionoffiles.
PrivatepcolFilesAsNewCollection


为了将Collection对象与外界"隔绝",并阻止程序的其他部分用无用的东西填充它,必须将Collection对象声明为Private。


复制所需要的方法


当然,一旦你已经将Collection对象声明为Private,那么对于任何过程都没有办法向其中添加项目或从中删除项目了。因而,下一步就是复制Collection对象的标准方法了。尽管听起来象是做了大量额外的工作,实际上仍然在做我们前面所提及的"过滤"工作。


请记住,内建的Collection对象具有Add方法,该方法接受对象引用和独特的、包括文字与数字的标识符。如果你的应用程序正在直接使用Collection对象,那么它将极有可能创建对象的一个新的实例,并将其添加到Collection本身。


'Createanewinstanceofanobject.
DimobjFileAsNewFile
objFile.Path="C:AUTOEXEC.BAT"

'AddtoaCollectionobject.
colFiles.AddobjFile,objFile.ShortName

应用Collection类,应用程序调用该类的Add方法,传递任何必需的信息。请将先前的代码与Files类的Add方法做一比较:

WithaCollectionclass,theapplicationcallstheAddmethodoftheclass,passinganyrequiredinformation.ContrastthepreviouscodewiththeAddmethodoftheFilesclass:

PublicFunctionAdd(PathAsString)AsFile

DimobjFileAsFile

'CreatethenewFileobject.
SetobjFile=NewFile
objFile.Path=Path

'AddittothePrivatecollection.
pcolFiles.AddobjFile,objFile.ShortName

'Returnapointertothenewobject.
SetAdd=objFile

EndFunction

在本例中,到Collection的对象创建和添加发生在Add方法内部;而类则保留了完整的控制。任何必需的信息(例如文件的路径)是作为参数向方法提供的。由应用程序调用将文件添加到Collection的代码然后可以简化为:

'Addafiletothecollection.
colFiles.Add"C:AUTOEXEC.BAT"
InadditiontotheAddmethod,theCollectionclassshouldalsoimplementtheItemandRemovemethods,aswellasaCountproperty:

PublicFunctionItem(KeyAsVariant)AsFile
'Returnaniteminthecollection.
SetItem=pcolFiles.Item(Key)
EndFunction

PublicSubRemove(KeyAsVariant)
'Removeanitemfromthecollection.
pcolFiles.RemoveKey
EndSub

PropertyGetCount()AsLong
'Returnthenumberofitems.
Count=pcolFiles.Count
EndProperty

请注意,在这三种方法中,我们省略了错误处理--有些事情你是从来都不应该做的!至少应该包括一个错误处理器,通过使用Err对象的Raise方法来将错误传递、给调用过程。

图3这个表单通过显示文件信息来说明Collection类

'Privatevariabletostorepath.
PrivatepstrPathAsString

PropertyGetPath()AsString
'Returnstoredpathvalue.
Path=pstrPath
EndProperty

PropertyLetPath(strPathAsString)

DimstrFileAsString

'Clearthecollection.
SetpcolFiles=NewCollection

'Makesurethere'sabackslash.
IfRight(strPath,1)<>""Then
strPath=strPath&""
EndIf

'Getthefirstfile.
strFile=Dir(strPath&"*.*",_
vbReadOnlyOrvbHiddenOrvbArchiveOrvbSystem)
DoUntilLen(strFile)=0
'Addittothecollection.
CallAdd(strPath&strFile)
'Getthenextfile.
strFile=Dir()
Loop

'Savethepath.
pstrPath=strPath

EndProperty

图4向Collection类添加Path属性。将该属性和类设置为扫描目录并将所找到的每个文件添加到私有Collection对象。

扩展Collection类

现在,你可以通过声明Files类的一个实例来使用它了,并为曾经由Dir函数找到的每个文件反复调用该类的Add方法。但这不是我们的例子要完成的工作。为什么不是呢?使用Collection类的一个优点是你可以通过添加更多的属性和方法来扩展它的功能;不仅仅限于Add,Remove,Item,和Count。

在我们的Files类的情形中,它难道不

[1] [2]  下一页

相关文章
广告赞助
网友评论

共有 0 位网友发表了评论,平均得分: 0 查看完整内容

用户名:

分 值:100分 85分 70分 55分 40分 25分 10分 0分

内 容:

(注“”为必填内容。) 验证码: 验证码,看不清楚?请点击刷新验证码