分享
 
 
 

集合類:VBA集合對象的安全包裝

王朝vb·作者佚名  2008-06-01
窄屏简体版  字體: |||超大  

你遲早都要管理一組由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類的情形中,它難道不對在類本身,而不是使用該類的每個應用程序裏面,放置掃描目錄的代碼做更多的檢測嗎?這是面向對象設計的一個指導原則:將代碼放在最靠近需要它的地方。

為了闡述這個概念,我們向Collection類添加了一個Path屬性。當你設置這個屬性的時候,這個類將對目錄進行掃描,並向Collection對象添加它所找到的每個文件(見圖4)。

當一個過程改變該類的Path屬性的時候,將觸發PropertyLet過程。在我們的例子中,它發生在你從瀏覽器對話框選擇了一個路徑之後。這裏是完成用文件列表填充Collection任務的簡單代碼。

'Reinitializethecollection.

SetmobjFiles=NewFiles

'Setthepathproperty.

mobjFiles.Path=strPath

一旦設置了Path屬性,Files類就將通俗化它自己的Collection,並且使它可以提供給應用程序。這已經是另一個例子了,在這個例子裏面,過程的"guts"存在於類自己內部(你可以證明類已不再需要它的Add和Remove方法了。在有些應用程序中,可能確實是這樣,但為了達到說明的目的,我們已經選擇了留下它們作為該類的一部分)。

一些不利之處

使用VBACollection類的生活並不總是美酒和玫瑰。當你使用Collection類代替Collection對象時,必須放棄兩樣東西。第一樣是Collection對象的默認方法,Item。默認的方法允許你從你的代碼中省略單詞"Item"。例如,如下兩條語句是一樣的,都是假定colFiles引用一個Collection對象。

Debug.PrintcolFiles.Item(1).Size

Debug.PrintcolFiles(1).Size

除非你正在使用的是VisualBasic5.0,否則沒有辦法為一個類指定默認的方法。因而,你必須總是顯式調用Item方法。

Collection類的第二個主要的不足之處是不能創建列舉函數。列舉類就是可以使ForEach循環工作的類。如果你想重復Collection中的每一個項目,那麽就必須用老式的方法來完成,也就是使用Count屬性和ForNext循環。例如,下面的代碼可以通俗化列表框:

'Fillthelistboxwithinfo.

lstFiles.Clear

ForlngCount=1TomobjFiles.Count

WithmobjFiles.Item(lngCount)

lstFiles.AddItem.ShortName&_

Space(12-Len(.ShortName))&_

vbTab&.AttributeString&_

vbTab&.Size

EndWith

Next

請註意該過程是如何使用計數器變量lngCount來完成從1到Collection中項目數的循環的。With語句使用了Item方法來引用Collection中的每個對象。

請註意,VisualBasic5.0用戶可以通過創建列舉函數來克服這一局限。在VisualBasicBookOnline中搜索關鍵字"enumeration"可以得到更為詳細的信息。-

 
 
 
免責聲明:本文為網絡用戶發布,其觀點僅代表作者個人觀點,與本站無關,本站僅提供信息存儲服務。文中陳述內容未經本站證實,其真實性、完整性、及時性本站不作任何保證或承諾,請讀者僅作參考,並請自行核實相關內容。
2023年上半年GDP全球前十五強
 百态   2023-10-24
美眾議院議長啟動對拜登的彈劾調查
 百态   2023-09-13
上海、濟南、武漢等多地出現不明墜落物
 探索   2023-09-06
印度或要將國名改為「巴拉特」
 百态   2023-09-06
男子為女友送行,買票不登機被捕
 百态   2023-08-20
手機地震預警功能怎麽開?
 干货   2023-08-06
女子4年賣2套房花700多萬做美容:不但沒變美臉,面部還出現變形
 百态   2023-08-04
住戶一樓被水淹 還衝來8頭豬
 百态   2023-07-31
女子體內爬出大量瓜子狀活蟲
 百态   2023-07-25
地球連續35年收到神秘規律性信號,網友:不要回答!
 探索   2023-07-21
全球鎵價格本周大漲27%
 探索   2023-07-09
錢都流向了那些不缺錢的人,苦都留給了能吃苦的人
 探索   2023-07-02
倩女手遊刀客魅者強控制(強混亂強眩暈強睡眠)和對應控制抗性的關系
 百态   2020-08-20
美國5月9日最新疫情:美國確診人數突破131萬
 百态   2020-05-09
荷蘭政府宣布將集體辭職
 干货   2020-04-30
倩女幽魂手遊師徒任務情義春秋猜成語答案逍遙觀:鵬程萬裏
 干货   2019-11-12
倩女幽魂手遊師徒任務情義春秋猜成語答案神機營:射石飲羽
 干货   2019-11-12
倩女幽魂手遊師徒任務情義春秋猜成語答案昆侖山:拔刀相助
 干货   2019-11-12
倩女幽魂手遊師徒任務情義春秋猜成語答案天工閣:鬼斧神工
 干货   2019-11-12
倩女幽魂手遊師徒任務情義春秋猜成語答案絲路古道:單槍匹馬
 干货   2019-11-12
倩女幽魂手遊師徒任務情義春秋猜成語答案鎮郊荒野:與虎謀皮
 干货   2019-11-12
倩女幽魂手遊師徒任務情義春秋猜成語答案鎮郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手遊師徒任務情義春秋猜成語答案鎮郊荒野:指鹿為馬
 干货   2019-11-12
倩女幽魂手遊師徒任務情義春秋猜成語答案金陵:小鳥依人
 干货   2019-11-12
倩女幽魂手遊師徒任務情義春秋猜成語答案金陵:千金買鄰
 干货   2019-11-12
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有