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

下載本文檔

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

文檔簡介

1、VBA 類模塊完全教程EXCEL VBA 2009-05-13 15:52 閱讀 344 評論 1字號: 大 中 小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一個完

2、整的類實例8未完的結(jié)尾什么是類在我們身邊,相同或相似的物品無處不在,從生活用品,到工業(yè) 產(chǎn)品,通常它們都是由同一個可以稱為 “模具”的東西生產(chǎn)出來。理解類,一般要先從對象談起,但由于從不同的角度,有不同的 理解,從而也有不同的關(guān)于類的定義, 本文不去探討一個完整并且公 認(rèn)的類概念,在這一部分后, 只要你有一個基本的判斷并且在遇到時 知道是類就可以了。在上面的這個例子中, 一個“模具”就是一個“類”, 而由它生產(chǎn)出的每一個產(chǎn)品,就是一個“對象”。看下面的 VBA 語 句:Dim tx1 As Textbox不用解釋它的意思吧, 這里我們用到一個類 Textbox 定義了一個 對象 tx1 ,再來

3、看:Dim tx1 As TextboxDim tx2 As Textbox又定義了一個對象 tx2 ,如果你不嫌煩,我還可以繼續(xù)下去。對 象增加了,但 As 后的 Textbox 沒有變,它可以無限制的使用下去。類是一個隱者,上面 Textbox 是 VBA 已經(jīng)給我們準(zhǔn)備好的一個 類,我們無法知道 VBA 是怎么準(zhǔn)備的(它的真身被隱藏了),但我 們可以知道對象 tx1 怎么用。 VBA 把對對象的使用劃分為三種,屬 性、方法和事件(后面預(yù)備知識我們再提)。然而, Textbox 是一個類,仍然不是本文要說的類,因為它是 V BA 已經(jīng)給我們準(zhǔn)備好了的, 我們要做的,只是知道如何使用它而已。

4、 本文要介紹的,是利用 VBA 已經(jīng)給我們提供的資源,來構(gòu)建我們自 己的類,姑且可稱之為自定義類。這需要在 VBE 下,通過插入類模 塊,然后向類模塊中寫入代碼來完成。這就是你常常聽說的類,本文 的主題就是這個包含代碼的模塊! 通過這個模塊, 可以提供給我們一 個和 VBA 提供給我們的諸如 Textbox 功能性質(zhì)完全相同的類, 然后, 再由我們自己象使用 Textbox 一樣使用!類是一個隱者, 她把自己藏在所有模塊的最后, 甚至在多數(shù)情況, 她從不出場?,F(xiàn)在,她掛著神秘的微笑,向你走來,你要拒絕嗎為什么要學(xué)習(xí)類模塊類通常被認(rèn)為是學(xué)習(xí) VBA 的難點之一,之所以如此,因為相對 于制造一個標(biāo)

5、準(zhǔn)模塊或用戶窗體, 我們可以找到的類的學(xué)習(xí)資源少之 又少,甚至很多 VB 的書籍也只有繆繆字語(在后面的預(yù)備知識,我 們再提另一個重要的原因) 。從技術(shù)角度上看, 類的構(gòu)建,不象窗體, VBA 的類也不象有些語言提供了可視的設(shè)計界面, 感性上那樣直接, 隱者!她是不可視的設(shè)計, 所有的構(gòu)建都是通過在類模塊中寫代碼來 實現(xiàn)的。1學(xué)習(xí)是一種興趣的追求俗語云:學(xué)的千千萬,用的有幾何?又曰:書到用時方恨少。 林語堂先生將做學(xué)問劃分為三重境界,第二重說“為伊消得人憔 悴,衣帶漸寬終不悔” ,大多數(shù)朋友, 包括本人,都不是專業(yè)程序員, 學(xué)習(xí)程序只是一種興趣和愛好, 就好象有人喜歡修煉網(wǎng)游一樣, 對喜 歡程

6、序的人,不斷地學(xué)習(xí)和提高,也是一種追求優(yōu)秀的態(tài)度,并且樂 意享受這個追求的過程。模塊、控件、鏈接庫和類構(gòu)成軟件工程開發(fā) 的四大技術(shù),而類技術(shù)是控件和鏈接庫技術(shù)的基礎(chǔ),我們不得不學(xué)。2類有什么用如你前面看到的我們使用 Textbox 類,類可以創(chuàng)建大量性質(zhì)相近 的對象,減輕我們的程序量,簡潔代碼并提高效率類定義后,在其它模塊中使用時,我們就可以暫時忘記或不必考 慮它內(nèi)部復(fù)雜的細(xì)節(jié),讓我們變得輕松, VBA 雖然不能真正封裝類 的形式,但在這里,我們可以封裝它的概念。這并不是類的全部好處,其它的,留著朋友們用的時候慢慢體會 吧。類掛著神秘的微笑,已經(jīng)走到你的大門口,開門迎接她吧,你還 等什么?類的

7、預(yù)備知識廣義上講,所有 VBA 的知識,包括語句、函數(shù)以及為我們提供 的標(biāo)準(zhǔn)類甚至第三方的資源都可以在類中被使用。 本文無法也不準(zhǔn)備 逐一探討,這里只說一些最密切最基本的,但即使這樣,筆者仍然不 能把這些點的知識都寫到, 甚至因為對問題解釋清晰或符合邏輯的需 要,采用非規(guī)范的表述,對專門問題的全面理解,請讀者注意參考有 關(guān)標(biāo)準(zhǔn)幫助文檔并加以甄別。1從構(gòu)建者的角度理解對象上一回我們提到,類被認(rèn)為是 VBA 難點還有一個原因,這就是 我們的思想! VBA 提供了大量的現(xiàn)成的類,我們幾乎不再需要去構(gòu) 建自己的類, 這種結(jié)果, 我們熟練地習(xí)慣了從使用者的角度去理解類 的實例:對象,包括它的屬性、方法和

8、事件。但是,現(xiàn)在你還要嘗 試做一個提供者, 這和你作為使用者時的思考方法是完全不同的, 甚 至是革命性的。 這種角色的轉(zhuǎn)位是痛苦的, 它需要你放棄你原本可以 自豪地解釋出對象以及它的屬性、方法、事件的定義,它們原本是如 此邏輯地被劃分,如此清晰,但現(xiàn)在,類模塊中的一切,彼此交織, 你會發(fā)現(xiàn)它們都模糊了!是需要你忘掉所有固執(zhí)的 “招勢”的時候了, 當(dāng)你心中無劍時,轉(zhuǎn)位也就完成了,隱者變得清晰了,她是如此美麗。 且慢,在你完全忘掉前,讓我們最后再看一眼它們的樣子,呵呵,如 果你實在忘不掉, 你就提醒一下自己構(gòu)建者的身份吧。 下面是通常情 況下關(guān)于對象、屬性、方法、事件的基本表述, 如果你以前沒了解

9、過, 則應(yīng)當(dāng)找些資料先認(rèn)真地理解它們,然后再按照上面的提示去做。對象是由類創(chuàng)建的一個實例,它是類的實體化。對象的引用和操作被邏輯上劃分為不重疊的三個部分:屬性是指對象的特性。以前面的 Textbox 為例,有長度,高度, 框中顯示的文字等等。方法是指對象的某個操作。 如讓 Textbox 成為當(dāng)前的焦點 (即光 標(biāo)移動到它上面)。事件是指對象對外部動作的響應(yīng)。 如我們用鼠標(biāo)點擊 Textbox 時, 會產(chǎn)生一個 Click 事件,改變它的值,則產(chǎn)生一個 Change 事件變量的作用域變量因為聲明的位置和方式不同,從而有不同的作用域。作用域 是指變量在多大范圍內(nèi)能被代碼識別。 可以劃分為過程級、

10、 模塊級和 全局變量。過程級變量在過程中聲明,這里過程指的是一個 Sub 或 Functi on ,也包括后面提到到屬性過程。通常用 Dim 或 Static 進(jìn)行聲明。 Dim 聲明的變量,只在該過程執(zhí)行時存在,過程結(jié)束,變量的值也 就消失了。 Static 聲明的變量稱為靜態(tài)變量,這個值在整個程序運行 期間都存在。模塊級變量對整個模塊的所有過程都有效,但對其它模塊不可用。 可以在模塊頂部聲明。聲明模塊級變量用 Private 關(guān)鍵字和直接使用 Dim 沒有區(qū)別。但推薦使用 Private 進(jìn)行聲明, 因為這樣可以方便地 與后面的全局變量區(qū)分開來。全局變量是對整個 VBA 工程的所有過程都有

11、效的變量,使用 Pu blic 關(guān)鍵字在標(biāo)準(zhǔn)模塊的頂部來聲明。在類模塊中,對變量作用域的理解要注意下面兩點:(a)由于類是生成對象的模具,每生成一個對象,相當(dāng)于產(chǎn)生 了一個副本,這個副本就是對象的“真身”,副本間是相互獨立的, 從而,模塊級的變量只作用于副本自身。(b )類模塊中使用 Public 關(guān)鍵字,只有當(dāng)對象變量是這個類的 實例時,才能被訪問。過程和函數(shù)變量、過程( Sub )、函數(shù)( Function )是我們在標(biāo)準(zhǔn)模塊中使 用的最基本的構(gòu)件,在類摸塊中,它們?nèi)匀皇亲罨竞椭匾慕巧?對于它們,你已經(jīng)再熟悉不過,之所以前面還要花這么多文字,是為 了突出它的重要,也是想讓你放松一下,

12、哦,我花了很短的時間已經(jīng) 看了這么多(我也寫了這么多?。?。過程和函數(shù)并無實質(zhì)的區(qū)別,當(dāng)需要返回值時,就使用 Functio n,如果不需要返回任何結(jié)果, 隨你的愛好,但這時推薦你使用 Sub , 因為這樣更符合微軟的本意。過程( Sub )、函數(shù)( Function )也有 作用域,在標(biāo)準(zhǔn)模塊中通過使用 Private 和 Public 關(guān)鍵字(可以省 略 Public 關(guān)鍵字,因為它是默認(rèn)的) ,可以劃分為模塊級和全局級, 以決定它是在當(dāng)前的模塊有效還是整個工程有效。同變量一樣, 在類模塊中使用 Public 關(guān)鍵字,只有當(dāng)引用對象變 量是這個類的實例時,才能被訪問通用內(nèi)部控件 Contro

13、l ( s)VBA 提供 Control 類作為一般內(nèi)部控件類型,當(dāng)使用Dim Ct As Control聲明了一個變量后,就可以將任何控件賦給該變量,而不管具體 的類型,因為在類的使用通常是處理大量相近的對象, 所以這種特性 非常有用。在實際使用時,我們多是通過容器控件的 Controls 屬性 來返回一個 Control 的集合對象。Dim Ct As ControlFor Each Ct In Me.ControlsIf TypeName(Ct) = "CommandButton" Then MsgBox Ct.CaptionNext上面這段代碼可以遍歷窗體的所有控件

14、并報告找到的命令按鈕。集合 CollectionCollection 是我們在使用類時最常用到的對象。 一個 Collection 對象代表一組相關(guān)的項目, 雖然它的成員并不被強制要求是同一類型 的的,但請記住,這通常并不能給我們帶來額外的方便,相反,我們 通常是用來收集同一類型的數(shù)據(jù)。建立集合的方法和建立其它對象一樣,如:Dim col As New Collection集合建立后,可以使用 Add 方法添加成員,用 Remove 方法刪 除成員,用 Item 方法從集合中返回特定成員。Private Sub CommandButton1_Click()Dim col As New Coll

15、ectionDim i%Dim ct As ControlFor Each ct In Me.ControlsIf Left(ct.Name, 7) = "TextBox" Then col.Add ctNext ctFor i = col.Count To 1 Step -1MsgBox " 下面刪除成員 " & col.Item(i).Namecol.Remove iNext iEnd Sub上面的代碼先將窗體上所有的 TextBox 加入到集合中, 然后再刪 除掉。 Count 屬性返回集合的成員數(shù)量, Remove 方法后面的參數(shù) 是集合

16、成員的索引號。 成員的索引號通常是按照加入的順序自然編號, 從 1 開始,但可以在加入時使用 Add 方法的參數(shù)進(jìn)行改變。 Add 方 法的完整語法是:object .Add item , key , before , afteritem 必需的。任意類型的表達(dá)式, 指定要添加到集合中的成員。key 可選的。唯一字符串表達(dá)式,指定可以使用的鍵字符串,代 替位置索引來訪問集合中的成員。before/after 可選的。表達(dá)式,指定集合中的相對位置。下面語句向集合增加一個對象 TextBox1 ,并定義該成員的關(guān)鍵 字為 tx1 。col.Add TextBox1, "tx1"

17、然后,下面兩句都可以向集合中增加一個 TextBox2 ,并把它放 在成員 TextBox1 的前面。col.Add TextBox2, , col.Countcol.Add TextBox2, , "tx1"第一句中,因為只有一個成員,所以 col.Count 也是索引號使用事件的 WithEvents 變量WithEvents 不是一個單獨的語句,為了使用對象的事件,需要 在聲明該對象時使用 WithEvents 關(guān)鍵字。例如:Dim WithEvents app As Application將上面的語句寫入 ThisWorkBook 的模塊,可以看到在通用框中 出現(xiàn)了

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

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

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

21、該類的對象時,其它工程才允許使用這個對象, 注意,僅僅是在本工程中創(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)建

22、類屬性在類模塊中寫下行代碼:Public x$過程創(chuàng)建類屬性是的,就這么簡單,通常情況下,只需要這么簡單使用 PropertyPrivate s$Public Property Get x() As Stringx = sEnd PropertyPublic Property Let x(ByVal c As String)s = cEnd Property我們可以省去上面默認(rèn)的 Public 。但看上去還是有點麻煩哦,不 僅需要兩個公共過程, 而且還要一個輔助的私有變量 s 和一個參數(shù) c。 在類模塊中, Property 過程把對屬性的讀寫分開了,說一下 Proper ty 過程的工作機制

23、, 當(dāng)標(biāo)準(zhǔn)模塊中的代碼讀取對象的屬性時, 便會觸 發(fā)存在的 Property Get 過程,或者說 Property Get 過程提供了屬 性的讀功能,同樣, Property Let 過程提供了寫屬性。這樣,上面 的兩個過程(當(dāng)然在模塊中沒有先后的要求),可以只有一個,或者 雖然兩個都有,但卻不全是 Public ,從而提供出去的屬性是只讀或只 寫(呵呵,沒見過只寫哈)。僅僅是為了提供只讀或只寫的屬性,代 碼就從一行變成了七行?!這樣的理由,你不會信服, VBA 中的類 通常是提供給我們自己使用的! 如果它確實是只讀的, 我們自覺地去 只讀就是了!我們使用 Property 過程還有其它理由

24、, 最基本的一條, 我們可以利用這個“過程”來做我們想做的事??匆豢矗篜ublic Property Let x(ByVal c As String)s = Format(c, "0000")End Property這里我們只是簡單的利用了一下, 更多的在后面你會看到。 此外, 誰會保證有一天你不使用 VB 給別人提供類呢,這個技術(shù)可是通用的。 提供一段標(biāo)準(zhǔn)模塊的測試代碼, 來看看我們上面構(gòu)建的類屬性, 你自 己試試吧。Sub aTest()Dim mc As New MyClassmc.x = "123"Debug.Print mc.xEnd Sub就

25、象我們給普通變量和對象變量賦值的方式不同一樣,對象變量 是使用 Set 賦值的。對“對象”屬性, VBA 提供了 Property Set 來 代替構(gòu)建“普通”屬性使用的 Property Let 。來看一段代碼:Private tx As ObjectProperty Get x() As ObjectSet x = txEnd PropertyProperty Set x(ByVal o As Object)Set tx = o和前面的比較一下,除了多一個 Set ,實在沒有什么不同告訴你一個小秘訣, 你可以按照 Function 去記住 Property Get 的用法,按照 Sub 去

26、記住 Property Let /Set屬性的初始值我們常常希望,當(dāng)一個對象建立的時候,它的某些屬性會被自動 賦予一個初始值, 這樣,對具有最常見的屬性值的對象可以減少重復(fù) 性的賦值工作。這需要借助于類的構(gòu)建函數(shù)來完成。在類模塊代碼窗口的“通用”框中點擊向下的小三角箭頭,選擇 “Class”,右面聲明框中可以看到兩個選項,“ Initialize ”和“ Ter minate ”,我們對它們應(yīng)該不陌生,很多對象都有這兩個事件, Ini tialize 事件當(dāng)對象建立時發(fā)生, Terminate 事件在對象對釋放時發(fā)生。 由于類是靜態(tài)存在的,它并不是真正的對象,所以在類模塊中,它們 通常被稱為構(gòu)

27、建函數(shù)和析構(gòu)函數(shù), 或構(gòu)建過程和析構(gòu)過程。 對它們的 理解和你在對象中的用法并沒有什么不同。 當(dāng)一個對象被建立時, 構(gòu) 建函數(shù)將被首先執(zhí)行,同樣,當(dāng)對象釋放后,將執(zhí)行析構(gòu)函數(shù)。下面建立 MyClass ,屬性 x初始值為” 0001 ”的全部測試代碼:類模塊 MyClass 的代碼 Option ExplicitPrivate s$End SubPublic Property Get x() As Stringx = sEnd PropertyPublic Property Let x(ByVal c As String)s = cEnd PropertyPrivate Sub Class_I

28、nitialize()s = "0001"End Sub標(biāo)準(zhǔn)模塊 1 的代碼 Option ExplicitSub aTest()Dim mc As New MyClassDebug.Print mc.x隱者為你揭開了第一層面紗,你隱約已看到她美麗的面厐,雖然還不是很清晰,但你知道,早晚會的創(chuàng)建類方法放松一下,請拿出你家的紫砂壺,泡上一壺好茶,聽我給你將類的方法的故事,你的茶品完了,我的故事也差不多就講完了。1 構(gòu)建類的方法其實就是在類模塊中寫公共的 Sub 和 Function現(xiàn)在我們給前面提到的 MyClass 創(chuàng)建一個方法 PutIntoActiveCell ,功能是

29、將 x 屬性值寫入活動單元格。Public x$Sub PutIntoActiveCell()ActiveCell = xEnd Sub在標(biāo)準(zhǔn)模塊中用下面的代碼測試一下:Sub aTest()Dim mc As New MyClassmc.x = "abc"mc.PutIntoActiveCellEnd Sub這是本回要告訴你的全部嗎?你還沒有開始品茶吧?就這樣了 結(jié)束?這是最重要和基本的,但卻不是全部。你是否有一種感覺,但你不能清楚地說出來? 端起你可愛的茶 杯,品一口茶,我們繼續(xù)。類的方法環(huán)境借用廣為眾知的一個名詞“數(shù)據(jù)環(huán)境”,雖然不準(zhǔn)確,但我實在想不出更好的稱謂來代替

30、, 姑且這么叫吧。稍后你就會知道它的含義。類可以象 VBA 提供給我們的很多標(biāo)準(zhǔn)類一樣風(fēng)光無限,所有的 程序設(shè)計者都在工程中使用它, 但更多時候, 我們所構(gòu)建的類只在特 定的環(huán)境下被使用, 類的方法環(huán)境是指包括類所在工程的其它成員在 內(nèi)的,可以調(diào)用的資源的集合。工作簿、工作表、窗體或其它,在類 模塊中, 你可以象在標(biāo)準(zhǔn)模塊中一樣操作它們, 千萬不要因為換成了 類模塊而產(chǎn)生任何疑慮, 作為類的創(chuàng)建者, 你要讓類模塊中的代碼象 你在標(biāo)準(zhǔn)模塊中一樣親近它們, 只要你認(rèn)為必要。 脫離了方法環(huán)境的、 謹(jǐn)小慎微的、 封閉的類實在沒有什么意義。 如果你預(yù)期方法環(huán)境在運 行時可能會有變化, 你要事先預(yù)知它們并

31、象在標(biāo)準(zhǔn)模塊中一樣使用恰當(dāng)?shù)拇胧?比如你不能確定運行時活動工作表的名稱 (但你確定屆時 會是一個工作表),你可以使用 ActiveSheet 。我反復(fù)說“和標(biāo)準(zhǔn)模塊一樣”,就是想告訴你在類模塊中創(chuàng)建方 法時,對工程中其它成員的操作, 和你已經(jīng)熟悉的標(biāo)準(zhǔn)模塊中的方式 的實在沒有什么不同, 這一原則適用于類模塊中所有代碼 (也許叫代 碼環(huán)境更準(zhǔn)確些),而不僅僅是構(gòu)建方法的代碼?,F(xiàn)在,你知道了,你剛才的感覺到的是開放的方法環(huán)境。是的, 以后你會更深地體會到,作為好的提供者,開放的思維有多重要方法的兄弟成員事件類方法的執(zhí)行需要在代碼中以顯性的方式指定, 象上面的 mc.Pu tIntoActiveC

32、ell ,有時候,當(dāng)最終操作者觸發(fā)類對象成員(屬性)的 某個事件,需要在事件發(fā)生時產(chǎn)生一系列的操作,這時,我們要運用 成員事件。 成員事件和方法都是類提供的一系列代碼的操作, 倆兄弟 的區(qū)別在于,成員事件無法也不必再由代碼顯性調(diào)用。我們來看一個具有普遍意義的事例。重要例窗體 UserForm1 上有 5 個 CommandButton 控件(名稱分別 為默認(rèn) CommandButton 1- CommandButton 5 )和 1 個 TextB ox 控件(名稱為 TextBox1 )。要求當(dāng)各個 CommandButton 控件 被點擊時,它的按鈕文字( Caption )會寫入 Tex

33、tBox1 。如果不用類,我們需要為 5 個 CommandButton 控件分別寫 5 個相同的 Click 事件代碼。如 :Private Sub CommandButton 1_Click()TextBox1 = CommandButton 1.CaptionEnd Sub下面是用類的成員事件方法的代碼:類模塊 Cmds 的代碼Option ExplicitPublic WithEvents cmd As CommandButtonPrivate Sub cmd_Click()UserForm1.TextBox1 = cmd.CaptionEnd Sub窗體 UserForm1 的代碼O

34、ption ExplicitDim co As New CollectionPrivate Sub UserForm_Initialize()Dim i%Dim myc As CmdsFor i = 1 To 5Set myc = New CmdsSet myc.cmd = Me.Controls("CommandButton" & i)co.Add mycNext iSet myc = NothingEnd Sub仔細(xì)玩味上例的每一行代碼,直至品完你壺中的茶。呵呵,因為 它實在很有用。 最后提一下 Friend 關(guān)鍵字,雖然在 VBA 中幾乎沒有 什么用, 但如果

35、有一天你要制作 ActiveX 部件,可能會用到它。 之所 以要有 Friend 關(guān)鍵字,是因為類的私有部分在類模塊外是不可見的, 但有時卻需要從外面訪問這些私有部分,這時,可以使用 Friend 關(guān) 鍵字使屬性和方法成為“友元成員”。友元成員在本工程中相當(dāng)于 P ublic ,但在工程外,它仍是 Private 。隱者為你揭去了第二層面紗,你幾乎已看清她美麗的面龐,她帶 著甜蜜的微笑,似乎在問:什么才是最美的期待?創(chuàng)建類事件在 VBA 中,因為我們既是提供者,也是使用者,所以通過良好 地構(gòu)建類的屬性和方法, 已可以滿足我們需要全部的要求。 我不再去 解釋這個觀點,在本回后你自然會明白。從這個

36、意義上講,創(chuàng)建類事 件實在沒有必要。 唯一的遺憾是, 我們沒有體會到作為創(chuàng)建者的全部 樂趣,標(biāo)準(zhǔn)類給我們提供了各種事件,當(dāng)然希望自己也可以做到,想 象中這應(yīng)當(dāng)是一件激動人心的事, 所以,追求快樂是創(chuàng)建類事件的重 要理由,另一個理由,前面已經(jīng)提到?;氐角懊嫖覀兊?MyClass 類,我們將 x 屬性改名為 Value 屬性, 雖然對屬性、方法以及事件的命名, VBA 沒有特別的限制,但建議 您不要象我前面那樣,隨便取一個 x,可能的話,要盡量和標(biāo)準(zhǔn)類的 成員(屬性、方法以及事件)名稱相一致。現(xiàn)在我們?yōu)椤笆褂谩闭咛峁┮粋€“ Change ”事件,不錯,我們 給它取名為“ Change ”,而不再是

37、隨意的“ y”或其它(雖然也可 以),這樣,我也不用解釋這個事件的用意了,呵呵。為了做到這一 點,看看我們應(yīng)該做什么。1第一步:使用 Event 語句聲明事件看一下類模塊中現(xiàn)在的代碼:Option ExplicitPublic Event Change(ByRef Cancel As Boolean)Private s$Public Property Get Value() As StringValue = sEnd PropertyPublic Property Let Value(ByVal c As String)s = cEnd PropertyPrivate Sub Class_In

38、itialize()s = "abc" 初始值End Sub和前面的代碼比較,多出了一句:Public Event Change(ByRef Cancel As Boolean)這就是 Event 語句,只此一句,我們已經(jīng)為我們的類聲明(我想 使用“注冊”一詞是不是更妥切)了一個事件 Change 。在看 Event 語句產(chǎn)生的效果前,先來看它的特性:(1)為了聲明事件, Event 總是 Public 的,這好理解吧。(2)事件可以不帶參數(shù),如 Public Event Change() ,也可以 帶參數(shù),如我們上面給出的,但參數(shù)不能是命名參數(shù),可選參數(shù)或數(shù) 組參數(shù)。這里

39、我只解釋一下命名參數(shù)的含義。我們知道,事件可以因 特定的用戶事件而觸發(fā), 也可以在代碼中象方法一樣指定執(zhí)行, 如下 面的 CommandButton1_Click :Private Sub CommandButton2_Click()CommandButton1_ClickEnd Sub但在調(diào)用對象的方法時我們通常喜歡這樣的方式:Selection.Sort Key1:=Range("A2"), Order1:=xlAscending這里 Key1 、Order1 就是命名參數(shù),命名參數(shù)的好處是我們不必 記住它們的次序,調(diào)用時直接以名稱和冒號后加等于號指定它的值, 但對事件

40、的調(diào)用卻不允許這樣。3)事件沒有返回值現(xiàn)在我們看一下, Event 為我們做了什么。建立一窗體 UserForm1 ,添加一個 TextBox 控件(名稱為 Text Box1 ),兩個 CommandButton 控件(名稱為 CommandButton 1 和 CommandButton2 ), CommandButton1 的 Caption 設(shè)置 為“賦值”, CommandButton2 的 Caption 設(shè)置為“讀值”,窗 體的代碼如下:Option ExplicitDim WithEvents mc As MyClassPrivate Sub CommandButton1_Cl

41、ick()mc.Value = TextBox1 ' 賦值End SubPrivate Sub CommandButton2_Click()MsgBox "mc 當(dāng)前的值為 " & mc.Value '讀值End SubPrivate Sub UserForm_Initialize()Set mc = New MyClassEnd Sub上面這段代碼實現(xiàn)的是, 當(dāng)點擊 CommandButton1 時便會將 T extBox1 的值賦給 mc 的 Value ,當(dāng)點擊 CommandButton2 時便 會顯示 mc 當(dāng)前的 Value 值。來運行一

42、下這個窗體, 先點擊 CommandButton2 ,此時顯示“ a bc”,是 mc 的初始值,然后在 TextBox1 輸入“ 123 ”,點擊 Co mmandButton1 ,再點擊 CommandButton2 ,顯示“ 123 ”,說 明賦值成功了。呵呵,忘了,我們要做什么了!現(xiàn)在,請從 UserForm1 代碼窗 口的“通用”框中選擇 mc ,哇!我們聲明的事件在右邊“聲明”框 中已經(jīng)出現(xiàn)了!我們定義這個事件是希望當(dāng) mc 的值改變時響應(yīng)的,現(xiàn)在就迫不 及待地給它寫一句代碼吧:Private Sub mc_Change(ByRef Cancel As Boolean)If Msg

43、Box(" 要改變 mc 的值嗎 ?", vbYesNo) = vbNo Then Cancel = TrueEnd Sub上面這句代碼你不會陌生吧,希望當(dāng)用戶選擇了在改變時給用戶 一個確認(rèn)的機會。但是,現(xiàn)在點擊 CommandButton1 ,卻不會給你選擇的機會, 我們還有一步?jīng)]有做。第二步:使用 RaiseEvent 語句引發(fā)事件聲明了事件后,我們要做的,便是找到所有與事件發(fā)生關(guān)聯(lián)的地 方,使用 RaiseEvent 語句引發(fā)事件,這里引發(fā)的含義相當(dāng)于 Call , 就是調(diào)用用戶在事件中寫的代碼。在本例中,只有一個地方,就是 P roperty Let Value 過

44、程中:Dim chyn As BooleanRaiseEvent Change(chyn)s = "abc"通過傳遞回的 chyn ,決定是否執(zhí)行后面的賦值語句。下面就是添加了 RaiseEvents 語句后的類模塊的代碼:Option ExplicitPublic Event Change(ByRef Cancel As Boolean)Private s$Public Property Get Value() As StringValue = sEnd PropertyPublic Property Let Value(ByVal c As String)Dim chyn As BooleanRaiseEvent Change(chyn)If chyn Then Exit Propertys = cEnd PropertyPrivate Sub Class_Initialize()End Sub現(xiàn)在你可以去運行你的窗體了,我們要的效果應(yīng)該是達(dá)到了吧。為了便于你調(diào)試,下面給出窗體的全部代碼:Option ExplicitDim WithEvents mc As MyClassPrivate Sub CommandButton1_Click()mc.Value = TextBox1 ' 賦值End SubPrivate Sub Comman

溫馨提示

  • 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論