


下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、實用標(biāo)準(zhǔn)文案Excel 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. 個完整的類實例&未完的結(jié)尾什
2、么是類在我們身邊,相同或相似的物品無處不在,從生活用品,到工業(yè)產(chǎn)品,通常它們都是由同一個可以稱為“模具”的 東西生產(chǎn)出來。理解類,一般要先從對象談起,但由于從不同的角度,有不 同的理解,從而也有不同的關(guān)于類的定義,本文不去探討一 個完整并且公認(rèn)的類概念,在這一部分后,只要你有一個基 本的判斷并且在遇到時知道是類就可以了。在上面的這個例 子中,一個“模具”就是一個“類”,而由它生產(chǎn)出的每一 個產(chǎn)品,就是一個“對象”??聪旅娴?VBA語句:Dim tx1 As Textbox 不用解釋它的意思吧,這里我們用到一個類 Textbox 定義了 一個對象 tx1 ,再來看:Dim tx1 As Text
3、boxDim tx2 As Textbox又定義了一個對象 tx2 ,如果你不嫌煩, 我還可以繼續(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)建
4、我們自己的類,姑且可稱之為自定義類。這需 要在VBE下,通過插入類模塊,然后向類模塊中寫入代碼來 完成。這就是你常常聽說的類,本文的主題就是這個包含代 碼的模塊!通過這個模塊,可以提供給我們一個和VBA提供給我們的諸如 Textbox 功能性質(zhì)完全相同的類,然后,再由 我們自己象使用 Textbox 一樣使用! 類是一個隱者,她把自己藏在所有模塊的最后,甚至在多數(shù) 情況,她從不出場?,F(xiàn)在,她掛著神秘的微笑,向你走來, 你要拒絕嗎為什么要學(xué)習(xí)類模塊類通常被認(rèn)為是學(xué)習(xí) VBA的難點之一,之所以如此,因為相 對于制造一個標(biāo)準(zhǔn)模塊或用戶窗體,我們可以找到的類的學(xué) 習(xí)資源少之又少,甚至很多 VB的書籍也
5、只有繆繆字語(在 后面的預(yù)備知識,我們再提另一個重要的原因)。從技術(shù)角 度上看,類的構(gòu)建,不象窗體,VBA的類也不象有些語言提供了可視的設(shè)計界面,感性上那樣直接,隱者!她是不可視的設(shè)計,所有的構(gòu)建都是通過在類模塊中寫代碼來實現(xiàn)的。1學(xué)習(xí)是一種興趣的追求俗語云: 學(xué)的千千萬, 用的有幾何?又曰: 書到用時方恨少。 林語堂先生將做學(xué)問劃分為三重境界,第二重說“為伊消得 人憔悴,衣帶漸寬終不悔”,大多數(shù)朋友,包括本人,都不 是專業(yè)程序員,學(xué)習(xí)程序只是一種興趣和愛好,就好象有人 喜歡修煉網(wǎng)游一樣,對喜歡程序的人,不斷地學(xué)習(xí)和提高, 也是一種追求優(yōu)秀的態(tài)度,并且樂意享受這個追求的過程。 模塊、控件、鏈接
6、庫和類構(gòu)成軟件工程開發(fā)的四大技術(shù),而 類技術(shù)是控件和鏈接庫技術(shù)的基礎(chǔ),我們不得不學(xué)。2類有什么用 如你前面看到的我們使用 Textbox 類,類可以創(chuàng)建大量性質(zhì) 相近的對象,減輕我們的程序量,簡潔代碼并提高效率。 類定義后,在其它模塊中使用時,我們就可以暫時忘記或不 必考慮它內(nèi)部復(fù)雜的細(xì)節(jié),讓我們變得輕松,VBA雖然不能真正封裝類的形式,但在這里,我們可以封裝它的概念。 這并不是類的全部好處,其它的,留著朋友們用的時候慢慢 體會吧。類掛著神秘的微笑,已經(jīng)走到你的大門口,開門迎接她吧, 你還等什么?類的預(yù)備知識廣義上講,所有 VBA的知識,包括語句、函數(shù)以及為我們提供的標(biāo)準(zhǔn)類甚至第三方的資源都可
7、以在類中被使用。本文無 法也不準(zhǔn)備逐一探討,這里只說一些最密切最基本的,但即 使這樣,筆者仍然不能把這些點的知識都寫到,甚至因為對 問題解釋清晰或符合邏輯的需要,采用非規(guī)范的表述,對專 門問題的全面理解,請讀者注意參考有關(guān)標(biāo)準(zhǔn)幫助文檔并加 以甄別。1從構(gòu)建者的角度理解對象上一回我們提到,類被認(rèn)為是 VBA難點還有一個原因,這就 是我們的思想! VBA提供了大量的現(xiàn)成的類,我們幾乎不再 需要去構(gòu)建自己的類,這種結(jié)果,我們熟練地習(xí)慣了從使用 者的角度去理解類的實例:對象,包括它的屬性、方法和 事件。但是,現(xiàn)在你還要嘗試做一個提供者,這和你作為使 用者時的思考方法是完全不同的,甚至是革命性的。這種角
8、 色的轉(zhuǎn)位是痛苦的,它需要你放棄你原本可以自豪地解釋出 對象以及它的屬性、方法、事件的定義,它們原本是如此邏 輯地被劃分,如此清晰,但現(xiàn)在,類模塊中的一切,彼此交 織,你會發(fā)現(xiàn)它們都模糊了!是需要你忘掉所有固執(zhí)的“招 勢”的時候了,當(dāng)你心中無劍時,轉(zhuǎn)位也就完成了,隱者變 得清晰了,她是如此美麗。且慢,在你完全忘掉前,讓我們 最后再看一眼它們的樣子,呵呵,如果你實在忘不掉,你就 提醒一下自己構(gòu)建者的身份吧。下面是通常情況下關(guān)于對 象、屬性、方法、事件的基本表述,如果你以前沒了解過, 則應(yīng)當(dāng)找些資料先認(rèn)真地理解它們,然后再按照上面的提示 去做。對象是由類創(chuàng)建的一個實例,它是類的實體化。 對象的引用
9、和操作被邏輯上劃分為不重疊的三個部分: 屬性是指對象的特性。以前面的 Textbox 為例,有長度,高 度,框中顯示的文字等等。方法是指對象的某個操作。 如讓 Textbox 成為當(dāng)前的焦點 (即 光標(biāo)移動到它上面)。事件是指對象對外部動作的響應(yīng)。如我們用鼠標(biāo)點擊 Textb ox 時,會產(chǎn)生一個 Click 事件,改變它的值,則產(chǎn)生一個 C hange 事件變量的作用域變量因為聲明的位置和方式不同,從而有不同的作用域。作 用域是指變量在多大范圍內(nèi)能被代碼識別。可以劃分為過程 級、模塊級和全局變量。過程級變量在過程中聲明,這里過程指的是一個Sub 或 Function ,也包括后面提到到屬性過
10、程。通常用Dim 或 Static進(jìn)行聲明。 Dim 聲明的變量,只在該過程執(zhí)行時存在,過程 結(jié)束, 變量的值也就消失了。 Static 聲明的變量稱為靜態(tài)變 量,這個值在整個程序運(yùn)行期間都存在。 模塊級變量對整個模塊的所有過程都有效,但對其它模塊不 可用??梢栽谀K頂部聲明。聲明模塊級變量用 Private 關(guān) 鍵字和直接使用 Dim 沒有區(qū)別。但推薦使用 Private 進(jìn)行聲 明,因為這樣可以方便地與后面的全局變量區(qū)分開來。全局變量是對整個 VBA工程的所有過程都有效的變量,使用 Public 關(guān)鍵字在標(biāo)準(zhǔn)模塊的頂部來聲明。在類模塊中,對變量作用域的理解要注意下面兩點:(a) 由于類是生
11、成對象的模具,每生成一個對象,相當(dāng)于 產(chǎn)生了一個副本,這個副本就是對象的“真身”,副本間是 相互獨立的,從而,模塊級的變量只作用于副本自身。(b) 類模塊中使用Public關(guān)鍵字,只有當(dāng)對象變量是這個 類的實例時,才能被訪問。過程和函數(shù)變量、過程(Sub)、函數(shù)(Function )是我們在標(biāo)準(zhǔn)模塊中使用的最基本的構(gòu)件,在類摸塊中,它們?nèi)匀皇亲罨竞?重要的角色。對于它們,你已經(jīng)再熟悉不過,之所以前面還 要花這么多文字,是為了突出它的重要,也是想讓你放松一 下,哦,我花了很短的時間已經(jīng)看了這么多(我也寫了這么 多!)。過程和函數(shù)并無實質(zhì)的區(qū)別,當(dāng)需要返回值時,就使用 Fun ction ,如果
12、不需要返回任何結(jié)果,隨你的愛好,但這時推 薦你使用Sub,因為這樣更符合微軟的本意。過程(Sub)、函數(shù)( Function )也有作用域,在標(biāo)準(zhǔn)模塊中通過使用 Pri vate 和 Public 關(guān)鍵字(可以省略 Public 關(guān)鍵字, 因為它是 默認(rèn)的),可以劃分為模塊級和全局級,以決定它是在當(dāng)前 的模塊有效還是整個工程有效。同變量一樣,在類模塊中使用 Public 關(guān)鍵字,只有當(dāng)引用 對象變量是這個類的實例時,才能被訪問通用內(nèi)部控件 Control ( s)VBA提供Control類作為一般內(nèi)部控件類型,當(dāng)使用Dim Ct As Control聲明了一個變量后,就可以將任何控件賦給該變量
13、,而不管 具體的類型,因為在類的使用通常是處理大量相近的對象, 所以這種特性非常有用。在實際使用時,我們多是通過容器 控件的 Controls 屬性來返回一個 Control 的集合對象。Dim Ct As ControlFor Each Ct In Me.ControlsIf TypeName(Ct) = "CommandButton" Then MsgBox Ct.CaptionNext上面這段代碼可以遍歷窗體的所有控件并報告找到的命令 按鈕。集合 CollectionCollection 是我們在使用類時最常用到的對象。一個 Colle ction 對象代表一組相關(guān)的
14、項目,雖然它的成員并不被強(qiáng)制 要求是同一類型的的,但請記住,這通常并不能給我們帶來 額外的方便,相反,我們通常是用來收集同一類型的數(shù)據(jù)。建立集合的方法和建立其它對象一樣,如:Dim col As New Collection集合建立后,可以使用Add方法添加成員,用Remove方法刪除成員,用 Item 方法從集合中返回特定成員。Private Sub CommandButton1_Click()Dim col As New CollectionDim i%Dim ct As ControlFor Each ct In Me.ControlsIf Left(ct.Name, 7) = &quo
15、t;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ù)是集合成員的索引號。成員的索引號通常是按照加入的順序自然編號,從 1開始,但可以在加入時使用 Add方 法的參數(shù)進(jìn)行改變。Add方法的完整語法是:object .Add item
16、 , key , before , afteritem 必需的。任意類型的表達(dá)式,指定要添加到集合中的成員。key 可選的。 唯一字符串表達(dá)式, 指定可以使用的鍵字符串, 代替位置索引來訪問集合中的成員。before/after 可選的。表達(dá)式,指定集合中的相對位置。 下面語句向集合增加一個對象 TextBox1 ,并定義該成員的關(guān) 鍵字為 tx1 。col.Add TextBox1, "tx1"然后, 下面兩句都可以向集合中增加一個 TextBox2 ,并把它 放在成員 TextBox1 的前面。col.Add TextBox2, , col.Countcol.Add T
17、extBox2, , "tx1"第一句中,因為只有一個成員,所以col.Count也是索引號使用事件的WithEvents變量WithEvents不是一個單獨的語句,為了使用對象的事件,需要在聲明該對象時使用WithEvents關(guān)鍵字。例如:Dim WithEvents app As Application將上面的語句寫入 ThisWorkBook的模塊,可以看到在通用 框中出現(xiàn)了一個變量app:此主題相關(guān)圖片如下:S Microsofl. Visual Basic - Book! - ThisWorkbook (代碼)婦 丈件)編輯 視圈邊 插入 格式辺 調(diào)試 運(yùn)行
18、74; 工具 外接程存® I-題 ¥BA?raject 3onkl)j込 licraEoft Excel 對象Sh&etl (Sh&etl)SkeetS (Shtet?)Sheets CSheet) Thi WorkbookWW«)聲明)Option ExplicitDim Vfi tKEveiits 電pp Am Appliation冋3模塊戰(zhàn)模塊1iF、類梗塊占類1屋牲-1 hi曲決Moi|TKi sf orkboa Workbook * ;按字魚序I按分類序佟稱)Thi sc-rkboolc 生AcceptLabsl eI Pals &
19、; AutoUpdateFre0 ChangeKi stcry0在通用框選擇app后,左邊的聲明框便會顯示 app的事件。此主題相關(guān)圖片如下:J J羽丨勺程-VBAProject縄文件歸編輯(1)視閣插入格式辺調(diào)試運(yùn)行® 工具外接程序)i d VBAPrnj ect (Boakl)F3 巴? Microsoft Ixcel 對象O Sheetl Gheetl)S Sheets (Sheet?) 雹)Sheet3 (SheetS) Q Thi sWcrkboflkL=l - i檯塊我模塊1TH類模塊類1岡u Hi hmlfl片險瞪髦MR|ThisVorkboo arkbook按字母序|
20、按分類序丨名稱)A.cceptL.belI FalseAutoUpdateFr e 0ChangeHi story 0<* c d cn 41 iri二2 » z丿址憩蘭"曽®行id “列1需要注意的是,使用WithEvents只是聲明了對象變量,而并不實際生成對象,為了生成真實的對象,你仍然需要在聲 明后向生成其它對象一樣,使用Set語句進(jìn)行指定。此外,WithEvents變量不能是通用類變量如Object,而必須指定類名,也不能把 WithEvents變量聲明為 As New。不能在標(biāo) 準(zhǔn)模塊中使用 WithEvents初識類模塊現(xiàn)在,請打開你的 VBE
21、主菜單-插入-類模塊。插入了一個類模塊,也就建立了一個類。類模塊的名字就是類的名字。你現(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)圖片如下:Micros Ft Visual 陰引 t - Bookl -類 1 (代瑪)繩文件漏輯(T 視團(tuán)插入格式Q)調(diào)試助運(yùn)行®
22、 工具外接程序 1越Sheet】&he泌打 彎 Sheets (SheetS) 團(tuán) 1 Sh&et3 (SheetS)Q ThisWorkbook T H檯塊懸模塊1 白由牌塊丿叱鬆宜歲 o行3,列堆Option Esplicitdim xx負(fù)呂七 ImlMaps越幺XmlHameEpace4 XmlNam&spaces XmlSchema XmlSchemasL XgT) <(名稱)Instinc 1 ng 1 - Private碣豳名I類i類t類檯塊轅字母序I植佔蘭卓你或許已經(jīng)注意到,在名字下面,只有一個屬性:Instancing,其值也只有兩個選項:Priv
23、ate 和PublicNotCreatable 。事實上,你完全可以忽略這個Instancing ,就象你完全忽略 條件編譯指令一樣,因為在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è)
24、置為 PublicNotCreatable 時,只有在自己的工程創(chuàng)建 了該類的對象時,其它工程才允許使用這個對象,注意,僅 僅是在本工程中創(chuàng)建的對象,而不能用她在其它工程中創(chuàng)建 對象。隱者已經(jīng)來到你的身邊,透過薄薄的面紗,你似乎已看到她 神秘的微笑。站起身來,走過去吧!創(chuàng)建類屬性讓我們想一下作為類的使用者時,我們是如何操作對象的屬 性的,對象屬性的操作不外乎讀和寫兩種。當(dāng)我們要給對象 的某個屬性賦值時,我們會:TextBox1.Text= ” abc ”當(dāng)我們要讀取對象的屬性時,S= TextBox1.Text現(xiàn)在,看看作為類的提供者需要怎樣做。我們將“類 1”改名為“ MyClass ”并為
25、它創(chuàng)建一個名稱為 x 的字符型屬性。1使用 Public 變量創(chuàng)建類屬性在類模塊中寫下行代碼:Public x$ 是的,就這么簡單,通常情況下,只需要這么簡單使用 Property 過程創(chuàng)建類屬性Private 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
26、 過程把對屬性的讀 寫分開了,說一下 Property 過程的工作機(jī)制,當(dāng)標(biāo)準(zhǔn)模塊 中的代碼讀取對象的屬性時,便會觸發(fā)存在的 Property Ge t 過程, 或者說 Property Get 過程提供了屬性的讀功能, 同 樣, Property Let 過程提供了寫屬性。這樣,上面的兩個過 程(當(dāng)然在模塊中沒有先后的要求),可以只有一個,或者 雖然兩個都有, 但卻不全是 Public ,從而提供出去的屬性是 只讀或只寫(呵呵,沒見過只寫哈)。僅僅是為了提供只讀 或只寫的屬性,代碼就從一行變成了七行?!這樣的理由, 你不會信服, VBA 中的類通常是提供給我們自己使用的! 如 果它確實是只讀
27、的,我們自覺地去只讀就是了!我們使用 roperty 過程還有其它理由,最基本的一條,我們可以利用 這個“過程”來做我們想做的事??匆豢矗?Public 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&q
28、uot;Debug.Print mc.xEnd Sub 就象我們給普通變量和對象變量賦值的方式不同一樣,對象 變量是使用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 = oEnd Property 和前面的比較一下,除了多一個Set ,實在沒有什么不同。告訴你一個小秘訣, 你可以按照
29、Function 去記住 Property Get的用法,按照 Sub去記住Property Let /Set 。屬性的初始值我們常常希望,當(dāng)一個對象建立的時候,它的某些屬性會被 自動賦予一個初始值,這樣,對具有最常見的屬性值的對象 可以減少重復(fù)性的賦值工作。這需要借助于類的構(gòu)建函數(shù)來 完成。在類模塊代碼窗口的“通用”框中點擊向下的小三角箭頭, 選擇“ Class ”,右面聲明框中可以看到兩個選項,“ Initi alize ”和“ Terminate ”,我們對它們應(yīng)該不陌生,很多對 象都有這兩個事件, Initialize 事件當(dāng)對象建立時發(fā)生, T erminate 事件在對象對釋放時發(fā)
30、生。由于類是靜態(tài)存在的, 它并不是真正的對象,所以在類模塊中,它們通常被稱為構(gòu) 建函數(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$Public Property Get x() As Stringx = sEnd PropertyPublic Property Let x(ByVal c As String)s = cEn
31、d PropertyPrivate Sub Class_Initialize()s = "0001"End Sub 標(biāo)準(zhǔn)模塊 1 的代碼 Option ExplicitSub aTest()Dim mc As New MyClassDebug.Print mc.xEnd Sub 隱者為你揭開了第一層面紗,你隱約已看到她美麗的面厐, 雖然還不是很清晰,但你知道,早晚會的創(chuàng)建類方法放松一下,請拿出你家的紫砂壺,泡上一壺好茶,聽我給你 將類的方法的故事,你的茶品完了,我的故事也差不多就講 完了。1構(gòu)建類的方法其實就是在類模塊中寫公共的Sub 和 Function現(xiàn)在我們給前面提到
32、的 MyClass 創(chuàng)建一個方法 PutIntoActi veCell ,功能是將 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ù)。類的
33、方法環(huán)境借用廣為眾知的一個名詞“數(shù)據(jù)環(huán)境”,雖然不準(zhǔn)確,但我 實在想不出更好的稱謂來代替,姑且這么叫吧。稍后你就會 知道它的含義。類可以象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)小慎微的、封閉的類實在沒有什么意
34、義。如果你預(yù)期方法 環(huán)境在運(yùn)行時可能會有變化,你要事先預(yù)知它們并象在標(biāo)準(zhǔn) 模塊中一樣使用恰當(dāng)?shù)拇胧?,比如你不能確定運(yùn)行時活動工 作表的名稱(但你確定屆時會是一個工作表),你可以使用 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í)行需要在代碼中以顯性
35、的方式指定,象上面的 m c.PutIntoActiveCell ,有時候,當(dāng)最終操作者觸發(fā)類對象 成員(屬性)的某個事件,需要在事件發(fā)生時產(chǎn)生一系列的 操作,這時,我們要運(yùn)用成員事件。成員事件和方法都是類 提供的一系列代碼的操作,倆兄弟的區(qū)別在于,成員事件無 法也不必再由代碼顯性調(diào)用。我們來看一個具有普遍意義的事例。 重要例 窗體 UserForm1 上有 5 個 CommandButton 控件(名稱分別為 默認(rèn) CommandButton 1- CommandButton 5)和 1 個 TextBox 控件(名稱為 TextBox1 )。要求當(dāng)各個 CommandButton 控件 被
36、點擊時,它的按鈕文字( Caption )會寫入 TextBox1 。如果不用類,我們需要為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
37、Sub窗體 UserForm1 的代碼Option 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 = NothingVBEnd Sub 仔細(xì)玩味上例的每一行代碼,直至品完你壺中的茶。呵呵, 因為它實在很有用。最后提一下 Friend 關(guān)鍵字,
38、雖然在 A 中幾乎沒有什么用, 但如果有一天你要制作 ActiveX 部件, 可能會用到它。之所以要有 Friend 關(guān)鍵字,是因為類的私 有部分在類模塊外是不可見的,但有時卻需要從外面訪問這 些私有部分,這時,可以使用 Friend 關(guān)鍵字使屬性和方法 成為“友元成員”。友元成員在本工程中相當(dāng)于 Public ,但 在工程外,它仍是 Private 。 隱者為你揭去了第二層面紗,你幾乎已看清她美麗的面龐, 她帶著甜蜜的微笑,似乎在問:什么才是最美的期待?創(chuàng)建類事件在VBA中,因為我們既是提供者,也是使用者,所以通過良 好地構(gòu)建類的屬性和方法,已可以滿足我們需要全部的要 求。我不再去解釋這個觀
39、點,在本回后你自然會明白。從這 個意義上講,創(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”事件,不錯,我們給它取名為“ Chan
40、ge”,而不再是隨意的“ 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
41、Sub Class_Initialize()s = "abc" 初始值End Sub和前面的代碼比較,多出了一句:Public Event Change(ByRef Cancel As Boolean)這就是 Event 語句,只此一句, 我們已經(jīng)為我們的類聲明 (我 想使用“注冊” 一詞是不是更妥切)了一個事件Changeo在看 Event 語句產(chǎn)生的效果前,先來看它的特性:(1)為了聲明事件,Event總是Public的,這好理解吧。( 2)事件可以不帶參數(shù),如 Public Event Change() ,也可以帶參數(shù),如我們上面給出的,但參數(shù)不能是命名參數(shù),可選參數(shù)
42、或數(shù)組參數(shù)。這里我只解釋一下命名參數(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)用時直接以名稱和冒號后加等于號 指定它的值,
43、但對事件的調(diào)用卻不允許這樣。( 3)事件沒有返回值?,F(xiàn)在我們看一下, Event 為我們做了什么。建立一窗體 UserForml,添加一個 TextBox控件(名稱為 Te xtBoxI ),兩個 CommandButton控件(名稱為 CommandButt on1 和 CommandButton2), CommandButton1 的 Caption 設(shè)置 為“賦值”,CommandButton2的Caption設(shè)置為“讀值”, 窗體的代碼如下:Option ExplicitDim WithEvents mc As MyClassPrivate Sub CommandButton1_Cli
44、ck()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)點擊CommandButtonl時便會將TextBoxl 的值賦給 me的 Value,當(dāng)點擊 CommandButton2時 便會顯示me當(dāng)前的Value值。來運(yùn)行一下這個窗體,先點擊Com
45、mandButton2,此時顯示“ a be”,是me的初始值,然后在 TextBox1輸入“ 123”,點擊 CommandButtonl,再點擊 CommandButton2 顯示 “ 123” ,說明賦值成功了。呵呵,忘了,我們要做什么了!現(xiàn)在,請從 UserForml代碼 窗口的“通用”框中選擇me,哇!我們聲明的事件在右邊 “聲 明”框中已經(jīng)出現(xiàn)了!此主題相關(guān)圖片如下:UserFormlMicrosoft Visual Basic = BookLmIs -垮 文件 編輯® 觀圖世)插入 格式 調(diào)試 運(yùn)行® 工具 外按程序國毎oa齟丨刁6丨工三p M國乂程會爭處丨金
46、丨行皿列-:題 VBAJfrojtct (Bookl.xls)-Microsoft Excel 對隊題 Sheetl (Sheetl)蜀 ShetS (Shet3) 窗 ThisWcrkbookS-已窗體圉 UserFormlEl - &類模塊丈1 NlyClasDjjn. WithEvents me As N)v)21assFr iv<te Sub CommazidBu.11on 1 Cl i ck 0 me. ¥alu& 二 TextBoxl ' RS值End Sub =_ ” Private Sub ConumaiiiBKitton2_Cli ck
47、 0"me當(dāng)前的值為"& me. Value,讀值 End EubFr £va tg Suber Formal ai ti ali zeSet me - New NlyClassEnd SubPrivate Sub mc_Chang(SyRe£ Cancel Boolean)End SubHUinidhlE我們定義這個事件是希望當(dāng)me的值改變時響應(yīng)的,現(xiàn)在就迫不及待地給它寫一句代碼吧:Private Sub mc_Change(ByRef Cancel As Boolean)If MsgBox(" 要改變 mc的值嗎?", v
48、bYesNo) = vbNo ThenCancel = TrueEnd Sub上面這句代碼你不會陌生吧,希望當(dāng)用戶選擇了在改變時給 用戶一個確認(rèn)的機(jī)會。但是,現(xiàn)在點擊 CommandButtonl,卻不會給你選擇的機(jī)會, 我們還有一步?jīng)]有做。使用 RaiseEvent 語句引發(fā)事件第二步:使用 RaiseEvent 語句引發(fā)事件 聲明了事件后,我們要做的,便是找到所有與事件發(fā)生關(guān)聯(lián) 的地方,使用 RaiseEvent 語句引發(fā)事件,這里引發(fā)的含義 相當(dāng)于 Call ,就是調(diào)用用戶在事件中寫的代碼。在本例中, 只有一個地方,就是 Property Let Value 過程中:Dim chyn A
49、s BooleanRaiseEvent Change(chyn)If chyn Then Exit Property通過傳遞回的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()s = "abc"End Sub 現(xiàn)在你可以去運(yùn)行你的窗體了,我們要的效
溫馨提示
- 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 動物基因表達(dá)研究
- 創(chuàng)新驅(qū)動:產(chǎn)品設(shè)計全流程管控體系構(gòu)建與實踐
- 交通事故和解協(xié)議書正式版-1
- 及時如實報告生產(chǎn)安全事故是誰的責(zé)任
- 通信網(wǎng)絡(luò)建設(shè)安全管理體系與實施細(xì)節(jié)
- 莫言的小說與戲劇的評論
- 優(yōu)惠框架效應(yīng)-洞察及研究
- 生態(tài)文明建設(shè)新思路
- 政策補(bǔ)貼對谷物增產(chǎn)影響-洞察及研究
- 安全工作總結(jié)15
- 數(shù)與代數(shù)課件
- 工會審計實務(wù)課件
- 預(yù)防艾滋病、梅毒和乙肝母嬰傳播相關(guān)報表、上報流程和要求
- 《鐵路技術(shù)管理規(guī)程》(普速鐵路部分)-14年新版
- 食用油儲存期品質(zhì)變化的太赫茲光譜無損識別
- 胎盤早剝預(yù)案演練腳本
- 五山文學(xué)全集第一卷
- 聚磷腈功能高分子材料的合成及應(yīng)用
- 中國鐵路總公司《鐵路技術(shù)管理規(guī)程》(高速鐵路部分)2014年7月
- 鈣加維生素Dppt課件(PPT 14頁)
- TRD深基坑止水帷幕施工方案(22頁)
評論
0/150
提交評論