VBA類模塊完全教程_第1頁
VBA類模塊完全教程_第2頁
VBA類模塊完全教程_第3頁
VBA類模塊完全教程_第4頁
VBA類模塊完全教程_第5頁
已閱讀5頁,還剩29頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、vba類模塊完全教程vba類:隱者的秘密 前言 寫下這個題目,可能會讓很多朋友疑惑,筆者先埋下一個關(guān)子,很快我會讓您知道這個標(biāo)題的寓意。 這份禮物送給現(xiàn)在想學(xué)習(xí)類知識或曾經(jīng)學(xué)過但因為各種原因沒有“修成正果”的朋友,我期望的結(jié)果是這篇文章后,您可以在類模塊中像在標(biāo)準(zhǔn)模塊中寫代碼一樣熟練,我也期望不至于太乏味而使您沒有耐心看完整篇文章,或者說期望您學(xué)習(xí)的過程是輕松愉悅的,但愿我可以做到。文章構(gòu)劃為8部分: 1什么是類 2為什么要學(xué)習(xí)類 3類的預(yù)備知識 4創(chuàng)建類屬性 5創(chuàng)建類方法 6創(chuàng)建類事件 7一個完整的類實例 8未完的結(jié)尾 什么是類在我們身邊,相同或相似的物品無處不在,從生活用品,到工業(yè)產(chǎn)品,通

2、常它們都是由同一個可以稱為“模具”的東西生產(chǎn)出來。 理解類,一般要先從對象談起,但由于從不同的角度,有不同的理解,從而也有不同的關(guān)于類的定義,本文不去探討一個完整并且公認的類概念,在這一部分后,只要你有一個基本的判斷并且在遇到時知道是類就可以了。在上面的這個例子中,一個“模具”就是一個“類”,而由它生產(chǎn)出的每一個產(chǎn)品,就是一個“對象”??聪旅娴膙ba語句: dim tx1 as textbox 不用解釋它的意思吧,這里我們用到一個類textbox定義了一個對象tx1,再來看: dim tx1 as textbox dim tx2 as textbox 又定義了一個對象tx2,如果你不嫌煩,我還

3、可以繼續(xù)下去。對象增加了,但as后的textbox沒有變,它可以無限制的使用下去。 類是一個隱者,上面textbox是vba已經(jīng)給我們準(zhǔn)備好的一個類,我們無法知道vba是怎么準(zhǔn)備的(它的真身被隱藏了),但我們可以知道對象tx1怎么用。vba把對對象的使用劃分為三種,屬性、方法和事件(后面預(yù)備知識我們再提)。 然而,textbox是一個類,仍然不是本文要說的類,因為它是vba已經(jīng)給我們準(zhǔn)備好了的,我們要做的,只是知道如何使用它而已。本文要介紹的,是利用vba已經(jīng)給我們提供的資源,來構(gòu)建我們自己的類,姑且可稱之為自定義類。這需要在vbe下,通過插入類模塊,然后向類模塊中寫入代碼來完成。這就是你常常

4、聽說的類,本文的主題就是這個包含代碼的模塊!通過這個模塊,可以提供給我們一個和vba提供給我們的諸如textbox功能性質(zhì)完全相同的類,然后,再由我們自己象使用textbox一樣使用! 類是一個隱者,她把自己藏在所有模塊的最后,甚至在多數(shù)情況,她從不出場。現(xiàn)在,她掛著神秘的微笑,向你走來,你要拒絕嗎為什么要學(xué)習(xí)類模塊二、 類通常被認為是學(xué)習(xí)vba的難點之一,之所以如此,因為相對于制造一個標(biāo)準(zhǔn)模塊或用戶窗體,我們可以找到的類的學(xué)習(xí)資源少之又少,甚至很多vb的書籍也只有繆繆字語(在后面的預(yù)備知識,我們再提另一個重要的原因)。從技術(shù)角度上看,類的構(gòu)建,不象窗體,vba的類也不象有些語言提供了可視的設(shè)

5、計界面,感性上那樣直接,隱者!她是不可視的設(shè)計,所有的構(gòu)建都是通過在類模塊中寫代碼來實現(xiàn)的。 1學(xué)習(xí)是一種興趣的追求 俗語云:學(xué)的千千萬,用的有幾何?又曰:書到用時方恨少。林語堂先生將做學(xué)問劃分為三重境界,第二重說“為伊消得人憔悴,衣帶漸寬終不悔”,大多數(shù)朋友,包括本人,都不是專業(yè)程序員,學(xué)習(xí)程序只是一種興趣和愛好,就好象有人喜歡修煉網(wǎng)游一樣,對喜歡程序的人,不斷地學(xué)習(xí)和提高,也是一種追求優(yōu)秀的態(tài)度,并且樂意享受這個追求的過程。模塊、控件、鏈接庫和類構(gòu)成軟件工程開發(fā)的四大技術(shù),而類技術(shù)是控件和鏈接庫技術(shù)的基礎(chǔ),我們不得不學(xué)。 2類有什么用 如你前面看到的我們使用textbox類,類可以創(chuàng)建大量

6、性質(zhì)相近的對象,減輕我們的程序量,簡潔代碼并提高效率。 類定義后,在其它模塊中使用時,我們就可以暫時忘記或不必考慮它內(nèi)部復(fù)雜的細節(jié),讓我們變得輕松,vba雖然不能真正封裝類的形式,但在這里,我們可以封裝它的概念。 這并不是類的全部好處,其它的,留著朋友們用的時候慢慢體會吧。 類掛著神秘的微笑,已經(jīng)走到你的大門口,開門迎接她吧,你還等什么?類的預(yù)備知識 廣義上講,所有vba的知識,包括語句、函數(shù)以及為我們提供的標(biāo)準(zhǔn)類甚至第三方的資源都可以在類中被使用。本文無法也不準(zhǔn)備逐一探討,這里只說一些最密切最基本的,但即使這樣,筆者仍然不能把這些點的知識都寫到,甚至因為對問題解釋清晰或符合邏輯的需要,采用非

7、規(guī)范的表述,對專門問題的全面理解,請讀者注意參考有關(guān)標(biāo)準(zhǔn)幫助文檔并加以甄別。 1從構(gòu)建者的角度理解對象 上一回我們提到,類被認為是vba難點還有一個原因,這就是我們的思想!vba提供了大量的現(xiàn)成的類,我們幾乎不再需要去構(gòu)建自己的類,這種結(jié)果,我們熟練地習(xí)慣了從使用者的角度去理解類的實例:對象,包括它的屬性、方法和事件。但是,現(xiàn)在你還要嘗試做一個提供者,這和你作為使用者時的思考方法是完全不同的,甚至是革命性的。這種角色的轉(zhuǎn)位是痛苦的,它需要你放棄你原本可以自豪地解釋出對象以及它的屬性、方法、事件的定義,它們原本是如此邏輯地被劃分,如此清晰,但現(xiàn)在,類模塊中的一切,彼此交織,你會發(fā)現(xiàn)它們都模糊了!

8、是需要你忘掉所有固執(zhí)的“招勢”的時候了,當(dāng)你心中無劍時,轉(zhuǎn)位也就完成了,隱者變得清晰了,她是如此美麗。且慢,在你完全忘掉前,讓我們最后再看一眼它們的樣子,呵呵,如果你實在忘不掉,你就提醒一下自己構(gòu)建者的身份吧。下面是通常情況下關(guān)于對象、屬性、方法、事件的基本表述,如果你以前沒了解過,則應(yīng)當(dāng)找些資料先認真地理解它們,然后再按照上面的提示去做。 對象是由類創(chuàng)建的一個實例,它是類的實體化。 對象的引用和操作被邏輯上劃分為不重疊的三個部分: 屬性是指對象的特性。以前面的textbox為例,有長度,高度,框中顯示的文字等等。 方法是指對象的某個操作。如讓textbox成為當(dāng)前的焦點(即光標(biāo)移動到它上面)

9、。 事件是指對象對外部動作的響應(yīng)。如我們用鼠標(biāo)點擊textbox時,會產(chǎn)生一個click事件,改變它的值,則產(chǎn)生一個change事件變量的作用域 變量因為聲明的位置和方式不同,從而有不同的作用域。作用域是指變量在多大范圍內(nèi)能被代碼識別。可以劃分為過程級、模塊級和全局變量。 過程級變量在過程中聲明,這里過程指的是一個sub或function,也包括后面提到到屬性過程。通常用dim或static進行聲明。dim聲明的變量,只在該過程執(zhí)行時存在,過程結(jié)束,變量的值也就消失了。static聲明的變量稱為靜態(tài)變量,這個值在整個程序運行期間都存在。 模塊級變量對整個模塊的所有過程都有效,但對其它模塊不可用

10、??梢栽谀K頂部聲明。聲明模塊級變量用private關(guān)鍵字和直接使用dim沒有區(qū)別。但推薦使用private進行聲明,因為這樣可以方便地與后面的全局變量區(qū)分開來。 全局變量是對整個vba工程的所有過程都有效的變量,使用public關(guān)鍵字在標(biāo)準(zhǔn)模塊的頂部來聲明。 在類模塊中,對變量作用域的理解要注意下面兩點: (a)由于類是生成對象的模具,每生成一個對象,相當(dāng)于產(chǎn)生了一個副本,這個副本就是對象的“真身”,副本間是相互獨立的,從而,模塊級的變量只作用于副本自身。 (b)類模塊中使用public關(guān)鍵字,只有當(dāng)對象變量是這個類的實例時,才能被訪問。 過程和函數(shù) 變量、過程(sub)、函數(shù)(functi

11、on)是我們在標(biāo)準(zhǔn)模塊中使用的最基本的構(gòu)件,在類摸塊中,它們?nèi)匀皇亲罨竞椭匾慕巧τ谒鼈?,你已?jīng)再熟悉不過,之所以前面還要花這么多文字,是為了突出它的重要,也是想讓你放松一下,哦,我花了很短的時間已經(jīng)看了這么多(我也寫了這么多!)。 過程和函數(shù)并無實質(zhì)的區(qū)別,當(dāng)需要返回值時,就使用function,如果不需要返回任何結(jié)果,隨你的愛好,但這時推薦你使用sub,因為這樣更符合微軟的本意。過程(sub)、函數(shù)(function)也有作用域,在標(biāo)準(zhǔn)模塊中通過使用private和public關(guān)鍵字(可以省略public關(guān)鍵字,因為它是默認的),可以劃分為模塊級和全局級,以決定它是在當(dāng)前的模塊有效還

12、是整個工程有效。 同變量一樣,在類模塊中使用public關(guān)鍵字,只有當(dāng)引用對象變量是這個類的實例時,才能被訪問通用內(nèi)部控件control(s) vba提供control類作為一般內(nèi)部控件類型,當(dāng)使用 dim ct as control 聲明了一個變量后,就可以將任何控件賦給該變量,而不管具體的類型,因為在類的使用通常是處理大量相近的對象,所以這種特性非常有用。在實際使用時,我們多是通過容器控件的controls屬性來返回一個control的集合對象。 dim ct as control for each ct in me.controls if typename(ct) = "com

13、mandbutton" then msgbox ct.caption next 上面這段代碼可以遍歷窗體的所有控件并報告找到的命令按鈕。集合collection collection是我們在使用類時最常用到的對象。一個collection對象代表一組相關(guān)的項目,雖然它的成員并不被強制要求是同一類型的的,但請記住,這通常并不能給我們帶來額外的方便,相反,我們通常是用來收集同一類型的數(shù)據(jù)。 建立集合的方法和建立其它對象一樣,如: dim col as new collection 集合建立后,可以使用add方法添加成員,用remove方法刪除成員,用item方法從集合中返回特定成員。 p

14、rivate sub commandbutton1_click() dim col as new collection dim i% dim ct as control for each ct in me.controls if left(ct.name, 7) = "textbox" then col.add ct next ct for i = col.count to 1 step -1 msgbox "下面刪除成員" & col.item(i).name col.remove i next i end sub 上面的代碼先將窗體上所有的t

15、extbox加入到集合中,然后再刪除掉。count屬性返回集合的成員數(shù)量,remove方法后面的參數(shù)是集合成員的索引號。成員的索引號通常是按照加入的順序自然編號,從1開始,但可以在加入時使用add方法的參數(shù)進行改變。add方法的完整語法是: object.add item, key, before, after item 必需的。任意類型的表達式,指定要添加到集合中的成員。 key 可選的。唯一字符串表達式,指定可以使用的鍵字符串,代替位置索引來訪問集合中的成員。 before/after 可選的。表達式,指定集合中的相對位置。 下面語句向集合增加一個對象textbox1,并定義該成員的關(guān)鍵字

16、為tx1。 col.add textbox1, "tx1" 然后,下面兩句都可以向集合中增加一個textbox2,并把它放在成員textbox1的前面。 col.add textbox2, , col.count col.add textbox2, , "tx1" 第一句中,因為只有一個成員,所以col.count也是索引號使用事件的withevents變量 withevents不是一個單獨的語句,為了使用對象的事件,需要在聲明該對象時使用withevents關(guān)鍵字。例如: dim withevents app as application 將上面的語句

17、寫入thisworkbook的模塊,可以看到在通用框中出現(xiàn)了一個變量app: 此主題相關(guān)圖片如下:在通用框選擇app后,左邊的聲明框便會顯示app的事件。 此主題相關(guān)圖片如下:需要注意的是,使用withevents只是聲明了對象變量,而并不實際生成對象,為了生成真實的對象,你仍然需要在聲明后向生成其它對象一樣,使用set語句進行指定。此外,withevents變量不能是通用類變量如object,而必須指定類名,也不能把withevents變量聲明為as new。不能在標(biāo)準(zhǔn)模塊中使用withevents初識類模塊現(xiàn)在,請打開你的vbe,主菜單-插入-類模塊。 插入了一個類模塊,也就建立了一個類。

18、類模塊的名字就是類的名字。你現(xiàn)在看到的,她的名字叫“類1”,這是vba按她姐妹排行給她取的的,是的,vba一貫如此,你早就熟悉了這種規(guī)則,現(xiàn)在,在標(biāo)準(zhǔn)模塊或其它模塊中輸入dim as的時候,提示框中她已經(jīng)出現(xiàn)了。但我知道,有件事你正耿耿于懷,“類1”,太沒個性了,想改成自己要的名字吧。很容易,和你改標(biāo)準(zhǔn)模塊的名字一樣,打開屬性窗口,看到了吧,第一行就是她的名字,隨你的意愿修改吧。 此主題相關(guān)圖片如下:你或許已經(jīng)注意到,在名字下面,只有一個屬性:instancing,其值也只有兩個選項:private和publicnotcreatable。事實上,你完全可以忽略這個instancing,就象你完

19、全忽略條件編譯指令一樣,因為在vba中我們幾乎用不到它們,而只需維持她的默認值即可。至少我是這樣認為的,但我給不了您充足的理由,而只是個人的一種狹隘經(jīng)歷。既然提到了,就簡單說明一下: instancing屬性決定該“類”在其它工程中是否可以被使用。我們知道,標(biāo)準(zhǔn)模塊中的public過程,可以保存在宏工作簿甚至直接被另一工作簿的工程調(diào)用,但類中的代碼是不可分割的整體,所以必須整體決定是否允許外用。當(dāng)instancing屬性設(shè)為private(默認)時,不允許其它工程訪問。當(dāng)設(shè)置為publicnotcreatable時,只有在自己的工程創(chuàng)建了該類的對象時,其它工程才允許使用這個對象,注意,僅僅是在

20、本工程中創(chuàng)建的對象,而不能用她在其它工程中創(chuàng)建對象。 隱者已經(jīng)來到你的身邊,透過薄薄的面紗,你似乎已看到她神秘的微笑。站起身來,走過去吧!創(chuàng)建類屬性 讓我們想一下作為類的使用者時,我們是如何操作對象的屬性的,對象屬性的操作不外乎讀和寫兩種。當(dāng)我們要給對象的某個屬性賦值時,我們會: textbox1.text=”abc” 當(dāng)我們要讀取對象的屬性時, s= textbox1.text 現(xiàn)在,看看作為類的提供者需要怎樣做。 我們將“類1”改名為“myclass”并為它創(chuàng)建一個名稱為x的字符型屬性。 1使用public變量創(chuàng)建類屬性 在類模塊中寫下行代碼: public x$ 是的,就這么簡單,通常情

21、況下,只需要這么簡單使用property過程創(chuàng)建類屬性 private s$ public property get x() as string x = s end property public property let x(byval c as string) s = c end property 我們可以省去上面默認的public。但看上去還是有點麻煩哦,不僅需要兩個公共過程,而且還要一個輔助的私有變量s和一個參數(shù)c。在類模塊中,property過程把對屬性的讀寫分開了,說一下property過程的工作機制,當(dāng)標(biāo)準(zhǔn)模塊中的代碼讀取對象的屬性時,便會觸發(fā)存在的property get過程,

22、或者說property get過程提供了屬性的讀功能,同樣,property let過程提供了寫屬性。這樣,上面的兩個過程(當(dāng)然在模塊中沒有先后的要求),可以只有一個,或者雖然兩個都有,但卻不全是public,從而提供出去的屬性是只讀或只寫(呵呵,沒見過只寫哈)。僅僅是為了提供只讀或只寫的屬性,代碼就從一行變成了七行?!這樣的理由,你不會信服, vba中的類通常是提供給我們自己使用的!如果它確實是只讀的,我們自覺地去只讀就是了!我們使用property過程還有其它理由,最基本的一條,我們可以利用這個“過程”來做我們想做的事??匆豢矗?public property let x(byval c

23、as string) s = format(c, "0000") end property 這里我們只是簡單的利用了一下,更多的在后面你會看到。此外,誰會保證有一天你不使用vb給別人提供類呢,這個技術(shù)可是通用的。提供一段標(biāo)準(zhǔn)模塊的測試代碼,來看看我們上面構(gòu)建的類屬性,你自己試試吧。 sub atest() dim mc as new myclass mc.x = "123" debug.print mc.x end sub 就象我們給普通變量和對象變量賦值的方式不同一樣,對象變量是使用set賦值的。對“對象”屬性,vba提供了property set來代

24、替構(gòu)建“普通”屬性使用的property let。來看一段代碼: private tx as object property get x() as object set x = tx end property property set x(byval o as object) set tx = o end property 和前面的比較一下,除了多一個set,實在沒有什么不同。 告訴你一個小秘訣,你可以按照function去記住property get的用法,按照sub去記住property let /set。屬性的初始值 我們常常希望,當(dāng)一個對象建立的時候,它的某些屬性會被自動賦予一個初始值

25、,這樣,對具有最常見的屬性值的對象可以減少重復(fù)性的賦值工作。這需要借助于類的構(gòu)建函數(shù)來完成。 在類模塊代碼窗口的“通用”框中點擊向下的小三角箭頭,選擇“class”,右面聲明框中可以看到兩個選項,“initialize”和“terminate”,我們對它們應(yīng)該不陌生,很多對象都有這兩個事件,initialize事件當(dāng)對象建立時發(fā)生,terminate事件在對象對釋放時發(fā)生。由于類是靜態(tài)存在的,它并不是真正的對象,所以在類模塊中,它們通常被稱為構(gòu)建函數(shù)和析構(gòu)函數(shù),或構(gòu)建過程和析構(gòu)過程。對它們的理解和你在對象中的用法并沒有什么不同。當(dāng)一個對象被建立時,構(gòu)建函數(shù)將被首先執(zhí)行,同樣,當(dāng)對象釋放后,將執(zhí)

26、行析構(gòu)函數(shù)。 下面建立myclass,屬性x初始值為”0001”的全部測試代碼: 類模塊myclass的代碼 option explicit private s$ public property get x() as string x = s end property public property let x(byval c as string) s = c end property private sub class_initialize() s = "0001" end sub 標(biāo)準(zhǔn)模塊1的代碼 option explicit sub atest() dim mc a

27、s new myclass debug.print mc.x end sub 隱者為你揭開了第一層面紗,你隱約已看到她美麗的面厐,雖然還不是很清晰,但你知道,早晚會的創(chuàng)建類方法 放松一下,請拿出你家的紫砂壺,泡上一壺好茶,聽我給你將類的方法的故事,你的茶品完了,我的故事也差不多就講完了。 1構(gòu)建類的方法其實就是在類模塊中寫公共的sub和function 現(xiàn)在我們給前面提到的myclass創(chuàng)建一個方法putintoactivecell,功能是將x屬性值寫入活動單元格。 public x$ sub putintoactivecell() activecell = x end sub 在標(biāo)準(zhǔn)模塊中用

28、下面的代碼測試一下: sub atest() dim mc as new myclass mc.x = "abc" mc.putintoactivecell end sub 這是本回要告訴你的全部嗎?你還沒有開始品茶吧?就這樣了結(jié)束?這是最重要和基本的,但卻不是全部。 你是否有一種感覺,但你不能清楚地說出來? 端起你可愛的茶杯,品一口茶,我們繼續(xù)。 類的方法環(huán)境 借用廣為眾知的一個名詞“數(shù)據(jù)環(huán)境”,雖然不準(zhǔn)確,但我實在想不出更好的稱謂來代替,姑且這么叫吧。稍后你就會知道它的含義。 類可以象vba提供給我們的很多標(biāo)準(zhǔn)類一樣風(fēng)光無限,所有的程序設(shè)計者都在工程中使用它,但更多時候

29、,我們所構(gòu)建的類只在特定的環(huán)境下被使用,類的方法環(huán)境是指包括類所在工程的其它成員在內(nèi)的,可以調(diào)用的資源的集合。工作簿、工作表、窗體或其它,在類模塊中,你可以象在標(biāo)準(zhǔn)模塊中一樣操作它們,千萬不要因為換成了類模塊而產(chǎn)生任何疑慮,作為類的創(chuàng)建者,你要讓類模塊中的代碼象你在標(biāo)準(zhǔn)模塊中一樣親近它們,只要你認為必要。脫離了方法環(huán)境的、謹小慎微的、封閉的類實在沒有什么意義。如果你預(yù)期方法環(huán)境在運行時可能會有變化,你要事先預(yù)知它們并象在標(biāo)準(zhǔn)模塊中一樣使用恰當(dāng)?shù)拇胧?,比如你不能確定運行時活動工作表的名稱(但你確定屆時會是一個工作表),你可以使用activesheet。 我反復(fù)說“和標(biāo)準(zhǔn)模塊一樣”,就是想告訴你在

30、類模塊中創(chuàng)建方法時,對工程中其它成員的操作,和你已經(jīng)熟悉的標(biāo)準(zhǔn)模塊中的方式的實在沒有什么不同,這一原則適用于類模塊中所有代碼(也許叫代碼環(huán)境更準(zhǔn)確些),而不僅僅是構(gòu)建方法的代碼。 現(xiàn)在,你知道了,你剛才的感覺到的是開放的方法環(huán)境。是的,以后你會更深地體會到,作為好的提供者,開放的思維有多重方法的兄弟成員事件 類方法的執(zhí)行需要在代碼中以顯性的方式指定,象上面的mc.putintoactivecell,有時候,當(dāng)最終操作者觸發(fā)類對象成員(屬性)的某個事件,需要在事件發(fā)生時產(chǎn)生一系列的操作,這時,我們要運用成員事件。成員事件和方法都是類提供的一系列代碼的操作,倆兄弟的區(qū)別在于,成員事件無法也不必再由

31、代碼顯性調(diào)用。 我們來看一個具有普遍意義的事例。 重要例 窗體userform1上有5個commandbutton控件(名稱分別為默認commandbutton 1- commandbutton 5)和1個textbox控件(名稱為textbox1)。要求當(dāng)各個commandbutton控件被點擊時,它的按鈕文字(caption)會寫入textbox1。 如果不用類,我們需要為5個commandbutton控件分別寫5個相同的click事件代碼。如: private sub commandbutton 1_click() textbox1 = commandbutton 1.caption e

32、nd sub 下面是用類的成員事件方法的代碼: 類模塊cmds的代碼 option explicit public withevents cmd as commandbutton private sub cmd_click() userform1.textbox1 = cmd.caption end sub 窗體userform1的代碼 option explicit dim co as new collection private sub userform_initialize() dim i% dim myc as cmds for i = 1 to 5 set myc = new cmd

33、s set myc.cmd = me.controls("commandbutton" & i) co.add myc next i set myc = nothing end sub 仔細玩味上例的每一行代碼,直至品完你壺中的茶。呵呵,因為它實在很有用。最后提一下friend關(guān)鍵字,雖然在vba中幾乎沒有什么用,但如果有一天你要制作activex部件,可能會用到它。之所以要有friend關(guān)鍵字,是因為類的私有部分在類模塊外是不可見的,但有時卻需要從外面訪問這些私有部分,這時,可以使用friend關(guān)鍵字使屬性和方法成為“友元成員”。友元成員在本工程中相當(dāng)于publi

34、c,但在工程外,它仍是private 。 隱者為你揭去了第二層面紗,你幾乎已看清她美麗的面龐,她帶著甜蜜的微笑,似乎在問:什么才是最美的期待?創(chuàng)建類事件 在vba中,因為我們既是提供者,也是使用者,所以通過良好地構(gòu)建類的屬性和方法,已可以滿足我們需要全部的要求。我不再去解釋這個觀點,在本回后你自然會明白。從這個意義上講,創(chuàng)建類事件實在沒有必要。唯一的遺憾是,我們沒有體會到作為創(chuàng)建者的全部樂趣,標(biāo)準(zhǔn)類給我們提供了各種事件,當(dāng)然希望自己也可以做到,想象中這應(yīng)當(dāng)是一件激動人心的事,所以,追求快樂是創(chuàng)建類事件的重要理由,另一個理由,前面已經(jīng)提到。 回到前面我們的myclass類,我們將x屬性

35、改名為value屬性,雖然對屬性、方法以及事件的命名,vba沒有特別的限制,但建議您不要象我前面那樣,隨便取一個x,可能的話,要盡量和標(biāo)準(zhǔn)類的成員(屬性、方法以及事件)名稱相一致。 現(xiàn)在我們?yōu)椤笆褂谩闭咛峁┮粋€“change”事件,不錯,我們給它取名為“change”,而不再是隨意的“y”或其它(雖然也可以),這樣,我也不用解釋這個事件的用意了,呵呵。為了做到這一點,看看我們應(yīng)該做什么。1第一步:使用event語句聲明事件 看一下類模塊中現(xiàn)在的代碼: option explicit public event change(byref cancel as boolean) private s$

36、public property get value() as string value = s end property public property let value(byval c as string) s = c end property private sub class_initialize() s = "abc" 初始值 end sub 和前面的代碼比較,多出了一句: public event change(byref cancel as boolean) 這就是event語句,只此一句,我們已經(jīng)為我們的類聲明(我想使用“注冊”一詞是不是更妥切)了一個事件c

37、hange。在看event語句產(chǎn)生的效果前,先來看它的特性: (1)為了聲明事件,event總是public的,這好理解吧。 (2)事件可以不帶參數(shù),如public event change(),也可以帶參數(shù),如我們上面給出的,但參數(shù)不能是命名參數(shù),可選參數(shù)或數(shù)組參數(shù)。這里我只解釋一下命名參數(shù)的含義。我們知道,事件可以因特定的用戶事件而觸發(fā),也可以在代碼中象方法一樣指定執(zhí)行,如下面的commandbutton1_click: private sub commandbutton2_click() commandbutton1_click end sub 但在調(diào)用對象的方法時我們通常喜歡這樣的方式

38、: selection.sort key1:=range("a2"), order1:=xlascending 這里key1、order1就是命名參數(shù),命名參數(shù)的好處是我們不必記住它們的次序,調(diào)用時直接以名稱和冒號后加等于號指定它的值,但對事件的調(diào)用卻不允許這樣。 (3)事件沒有返回值。 現(xiàn)在我們看一下,event為我們做了什么。 建立一窗體userform1,添加一個textbox控件(名稱為textbox1),兩個commandbutton控件(名稱為commandbutton1和commandbutton2),commandbutton1的caption設(shè)置為“賦值”

39、,commandbutton2的caption設(shè)置為“讀值”,窗體的代碼如下: option explicit dim withevents mc as myclass private sub commandbutton1_click() mc.value = textbox1 '賦值 end sub private sub commandbutton2_click() msgbox "mc當(dāng)前的值為" & mc.value '讀值 end sub private sub userform_initialize() set mc = new mycl

40、ass end sub 上面這段代碼實現(xiàn)的是,當(dāng)點擊commandbutton1時便會將textbox1的值賦給mc的value,當(dāng)點擊commandbutton2時便會顯示mc當(dāng)前的value值。 來運行一下這個窗體,先點擊commandbutton2,此時顯示“abc”,是mc的初始值,然后在textbox1輸入“123”,點擊commandbutton1,再點擊commandbutton2,顯示“123”,說明賦值成功了。 呵呵,忘了,我們要做什么了!現(xiàn)在,請從userform1代碼窗口的“通用”框中選擇mc,哇!我們聲明的事件在右邊“聲明”框中已經(jīng)出現(xiàn)了! 此主題相關(guān)圖片如下:待添加的

41、隱藏文字內(nèi)容2我們定義這個事件是希望當(dāng)mc的值改變時響應(yīng)的,現(xiàn)在就迫不及待地給它寫一句代碼吧: private sub mc_change(byref cancel as boolean) if msgbox("要改變mc的值嗎?", vbyesno) = vbno then cancel = true end sub 上面這句代碼你不會陌生吧,希望當(dāng)用戶選擇了在改變時給用戶一個確認的機會。 但是,現(xiàn)在點擊commandbutton1,卻不會給你選擇的機會,我們還有一步?jīng)]有做。 使用raiseevent語句引發(fā)事件第二步:使用raiseevent語句引發(fā)事件 聲明了事件后,

42、我們要做的,便是找到所有與事件發(fā)生關(guān)聯(lián)的地方,使用raiseevent語句引發(fā)事件,這里引發(fā)的含義相當(dāng)于call,就是調(diào)用用戶在事件中寫的代碼。在本例中,只有一個地方,就是property let value過程中: dim chyn as boolean raiseevent change(chyn) if chyn then exit property 通過傳遞回的chyn,決定是否執(zhí)行后面的賦值語句。下面就是添加了raiseevents語句后的類模塊的代碼: option explicit public event change(byref cancel as boolean) priv

43、ate s$ public property get value() as string value = s end property public property let value(byval c as string) dim chyn as boolean raiseevent change(chyn) if chyn then exit property s = c end property private sub class_initialize() s = "abc" end sub 現(xiàn)在你可以去運行你的窗體了,我們要的效果應(yīng)該是達到了吧。為了便于你調(diào)試,下面給出窗體的全部代碼: option explicit dim withevents mc as myclass private sub commandbutton1_click() mc.value = textbox1 '賦值 end sub pr

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論