這里簡單地介紹VBA中的類模塊,使大家能夠在應(yīng)用程序中創(chuàng)建并使用簡單的類。 類是對象的“模板”。對象可以是任何事物,而類不會做任何事情,也不會占用內(nèi)存,只有當(dāng)類成為對象并使用Set語句和New關(guān)鍵字實例化為具體對象后,才能做事情并占用內(nèi)存。實例化類為具體對象的語法為: Dim C As Class1 Set C=New Class1 上述語句創(chuàng)建了一個名為C的對象,該對象的數(shù)據(jù)類型為定義的類Class1。 在詳細(xì)介紹類之前,讓我們先看看VBA的用戶自定義數(shù)據(jù)類型,即使用Type關(guān)鍵字定義的變量。例如,下面的Type變量定義了雇員的信息: Type Employee Name As String Address As String Salary As Double End Type 上面的語句定義了變量Employee,包含元素Name、Address和Salary。接著,您可以聲明一個Employee型的變量,并為其中的每個元素賦值: Sub test() Dim Fan As Employee Fan.Name = “fanjy” Fan.Address = “YiChang” Fan.Salary = 1000 End Sub 用戶自定義類型是很有用的,但是有三個主要的局限: 1、在編譯時必須聲明所有的自定義類型變量。雖然可以使用動態(tài)數(shù)組來處理多個自定義類型,但必須使用Redim Preserve關(guān)鍵詞。并且,不能在運(yùn)行時添加新的自定義類型變量。 2、不能控制賦給自定義類型中元素的值。例如,在上述代碼中,有可能給Salary元素賦一個負(fù)值。 3、自定義類型不做任何事情,只是靜態(tài)地存儲數(shù)據(jù)。 用戶自定義類型被廣泛用于在對Windows API函數(shù)調(diào)用時,除此之外,使用類模塊是更好的選擇。類克服了用戶自定義類型的局限。 1、使用New關(guān)鍵字,可以創(chuàng)建任意數(shù)量的類的新實例,并且能夠?qū)⑵浯鎯υ贑ollection對象中。 2、使用Property Let/Set/Get語句,可以編寫代碼驗證賦給類元素的值,并且可以編寫當(dāng)值改變時執(zhí)行的相應(yīng)代碼。例如,能夠編寫代碼確保Salary的值不為負(fù)值。 3、類可以定義方法(使用Sub過程和Function過程),執(zhí)行某項動作。 下面,讓我們將自定義類型Employee轉(zhuǎn)換為類。首先,在VBE編輯器中插入一個類模塊,并將其重命名為CEmployee,如圖1所示。(類模塊由屬性和方法組成,類本身類似于名詞;屬性可以當(dāng)作形容詞,用來描述類;方法則為動詞,執(zhí)行操作。) CEmployee類應(yīng)該有三個屬性:Name、Address和Salary。在類模塊的聲明部分聲明三個Private變量來存儲這些值,屬性的實際值被存儲在這三個私有變量中。 Private pName As String Private pAddress As String Private pSalary As Double 因為這些變量都被聲明為私有的,因此僅能在類內(nèi)部訪問,在類的外部是不可見的。如何為這些變量賦值呢?這就是Property Let語句要做的工作。每個私有變量都有相應(yīng)的Property Let語句。 Property Let Name(S As String) pName = S End Property Property Let Address(S As String) pAddress = S End Property Property Let Salary(D As Double) pSalary = D End Property Property Let語句用于給屬性賦值,即將值引入類。在上例中,簡單地將引入的值賦給私有變量。由于Property Let語句中能夠包含代碼,因此能夠編寫用于數(shù)據(jù)驗證的代碼。例如,改寫Property Let Salary函數(shù)中的代碼,使之不允許接受負(fù)值: Property Let Salary(D As Double) If D > 0 Then pSalary = D Else ‘錯誤提示 MsgBox “薪水怎能為負(fù)呢?” End If End Property 與Property Let函數(shù)相對應(yīng)的是Property Get函數(shù),用于從類中獲取屬性的值。在CEmployee類中,相應(yīng)的Property Get語句為: Property Get Name() As String Name = pName End Property Property Get Address() As String Address = pAddress End Property Property Get Salary() As Double Salary = pSalary End Property Let語句和Get語句的數(shù)據(jù)類型必須相匹配。例如,Let Salary接受Double類型的值作為其參數(shù),這意味著其返回的相應(yīng)的Get屬性的值必須是Double。如果數(shù)據(jù)類型不一致,就會導(dǎo)致編譯錯誤。 這些Get語句簡單地將三個屬性向外公開。要創(chuàng)建只讀屬性,則忽略Property Let語句而僅使用Property Get語句。例如,WithholdingTax屬性是只讀的,在Get語句中的代碼計算合適的值并將其公開,但避免從外部改變該屬性的值: Property Get WithholdingTax() As Double WithholdingTax = some_tax_calculation End Property 該屬性沒有對應(yīng)的Let語句,因此該屬性只讀,沒有辦法將值賦給WithholdingTax。 類模塊能夠包含方法,例如CEmployee類有一個用于雇員復(fù)核薪水的方法: Public Sub PrintPaycheck() ‘放置打印復(fù)核的實際代碼 End Sub 好了,我們已經(jīng)完成了CEmployee類的初步定義,如圖1所示。
圖1:CEmployee類 下面,在標(biāo)準(zhǔn)模塊的代碼中實例化類,并使用其屬性和方法。首先,在VBE編輯器中插入一個模塊,聲明一個CEmployee類型的變量。(注意,在復(fù)雜的應(yīng)用程序中,在類模塊中聲明并實例化另一個類是完全合法的) Dim Emp As CEmployee 接下來,實例化該類,創(chuàng)建一個可用來工作的實際對象,如下列語句: Set Emp = New CEmployee 上述語句創(chuàng)建了一個名為Emp的對象,能夠使用CEmployee類中的屬性來引用特定的雇員信息,例如: Emp.Name = “fanjy” Emp.Address = “YiChang” Emp.Salary = 1000 這三個語句調(diào)用在CEmployee類中聲明的Property Let語句來賦值給類中的私有變量。我們能夠使用下列代碼讀取對象的屬性的值: Debug.Print Emp.Name Debug.Print Emp.Address Debug.Print Emp.Salary 上述語句調(diào)用類模塊中的Property Get語句并獲取數(shù)據(jù)。我們也能讀取類中的只讀屬性WithholdingTax: Debug.Print Emp.WithholdingTax 由于WithholdingTax屬性沒有相應(yīng)的Let語句,因此不能給該屬性賦值。如果試圖賦值: Emp.WithholdingTax = 4000 則會導(dǎo)致:“編譯錯誤:不能給只讀屬性賦值”。 也能夠調(diào)用方法來執(zhí)行操作: Emp.PrintPaycheck 在集合中存儲類的多個實例 如果到運(yùn)行時還不知道有多少個雇員,那么能夠在運(yùn)行時按需要創(chuàng)建多個Emp對象,每創(chuàng)建一個Emp對象之后將其存儲在集合中。例如: Dim Coll As New Collection Dim Ndx As Long Dim Emp As CEmployee For Ndx = 1 To NumberOfEmployees Set Emp = New CEmployee ‘設(shè)置Emp對象的屬性 Coll.Add Item:=Emp, Key:=Emp.Name Next Ndx 上面的For…Next循環(huán)將創(chuàng)建CEmployee類的NumberOfEmployees個實例,具體數(shù)量由運(yùn)行時決定,并將其存儲在名為Coll的集合對象中。之后,能夠使用For Each循環(huán)從Coll集合中獲取每個雇員信息或執(zhí)行操作: For Each Emp In Coll Emp.PrintPaycheck Next Emp 類的Instancing屬性 類的Instancing屬性決定其可見性(或稱作作用域),默認(rèn)屬性值為1-Private,意味著類僅能在包含該類的工程中創(chuàng)建和訪問。其他工程不能基于該類創(chuàng)建對象。對于絕大多數(shù)應(yīng)用程序來說,Private是足夠了。 Instancing屬性的另一個值是2-PublicNotCreatable,表明其他工程能夠?qū)⒆兞柯暶鳛樵擃?,但是不能使用Set語句創(chuàng)建該類的實例。 在多個工程間使用類 如果一個工作簿需要使用定義在另一個工作簿中的類,則需要在包含類模塊的工作簿中編寫代碼導(dǎo)出類到另一個工程。該類的Instancing屬性必須是2-PublicNotCreatable。 假設(shè)Book1.xls工作簿中包含一個名為Class1的類模塊,Book2.xls需要使用該類。首先,將Book1工作簿的工程名稱從缺省的 “VBAProject”修改為唯一的名稱,例如MyProject。然后,在VBE編輯器中激活Book2工作簿的界面,設(shè)置對Book1工作簿的引用,即在VBE中選擇“工具——引用”,然后在列表中選擇“MyProject”。然后,在Book2中,創(chuàng)建如下聲明: Public C As MyProject.Class1 因為Instancing的屬性值為PublicNotCreatable,所以可以聲明一個Class1類的變量,但不能創(chuàng)建該類的實例。因此,需要在Book1中編寫一個函數(shù)來創(chuàng)建Class1的新實例,并返回該實例給Book2。在Book1中,創(chuàng)建下面的過程: Public Function GetClass1() As Class1 Set GetClass1 = New Class1 End Function 然后,在Book2中設(shè)置公共變量C為上述函數(shù)的結(jié)果,例如: Set C=MyProject.GetClass1() 現(xiàn)在,C被設(shè)置為Class1的新實例。 好了,上面只是對類模塊的一些初步介紹,還有一些知識未講述,例如Property Set語句,留待以后在慢慢整理。 |