Excel-VBA-類模塊入門_第1頁
Excel-VBA-類模塊入門_第2頁
Excel-VBA-類模塊入門_第3頁
Excel-VBA-類模塊入門_第4頁
Excel-VBA-類模塊入門_第5頁
已閱讀5頁,還剩27頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、Excel VBA類模塊入門教程示例一示例二集合示例VBA類:隱者的秘密刖言寫下這個題目,可能會讓很多朋友疑惑,筆者先埋下一個 關子,很快我會讓您知道這個標題的寓意。這份禮物送給現在想學習類知識或曾經學過但因為各種 原因沒有“修成正果”的朋友,我期望的結果是這篇文章后, 您可以在類模塊中像在標準模塊中寫代碼一樣熟練,我也期 望不至于太乏味而使您沒有耐心看完整篇文章,或者說期望 您學習的過程是輕松愉悅的,但愿我可以做到。文章構劃為 8部分:1 .什么是類2. 為什么要學習類3. 類的預備知識4. 創(chuàng)建類屬性5. 創(chuàng)建類方法6. 創(chuàng)建類事件7. 個完整的類實例&未完的結尾什么是類在我們身邊

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

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

4、,來構建我們自己的類,姑且可稱之為自定義類。 這需要在 VBE 下,通過插入類模塊,然后向類模塊中寫入 代碼來完成。這就是你常常聽說的類,本文的主題就是這個 包含代碼的模塊!通過這個模塊,可以提供給我們一個和 V BA 提供給我們的諸如 Textbox 功能性質完全相同的類,然 后,再由我們自己象使用 Textbox 一樣使用! 類是一個隱者,她把自己藏在所有模塊的最后,甚至在多數 情況,她從不出場?,F在,她掛著神秘的微笑,向你走來, 你要拒絕嗎為什么要學習類模塊類通常被認為是學習 VBA 的難點之一,之所以如此,因為 相對于制造一個標準模塊或用戶窗體,我們可以找到的類的 學習資源少之又少,

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

6、受這個追求的過程。 模塊、控件、鏈接庫和類構成軟件工程開發(fā)的四大技術,而 類技術是控件和鏈接庫技術的基礎,我們不得不學。2類有什么用 如你前面看到的我們使用 Textbox 類,類可以創(chuàng)建大量性質 相近的對象,減輕我們的程序量,簡潔代碼并提高效率。 類定義后,在其它模塊中使用時,我們就可以暫時忘記或不 必考慮它內部復雜的細節(jié), 讓我們變得輕松, VBA 雖然不能 真正封裝類的形式,但在這里,我們可以封裝它的概念。 這并不是類的全部好處,其它的,留著朋友們用的時候慢慢 體會吧。類掛著神秘的微笑,已經走到你的大門口,開門迎接她吧, 你還等什么?類的預備知識廣義上講,所有 VBA 的知識,包括語句、

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

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

9、 去做。對象是由類創(chuàng)建的一個實例,它是類的實體化。 對象的引用和操作被邏輯上劃分為不重疊的三個部分: 屬性是指對象的特性。以前面的 Textbox 為例,有長度,高 度,框中顯示的文字等等。方法是指對象的某個操作。 如讓 Textbox 成為當前的焦點 (即 光標移動到它上面)。事件是指對象對外部動作的響應。 如我們用鼠標點擊 Textbo x 時,會產生一個 Click 事件,改變它的值,則產生一個 Ch ange 事件變量的作用域變量因為聲明的位置和方式不同,從而有不同的作用域。作 用域是指變量在多大范圍內能被代碼識別。可以劃分為過程 級、模塊級和全局變量。過程級變量在過程中聲明,這里過程

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

11、頂部來聲明。 在類模塊中,對變量作用域的理解要注意下面兩點:(a) 由于類是生成對象的模具,每生成一個對象,相當于產 生了一個副本,這個副本就是對象的“真身”,副本間是相 互獨立的,從而,模塊級的變量只作用于副本自身。(b)類模塊中使用Public關鍵字,只有當對象變量是這個 類的實例時,才能被訪問。過程和函數變量、過程(Sub)、函數(Function)是我們在標準模塊中使用的最基本的構件,在類摸塊中,它們仍然是最基本和重 要的角色。對于它們,你已經再熟悉不過,之所以前面還要 花這么多文字, 是為了突出它的重要, 也是想讓你放松一下, 哦,我花了很短的時間已經看了這么多 (我也寫了這么多!

12、)。過程和函數并無實質的區(qū)別,當需要返回值時,就使用 Fun ction ,如果不需要返回任何結果,隨你的愛好,但這時推薦 你使用Sub,因為這樣更符合微軟的本意。過程(Sub)、函數( Function )也有作用域,在標準模塊中通過使用 Private 和 Public 關鍵字(可以省略 Public 關鍵字,因為它是默認的) , 可以劃分為模塊級和全局級,以決定它是在當前的模塊有效 還是整個工程有效。同變量一樣,在類模塊中使用 Public 關鍵字,只有當引用對 象變量是這個類的實例時,才能被訪問通用內部控件 Control ( s)VBA 提供 Control 類作為一般內部控件類型,

13、當使用Dim Ct As Control 聲明了一個變量后,就可以將任何控件賦給該變量,而不管 具體的類型,因為在類的使用通常是處理大量相近的對象, 所以這種特性非常有用。在實際使用時,我們多是通過容器 控件的 Controls 屬性來返回一個 Control 的集合對象。Dim Ct As ControlFor Each Ct In Me.ControlsIf TypeName(Ct) = "CommandButton" Then MsgBox Ct. CaptionNext 上面這段代碼可以遍歷窗體的所有控件并報告找到的命令 按鈕。集合 CollectionCollec

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

15、lFor 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).Name col.Remove iNext iEnd Sub 上面的代碼先將窗體上所有的 TextBox 加入到集合中,然后 再刪除掉。 Count 屬性返回集合的成員數量, Remove 方法后 面的參數是集合成員的索引號。成員的索引號通常是按照加 入的順序自然編

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

17、tBox2 ,并把它 放在成員 TextBox1 的前面。col.Add TextBox2, , col.Count col.Add TextBox2, , "tx1" 第一句中,因為只有一個成員,所以 col.Count 也是索引號使用事件的WithEvents 變量WithEvents不是一個單獨的語句,為了使用對象的事件,需 要在聲明該對象時使用WithEvents關鍵字。例如:Dim WithEvents app As Application將上面的語句寫入ThisWorkBook的模塊,可以看到在通用 框中出現了一個變量 app:外接程序)電t*i行卄列1此主題相

18、關圖片如下:么 Microsoft Visual Basic - Bookl - | ThisWorkbook (代巧)橢 文件怨)編輯 視窗 插入 格式辺 調試 運行® 工具j-a Jt電齟勺小丨壬三卜占醸倉1謝轉S 縣 ¥BJlFr*j ec t 白 Bicrosoft(Baakl)Entel刑象(Sheetl)13 2 匚|GM3卡WappSheetlShestE (SkeetS)Sheets (Sheets)Thi stfcrkbook白自模塊 戰(zhàn)複塊1:"類梗塊芒類1Option ExplicitDim WitKEvftiits 電pp As Appli

19、nation在通用框選擇app后,左邊的聲明框便會顯示 app的事件。此主題相關圖片如下:£3按字母序I按分類序I囲稱)JJS p w迅就|題廚瞥洪砲用m列i肉文件世編輯(1)視圉迪插入格式辺調試 運行 工具(1)外接程序 奮VBATrflject.(Bookl)&-3 Microsoft Jscel 對象S Sheetl Gheetl)Sj Sheets (5h eet2)O sheeta和 Thi sWorkbook 自-b模塊我模塊1-l 出類模塊類1TLi sVorkbovT Workbook |A.cceptLbelzI FalseAutoUpdateFr e 0C

20、han尊皀Hi story 0S "e "litf I * t r需要注意的是,使用WithEvents只是聲明了對象變量,而并不實際生成對象,為了生成真實的對象,你仍然需要在聲明后向生成其它對象一樣,使用Set語句進行指定。此外,WithEvents變量不能是通用類變量如Object,而必須指定類名,也不能把 WithEvents變量聲明為 As New。不能在標準模塊 中使用 WithEvents初識類模塊現在,請打開你的 VBE,主菜單-插入-類模塊。插入了一個類模塊,也就建立了一個類。類模塊的名字就是類的名字。你現在看到的,她的名字叫“類1”,這是VBA按她姐妹排行

21、給她取的的, 是的,VBA 一貫如此,你早就熟悉了這種規(guī)則,現在,在標準模塊或其它模塊中輸入 Dim As的時候,提示框中她已經出現了。 但我知道,有件事你正 耿耿于懷,“類1”,太沒個性了,想改成自己要的名字吧。 很容易,和你改標準模塊的名字一樣,打開屬性窗口,看到 了吧,第一行就是她的名字,隨你的意愿修改吧。此主題相關圖片如下:駕 文件便)漏輯© 視閣 插入 格式調試1運行® 工具外接程序®転M A ilU呂冒 =Microsoft Visual Bask: - Bookl -類I (代碼)' VBAProjectm mi口-VBAProjectCBn

22、okl-< < Mi crosoft Si cel 對象 0 Shetl (SheHl) 辱SheetE (SheetE) 園 1 Sheet3 (Sheets) © ThisWorkbook 曰曰複塊隣模塊1-勺類橈塊Opti on Ex:pli ci tdim xx魚呂 XnnlMap sXmlHwneEpjie® XmlNamespaces 思I XmlSchemaXmlSchemasthzi1饕1類模炊捲字母序丨松44舉字(名稱)類1ilnstarLCing I " Frivat e你或許已經注意到,在名字下面,只有一個屬性:Instancin

23、g,其值也只有兩個選項:Private 和PublicNotCreatable。事實上,你完全可以忽略這個Instancing ,就象你完全忽略條件編譯指令一樣,因為在 VBA中我們幾乎用不到它 們,而只需維持她的默認值即可。至少我是這樣認為的,但 我給不了您充足的理由,而只是個人的一種狹隘經歷。既然 提到了,就簡單說明一下:Instancing 屬性決定該“類”在其它工程中是否可以被使 用。我們知道,標準模塊中的 Public 過程,可以保存在宏工 作簿甚至直接被另一工作簿的工程調用,但類中的代碼是不 可分割的整體,所以必須整體決定是否允許外用。當 Insta ncing 屬性設為 Priv

24、ate (默認)時,不允許其它工程訪問。 當設置為 PublicNotCreatable 時,只有在自己的工程創(chuàng)建 了該類的對象時,其它工程才允許使用這個對象,注意,僅 僅是在本工程中創(chuàng)建的對象,而不能用她在其它工程中創(chuàng)建 對象。 隱者已經來到你的身邊,透過薄薄的面紗,你似乎已看到她 神秘的微笑。站起身來,走過去吧!創(chuàng)建類屬性讓我們想一下作為類的使用者時,我們是如何操作對象的屬 性的,對象屬性的操作不外乎讀和寫兩種。當我們要給對象 的某個屬性賦值時,我們會:TextBox1.Text= ”abc” 當我們要讀取對象的屬性時,S= TextBox1.Text 現在,看看作為類的提供者需要怎樣做。

25、我們將“類 1”改名為“ MyClass ”并為它創(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 我們可以省去上面默認的 Public 。但看上去還是有點麻煩哦, 不僅需要兩個公共過程,而且還要一個輔助的私有變量 s

26、 和 一個參數c。在類模塊中,Property過程把對屬性的讀寫分開 了,說一下 Property 過程的工作機制,當標準模塊中的代碼 讀取對象的屬性時,便會觸發(fā)存在的 Property Get 過程,或 者說 Property Get 過程提供了屬性的讀功能,同樣, Propert y Let 過程提供了寫屬性。這樣,上面的兩個過程(當然在 模塊中沒有先后的要求),可以只有一個,或者雖然兩個都 有,但卻不全是 Public ,從而提供出去的屬性是只讀或只寫 (呵呵,沒見過只寫哈)。僅僅是為了提供只讀或只寫的屬 性,代碼就從一行變成了七行?! 這樣的理由, 你不會信服,VBA 中的類通常是提供

27、給我們自己使用的!如果它確實是 只讀的,我們自覺地去只讀就是了!我們使用 Property 過程 還有其它理由,最基本的一條,我們可以利用這個“過程” 來做我們想做的事??匆豢矗篜ublic Property Let x(ByVal c As String)s = Format(c, "0000")End Property 這里我們只是簡單的利用了一下,更多的在后面你會看到。 此外,誰會保證有一天你不使用 VB 給別人提供類呢,這個 技術可是通用的。提供一段標準模塊的測試代碼,來看看我 們上面構建的類屬性,你自己試試吧。Sub aTest()Dim mc As New My

28、Classmc.x = "123"Debug.Print mc.xEnd Sub 就象我們給普通變量和對象變量賦值的方式不同一樣,對象 變量是使用 Set 賦值的。對“對象”屬性, VBA 提供了 Property Set來代替構建“普通”屬性使用的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 G et 的用法,按照 Sub 去記住 Property Let /Set。屬性的初始值我們常常希望,當一個對象建立的時候,它的某些屬性會被 自動賦予一個初始值,這樣,對具有最常見的屬性值的對象 可以減少重復性的賦值工作。這需要借助于類的構建函數來 完成。在類模塊代碼窗口的“通用”框中點擊向下的小三角箭頭, 選擇“ Class”,右面聲明框中可以看到兩個選項,“Initialize”和“ Terminate ”,我們對它們應該不陌生,很多對象都 有這兩個事件, Initialize 事件當對象建立時發(fā)生, Te

30、rminate 事件在對象對釋放時發(fā)生。由于類是靜態(tài)存在的,它并不是真正的對象,所以在類模塊中,它們通常被稱為構建函數和析構函數,或構建過程和析構過程。對它們的理解和你在對象中的用法并沒有什么不同。當一個對象被建立時,構建函 數將被首先執(zhí)行,同樣,當對象釋放后,將執(zhí)行析構函數。下面建立MyClass ,屬性x初始值為” 0001的全部測試代碼:類模塊 MyClass 的代碼 Option ExplicitPrivate s$Public Property Get x() As Stringx = sEnd PropertyPublic Property Let x(ByVal c As Str

31、ing)s = cEnd PropertyPrivate Sub Class_Initialize()s = "0001"End Sub 標準模塊 1 的代碼 Option ExplicitSub aTest()Dim mc As New MyClassDebug.Print mc.xEnd Sub 隱者為你揭開了第一層面紗,你隱約已看到她美麗的面厐, 雖然還不是很清晰,但你知道,早晚會的創(chuàng)建類方法放松一下,請拿出你家的紫砂壺,泡上一壺好茶,聽我給你 將類的方法的故事,你的茶品完了,我的故事也差不多就講 完了。1構建類的方法其實就是在類模塊中寫公共的Sub 和 Functi

32、on現在我們給前面提到的 MyClass 創(chuàng)建一個方法 PutIntoActive Cell ,功能是將 x 屬性值寫入活動單元格。Public x$Sub PutIntoActiveCell()ActiveCell = xEnd Sub在標準模塊中用下面的代碼測試一下:Sub aTest()Dim mc As New MyClassmc.x"abc"mc.PutIntoActiveCellEnd Sub 這是本回要告訴你的全部嗎?你還沒有開始品茶吧?就這 樣了結束?這是最重要和基本的,但卻不是全部。 你是否有一種感覺,但你不能清楚地說出來? 端起你可愛 的茶杯,品一口茶,

33、我們繼續(xù)。類的方法環(huán)境借用廣為眾知的一個名詞“數據環(huán)境”,雖然不準確,但我 實在想不出更好的稱謂來代替,姑且這么叫吧。稍后你就會 知道它的含義。類可以象 VBA 提供給我們的很多標準類一樣風光無限,所 有的程序設計者都在工程中使用它,但更多時候,我們所構 建的類只在特定的環(huán)境下被使用,類的方法環(huán)境是指包括類 所在工程的其它成員在內的,可以調用的資源的集合。工作 簿、工作表、窗體或其它,在類模塊中,你可以象在標準模 塊中一樣操作它們,千萬不要因為換成了類模塊而產生任何 疑慮,作為類的創(chuàng)建者,你要讓類模塊中的代碼象你在標準 模塊中一樣親近它們, 只要你認為必要。 脫離了方法環(huán)境的、 謹小慎微的、封

34、閉的類實在沒有什么意義。如果你預期方法 環(huán)境在運行時可能會有變化,你要事先預知它們并象在標準模塊中一樣使用恰當的措施,比如你不能確定運行時活動工 作表的名稱(但你確定屆時會是一個工作表),你可以使用 ActiveSheet 。我反復說“和標準模塊一樣”,就是想告訴你在類模塊中創(chuàng) 建方法時,對工程中其它成員的操作,和你已經熟悉的標準 模塊中的方式的實在沒有什么不同,這一原則適用于類模塊 中所有代碼(也許叫代碼環(huán)境更準確些),而不僅僅是構建 方法的代碼。現在,你知道了,你剛才的感覺到的是開放的方法環(huán)境。是 的,以后你會更深地體會到,作為好的提供者,開放的思維 有多重方法的兄弟 成員事件類方法的執(zhí)行

35、需要在代碼中以顯性的方式指定,象上面的 c.PutIntoActiveCell ,有時候,當最終操作者觸發(fā)類對象成員 (屬性) 的某個事件, 需要在事件發(fā)生時產生一系列的操作, 這時,我們要運用成員事件。成員事件和方法都是類提供的 一系列代碼的操作,倆兄弟的區(qū)別在于,成員事件無法也不 必再由代碼顯性調用。我們來看一個具有普遍意義的事例。 重要例 窗體 UserForm1 上有 5 個 CommandButton 控件(名稱分別為 默認 CommandButton 1- CommandButton 5)和 1 個 TextBo x 控件(名稱為 TextBox1 )。要求當各個 CommandB

36、utton 控件被點擊時,它的按鈕文字( 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

37、 = cmd.CaptionEnd 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 = NothingEnd Sub 仔細玩味上例的每一行代碼,直至品完你壺中的茶。呵呵, 因為它實在很有用。

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

39、我們需要全部的要 求。我不再去解釋這個觀點,在本回后你自然會明白。從這個意義上講,創(chuàng)建類事件實在沒有必要。唯一的遺憾是,我們沒有體會到作為創(chuàng)建者的全部樂趣,標準類給我們提供了各種事件,當然希望自己也可以做到,想象中這應當是一件 激動人心的事,所以,追求快樂是創(chuàng)建類事件的重要理由, 另一個理由,前面已經提到。回到前面我們的 MyClass 類,我們將 x 屬性改名為 Value 屬 性,雖然對屬性、 方法以及事件的命名, VBA 沒有特別的限 制,但建議您不要象我前面那樣,隨便取一個x,可能的話,要盡量和標準類的成員 (屬性、 方法以及事件) 名稱相一致?,F在我們?yōu)椤笆褂谩闭咛峁┮粋€“Chang

40、e ”事件,不錯,我們給它取名為“ Change”,而不再是隨意的“ y”或其它(雖 然也可以) ,這樣, 我也不用解釋這個事件的用意了, 呵呵。 為了做到這一點,看看我們應該做什么。1第一步:使用 Event 語句聲明事件 看一下類模塊中現在的代碼: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 =

41、 cEnd PropertyPrivate Sub Class_Initialize()s = "abc" 初始值End Sub和前面的代碼比較,多出了一句:Public Event Change(ByRef Cancel As Boolean) 這就是 Event 語句,只此一句, 我們已經為我們的類聲明 (我 想使用“注冊” 一詞是不是更妥切)了一個事件Changeo在看 Event 語句產生的效果前,先來看它的特性:(1 )為了聲明事件,Event總是Public的,這好理解吧。(2)事件可以不帶參數,女口 Public Event Change。,也可以 帶參數,如

42、我們上面給出的,但參數不能是命名參數,可選 參數或數組參數。這里我只解釋一下命名參數的含義。我們 知道,事件可以因特定的用戶事件而觸發(fā),也可以在代碼中 象方法一樣指定執(zhí)行,如下面的 CommandButton1_Click :Private Sub CommandButton2_Click()CommandButton1_ClickEnd Sub但在調用對象的方法時我們通常喜歡這樣的方式: Selection.Sort Key1:=Range("A2"), Order1:=xlAscending 這里 Key1 、 Order1 就是命名參數,命名參數的好處是我們 不必記住

43、它們的次序,調用時直接以名稱和冒號后加等于號 指定它的值,但對事件的調用卻不允許這樣。(3)事件沒有返回值?,F在我們看一下, Event 為我們做了什么。 建立一窗體 UserForm1 ,添加一個 TextBox 控件(名稱為 Te xtBox1 ),兩個 CommandButton 控件(名稱為 CommandBut ton1 和 CommandButton2 ), CommandButton1 的 Caption 設 置為“賦值” ,CommandButton2 的 Caption 設置為“讀值” , 窗體的代碼如下:Option ExplicitDim WithEvents mc As

44、 MyClassPrivate Sub CommandButton1_Click()mc.Value = TextBox1 '賦值End SubPrivate Sub CommandButton2_Click()MsgBox "mc 當前的值為 " & mc.Value '讀值End SubPrivate Sub UserForm_Initialize()Set mc = New MyClass End Sub上面這段代碼實現的是,當點擊 CommandButtonl時便會將TextBoxI 的值賦給 me 的 Value,當點擊 CommandBu

45、tton2 時便會顯示 me當前的Value值。來運行一下這個窗體,先點擊CommandButton2,此時顯示“abc”,是me的初始值,然后在 TextBoxI輸入“ 123”, 點擊 CommandButtonl,再點擊 CommandButton2,顯示 “ 1 23”,說明賦值成功了。呵呵,忘了,我們要做什么了!現在,請從 UserForml代碼 窗口的“通用”框中選擇me,哇!我們聲明的事件在右邊“聲明”框中已經出現了!此主題相關圖片如下:MicrosoFt Visual Basic = Bookl.xls - UserForml垮文件 編輯觀圖世)插入格式迫)調試運行®

46、 工具外按程序翅23 Ji Y IS 麹 3-VBAPrajecI色3 .0(Bdokl. xls)-Microsoft Ek cel 對隊 題 Sheetl (Sheetl) S侶h昵坨)適 ShetS (ShetS) 罰 ThisWorkbookS-曰窗體a UserForml El -舊類模塊NlyClas:E二CWge二Qptxcn Explicit 11 . 1 SIl le ll a 1 wILIWI -Ikllilll. 1N觀爭弓 妙行1列Din Hi tU/vivts; mu 人百 MtCIe倉百Fr ivete Sub CommaiidBu11on 1 Cl i ek 0m

47、e. Value 二 TextBoxIEnd EiAFyivata Sub CommuidButtoi£_Cli ck0"mu當前的值北T" & me. Value,讀值End SubFrivate Sub UerForrn_Initi sli re ()Set me - New MyClasEnd SubPrivets SubCancel Aw Bociean)End SubILUfllEIHEIi我們定義這個事件是希望當me的值改變時響應的,現在就迫不及待地給它寫一句代碼吧:Private Sub mc_Change(ByRef Cancel As B

48、oolean)If MsgBox(" 要改變 mc 的值嗎 ?", vbYesNo) = vbNo ThenCancel = TrueEnd Sub 上面這句代碼你不會陌生吧,希望當用戶選擇了在改變時給 用戶一個確認的機會。但是,現在點擊 CommandButton1 ,卻不會給你選擇的機會, 我們還有一步沒有做。使用 RaiseEvent 語句引發(fā)事件第二步:使用 RaiseEvent 語句引發(fā)事件 聲明了事件后,我們要做的,便是找到所有與事件發(fā)生關聯 的地方,使用 RaiseEvent 語句引發(fā)事件,這里引發(fā)的含義相 當于 Call ,就是調用用戶在事件中寫的代碼。在本

49、例中,只 有一個地方,就是 Property Let Value 過程中:Dim chyn As 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 現在你可以去運行你的窗體了,我們要的效果應該是達到了 吧。為了便于你

溫馨提示

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

評論

0/150

提交評論