標籤:
Excel物件模型簡介
在介紹Excel物件模型之前,讓我們先來看一個簡單的例子。大多數工廠都是按這樣的結構進行設定的:最上層為工廠總部,第二層次分為各個車間,在車間下面又分各班組。就這樣組織在一起,形成了一個工廠體系。Excel物件模型與此相似,看起來複雜但實質上很簡單清晰。
提示 任何看起來複雜的東西其實都是由一些簡單的部分組成的,或者其實它本身就比較簡單。
Excel的物件模型是通過階層很有邏輯地組織在一起的,一個對象可以是其它對象的容器,可以包含其它的對象,而這些對象又包含其它的對象。位於頂層的是Application對象,也就是Excel應用程式本身,它包含Excel中的其它的對象,如Workbook對象;一個Workbook對象包含其它一些對象,如Worksheet對象;而一個Worksheet對象又可以包含其它對象,如Range對象,等等。這就是Excel的物件模型。
例如,Range對象在Excel物件模型中的位置為:
Application對象
Workbook對象
Worksheet對象
Range對象
知道了某對象在物件模型階層中的位置,就可以用VBA代碼方便地引用該對象,從而對該對象進行操作,並以特定的方式組織這些對象,使Excel能根據您的需要自動化地完成工作任務。因此,要熟練掌握Excel VBA編程,必須理解Excel的物件模型。
在VBA協助系統中有Excel物件模型的階層圖,您可以參閱。
集合
集合是對象,是一組屬於同一類型的對象或相關的對象的集,作為它們的容器。例如,Workbooks對象是當前開啟的所有Workbook對象的集合,Worksheets是包含在某個Workbook對象中的所有Worksheet對象的集合。
對象的引用
■ 使用VBA可以處理某個對象的整個集合,或者某集合中的一個單獨的對象。
文法:集合(“對象名”) 或 集合(對象索引號)
說明:引用集合中的某個對象,即對象名或對象索引號所代表的對象
例如,Worksheets(“Sheet1”)引用集合Worksheets中的工作表Sheet1;若Sheet1是集合中的第一個工作表對象,還可以寫為Worksheets(1)。
特別地,”Sheets”集合由活頁簿中的所有工作表(包括圖表工作表)組成。若要引用活頁簿中的第一個工作表,可採用語句Sheets(1)表示。
■ 通過點運算引用某對象的成員
我們可以用句點連線物件名來限定是對某個對象成員的引用,同時也指定了該對象成員在對象階層中的位置。
文法:<對象名>.<對象名>. …
說明:後一對象是前一對象的成員,限定了對前一對象所包含的對象成員的引用
例如,Application.Workbooks(“Book1.xls”).Worksheets(“Sheet1”).Range(“A1”) 表明是對活頁簿Book1上的工作表Sheet1中儲存格A1的引用,其中Application代表Excel應用程式本身,可省略。特別地,若Book1是當前活動活頁簿,則上述語句可簡寫為 Worksheets(“Sheet1”).Range(“A1”) ;若Sheet1是當前使用中工作表,則又可簡寫為 Range(“A1”) 。因此,若在引用中省略了活頁簿對象,則表明是使用當前活動活頁簿;若再省略了工作表對象,則表明是使用當前使用中工作表。
設定物件變數
物件變數是代表一個完整對象的變數,如工作表或儲存格範圍。用Dim或Public語句來聲明物件變數。
文法:Dim(或Public) <變數名> AS <對象名>
說明:將<變數名>聲明為一個<對象名>對象。
一般可將對象名直接設為Object,即任意對象。但如果您知道變數將作用到的對象的話,最好將其設定為具體的對象。
例如,語句:Dim DataArea As Range,將變數DataArea聲明為一個Range對象。
在將變數聲明為一個物件變數後,用Set語句將某對象賦值給該變數。
文法:Dim(或Public) <變數名> AS <對象名>
Set <變數名>=<某對象>
說明:將<變數名>聲明為一個<對象名>對象,再將某對象賦值給該變數。
現在,讓我們來看看下面兩個簡單的例子,其作用是在活頁簿Book1的工作表Sheet1中的A1至B10儲存格範圍輸入數值666,並將它們格式化為粗體和斜體。
Sub 沒有設定物件變數()
WorkBooks(“Book1.xls”).Worksheets(“Sheet1”).Range(“A1:B10”).Value=666
WorkBooks(“Book1.xls”).Worksheets(“Sheet1”).Range(“A1:B10”).Font.Bold=True
WorkBooks(“Book1.xls”).Worksheets(“Sheet1”).Range(“A1:B10”).Font.Italic=True
End Sub
***************************************
Sub 設定了物件變數()
Dim DataArea As Range
Set DataArea = WorkBooks(“Book1.xls”).Worksheets(“Sheet1”).Range(“A1:B10”)
DataArea.Value=666
DataArea.Font.Bold=True
DataArea.Font.Italic=True
End Sub
比較這兩個程式,其功能相同,但可以看出,當我們設定了物件變數後,不僅可減少手工輸入重複的代碼,而且使得代碼得到了明顯的簡化。
此外,對於稍複雜一點的程式,設定物件變數後,由於減少了要處理的點運算子的數目,因此可使得代碼的運行速度更快。
當設定的變數運行完畢後,應將該變數釋放,以節省記憶體空間。其文法為:
文法:Set <變數名>=Nothing
對象的方法和屬性
在引用了對象或者設定了物件變數後,我們就可以對該對象進行所需要的操作或設定了。這就需要使用對象的方法和屬性。
■ 對象的方法
對象都有方法,一個方法就是在對象上執行的某個動作。為對象指定方法時,應將對象和方法組合在一起,中間用句點分隔。
文法:<對象>.<方法> <參數>
說明:為某對象指定方法。若該方法帶有參數或需要為帶參數的方法指定參數時,則指定參數以執行進一步的動作;若該參數傳回值,則應在參數兩邊加上括弧。
例如,語句Worksheets(“Sheet1”).Range(“A1:B2”).ClearContents,執行Range對象的ClearContents方法,清除A1至B2儲存格範圍的內容,但保留該地區的格式設定;而語句 Worksheets(“Sheet1”).Range(“A1:B2”).Clear,執行Range對象的Clear方法,清除A1至B2儲存格範圍的內容,並刪除所有的格式。
■ 對象的屬性
對象都有屬性,用來描述或設定對象的特徵。可以使用VBA來設定對象的屬性,也可以對一個對象的某些屬性進行修改,從而定義該對象,還可以引用某對象的屬性值。使用屬性時,應將對象和屬性群組合在一起,中間用句點分隔。
文法:<對象>.<屬性> <參數>
說明:設定或引用某對象的屬性。若該屬性帶有參數或需要為帶參數的屬性指定參數時,則指定參數以進一步描述該對象;若該參數傳回值,則應在參數兩邊加上括弧。
文法:<變數>=<對象>.<屬性>
說明:將某對象的屬性值賦值給一個變數,以便於在程式中使用。
例如,Range對象有一個Value屬性,可以用VBA代碼引用該對象的屬性值,也可以修改該屬性,如下面的語句:
Worksheets(“Sheet1”).Range(“A1”).Value,該語句引用當前活頁簿上工作表Sheet1中儲存格A1的值。
Worksheets(“Sheet1”).Range(“A1”).Value=666,該語句將當前活頁簿上工作表Sheet1中儲存格A1的值改為666。
Dim Var As Variant
Var=MyForm.Caption
上面兩句將MyForm對象的Caption屬性賦值給變數Var。
提示 (1) 大多數對象都有一個預設的屬性,如Range對象的預設屬性是Value屬性。對於預設的屬性可省略屬性代號的書寫,即Range(“A1”).Value與Range(“A1”)所表達的意思一樣。即便如此,仍建議還是要將屬性代號寫全,以提高程式的可讀性。
(2) 訪問一個對象不存在的屬性時,會返回一個錯誤。
■ 方法和屬性的參數
大多數方法都帶有參數,從而能進一步定義動作。例如,Range對象的Copy方法帶有一個參數,用來定義將儲存格範圍的內容複寫到什麼地方。語句
Worksheets(“sheet1”).Range(“A1”).Copy Worksheets(“sheet2”).Range(“A1”)表示將當前活頁簿上工作表Sheet1中儲存格A1的內容複寫到當前活頁簿上工作表Sheet2中儲存格A1中。
在一些情況下,方法帶有一個或多個可選的參數。如果方法使用了可選的參數,則應該為這些參數插入空白預留位置。例如,活頁簿對象的Protect方法有三個參數,即密碼、結構和視窗,對應於“保護活頁簿”對話方塊中的相應選項,其文法為:
文法:<活頁簿對象>.Protect (Password,Structure,Windows)
說明:保護活頁簿使其不至被修改。三個參數均為選擇性參數,其中Password指定密碼,若省略該參數,則不用密碼就可以取消對該活頁簿保護;Structure參數指定是否保護活頁簿結構;Windows參數指定是否保護活頁簿視窗。
若要保護活頁簿“Book1.xls”,可使用語句:
Workbooks(“Book1.xls”).Protect “xYzRq”,True,False
其中,第一個參數指定了保戶該活頁簿的密碼,注意密碼區分大小寫;第二個參數為True表明活頁簿結構受到保護;第三個參數為False表明不保護視窗。
若不想指定密碼,可使用語句:
Workbooks(“Book1.xls”).Protect ,True,False
該語句省略了第一個參數,表明不指定保護密碼,但必須在該參數出現的位置用一個逗號預留位置代表該參數。
讓我們再看看下面的語句:
Workbooks(“Book1.xls”).Protect Structure:=True,Windows:=False
該語句的功能與上面語句相同,即對活頁簿不指定保護密碼,要保護活頁簿結構,但不保護它的視窗。區別在於,該語句使用了命名的參數,對省略的參數沒有使用空白預留位置。因此,當某方法帶有多個可選的參數,但在VBA語句中只需使用其中的一些參數時,使用命名的參數,可以不必對省略的參數使用空白預留位置,且使代碼更具可讀性。注意,在參數名和參數值之間用“:=”串連。
還有一種情況,對象的屬性(和方法)可能返回一個值。對於返回一個值的屬性(和方法)來說,必須用括弧將參數括起來。例如,Range對象的Address屬性返回一個值即儲存格範圍的引用地址,該屬性帶有5個可選的參數。若寫成下面的語句:
Range(“A1”).Address False,由於參數缺少括弧,所以會出現錯誤。正確的表達如下:
Range(“A1”).Address(False)
或使用命名的參數Range(“A1”).Address(rowAbsolute:=False)。
■ 集合的方法和屬性
集合對象一般有特殊的屬性和可以用來管理該對象的方法。通常,集合對象有Add方法、Item方法和Remove方法,總有一個Count屬性用來返回集合中的對象個數。
對象小結
下面,對前面所描述的知識作一個簡短的小結。
■ 在Excel中,Application對象代表Excel應用程式本身,其它的對象都從它開始。每個對象都有自已的方法和屬性,並且某些對象的一些方法和屬性是相同的。
■ 在通常情況下,我們認為先需要選擇對象,然後再對所選對象進行處理,宏錄製器就是這樣的。事實上,在不進行選擇的情況下,直接在對象上執行動作將會更有效且運行快速。
■ 在大多數情況下,需要通過引用對象所在的集合間接地引用某個對象。例如,Workbooks(“Book1.xls”)在活頁簿集合中引用名為Book1的Workbook對象。
■ 屬性可以返回對另一個對象的引用,一定要認識到這一點。例如,語句Range(“A1”).Font.Bold=True中,Font屬性返回Range對象中所包含的一個Font對象。
■ 要引用一個對象,可以使用很多不同的方法。您可以根據程式運行所處的實際環境,以方便和易於理解為原則,確定具體使用何種方法。
對象的事件
Excel物件模型帶有物件導向編程的特點,但VBA也致力於事件驅動的編程模型。當某對象上的一個事件發生時,相應的程式運行。事件可以由應用程式觸發,也可以是在進行某個操作時產生。
例如,在VBE編輯器的工程視窗中,雙擊Microsoft Excel物件模型下面的ThisWorkbook對象,在右側代碼視窗頂部有兩個下拉式清單方塊,其左側為對象列表,右側為過程列表。選擇左側對象列表中的對象,右側列表中則相應列出響應該對象的事件。
可以利用對象的事件定製應用程式。例如,當開啟活頁簿時顯示歡迎視窗,這需要選擇ThisWorkbook對象的Open事件,在Private Sub Workbook_Open()過程中調用顯示歡迎視窗的程式。
處理對象和集合的兩個重要語句
您如果要想使用VBA有效地處理Excel物件模型,則需要經常使用With…End With語句和For Each…Next語句,它們可以簡化對對象和集合的處理。
■ With … End With語句
With … End With語句可以對某個對象執行一系列的操作,而不必重複指出該對象的名稱。其文法為:
With <對象>
[語句代碼]
End With
其中,<對象>表示With語句要執行操作的具體對象,[語句代碼]為對某對象執行操作的一條或多條語句,前面以點運算子開頭。
考慮下面的程式,該程式對當前活頁簿中的工作表Sheet1上的儲存格範圍A1:B10進行操作,設定該地區的字型樣式、字型大小、底線、以及字型顏色等屬性。
Sub 設定格式1()
Worksheets(“Sheet1”).Range("A1:B10").Font.Name = "Arial"
Worksheets(“Sheet1”).Range("A1:B10").Font.FontStyle = "Bold Italic"
Worksheets(“Sheet1”).Range("A1:B10").Font.Size = 10
Worksheets(“Sheet1”).Range("A1:B10").Font.Underline = xlUnderlineStyleSingle
Worksheets(“Sheet1”).Range("A1:B10").Font.ColorIndex = 3
End Sub
該過程可以使用With…End With語句來重新編寫,如下面的程式執行與上面程式完全一樣的操作:
Sub 設定格式2()
With Worksheets(“Sheet1”).Range("A1:B10").Font
.Name = "Arial"
.FontStyle = "Bold Italic"
.Size = 10
.Underline = xlUnderlineStyleSingle
.ColorIndex = 3
End With
End Sub
不能用一個With…End With語句來設定多個不同的對象,但可以將With塊放在另一個之中而產生嵌套的With語句,使用時必須在內層的With塊中使用完整的對象引用來指出在外層的With塊中的對象的成員,例如:
With MyObject ‘MyObject是一個對象的名稱
.Height = 100 ‘ 和 MyObject.Height 語句作用相同
.Caption = "Hello World" ‘ 和 MyObject.Caption語句作用相同
With .Font
.Color = Red ‘ 和 MyObject.Font.Color語句作用相同
.Bold = True ‘ 和 MyObject.Font.Bold語句作用相同
End With
End With
註:本樣本及下面的兩個樣本均來自於VBA協助系統。
提示 一般來說,建議您不要跳入或跳出With塊。如果在With塊中的語句被執行,但是With或End With 語句並沒有執行,則一個包含對該對象引用的臨時變數將保留在記憶體中,直到您退出該過程。
使用With語句,不僅能避免您反覆輸入相同的代碼,使您的程式碼更簡潔,而且更重要的是,能使您的程式運行得更快。在上面的“設定格式”程式中,可稍微感覺到兩個程式之間速度的差異,若資料量再加大,則這種運行速度之間的差異更明顯。
再舉兩個例子以加深對With…End With語句的認識。
下面的樣本將在當前活頁簿上的工作表Sheet1的儲存格範圍A1至C10中的儲存格都填入數值30,儲存格中的字型使用黑體格式,並將內部儲存格顏色設定成黃色。
Sub FormatRange()
With Worksheets("Sheet1").Range("A1:C10")
.Value = 30
.Font.Bold = True
.Interior.Color = RGB(255, 255, 0)
End With
End Sub
下面是With語句嵌套使用的例子,將With語句嵌套使用將更具有效率。樣本在活頁簿Book1上的工作表Sheet1中的儲存格A1中插入一個公式,然後格式化該儲存格中的字型。
Sub MyInput()
With Workbooks("Book1").Worksheets("Sheet1").Cells(1, 1)
.Formula = "=SQRT(50)"
With .Font
.Name = "Arial"
.Bold = True
.Size = 8
End With
End With
End Sub
■ For Each … Next 語句
For Each…Next語句遍曆集合或數組中的每個元素,重複執行語句中的代碼。其文法為:
For Each <元素> In <集合/數組>
[語句代碼]
[Exit For]
[語句代碼]
Next [元素]
其中,<元素>為必要參數,表示用來遍曆集合或數組中所有元素的變數;<集合/數組>表示對象的集合或數組的名稱;[語句代碼]為選擇性參數,為對集合或數組中每一元素執行操作的代碼;[Exit For]語句為中途退出迴圈;Next後的[元素]可省略。
當集合或數組中至少存在一個元素時,應會進入For Each…Next語句。首先針對集合或數組中的第一個元素執行For Each…Next語句中的代碼,然後針對第二個元素執行語句代碼,當集合或數組中的所有元素都執行完畢後,便會退出迴圈。如果在迴圈中的語句代碼放置Exit For語句,執行到此語句時,便會退出迴圈;Exit For語句通常放在條件判斷語句中。
可以將一個For Each…Next語句放在另一個For Each…Next語句中組成嵌套的迴圈。在每個For Each…Next語句中的<元素>變數應該不同。
下面舉幾個例子來說明For Each…Next語句的用法。
下面的樣本引自VBA協助系統。它使用For Each...Next語句搜尋集合中的所有成員的Text 屬性,尋找“Hello”字串。在樣本中,MyObject是面向文本的對象,並且是MyCollection集合的成員,這兩個名字都是為示範目的而使用的通用名稱,可用實際的對象賦值後在VBE編輯器中調試。
Sub Sample()
Dim Found, MyObject, MyCollection
Found = False ‘ 設定變數初始值。
For Each MyObject In MyCollection ‘ 對每個成員作一次迴圈
If MyObject.Text = "Hello" Then ‘ 判斷Text屬性的值是否等於“Hello”
Found = True ‘如果Text屬性的值是否等於“Hello”,則將變數Found的值設成True
Exit For ‘ 退出迴圈
End If
Next
End Sub
下面的樣本顯示當前活頁簿中所有工作表的名字,用MsgBox函數顯示。如果當前活頁簿中有3個工作表,則迴圈3次,相應地3次調用MsgBox函數。
Sub 顯示工作表名()
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
MsgBox ws.Name
Next ws
End Sub
下面的樣本關閉除當前活頁簿之外的所有活頁簿,在代碼中使用了If…Then語句來判斷活頁簿是否為當前活頁簿,若不是當前活頁簿,則關閉該活頁簿。
Sub 關閉活頁簿()
Dim wb As Workbook
For Each wb In Workbooks
If wb.Name <> ActiveWorkbook.Name Then wb.Close
Next wb
End Sub
下面的樣本需要選在工作表中選擇某儲存格範圍後,再運行代碼。程式將在所選儲存格範圍儲存格中迴圈,並將每個儲存格的值使用VBA的UCase函數轉換成大寫字母。
Sub 轉換成大寫()
Dim Cell As Range
For Each Cell In Selection
Cell.Value = UCase(Cell.Value)
Next Cell
End Sub
如何獲得協助
在使用VBA編寫代碼的過程中,難免會碰到問題,這時就需要協助了。除求助於別人外,其實在Excel中就帶有很好的協助系統,至少有以下三種方式。
■ 錄製宏。通過錄製宏,與所進行的操作過程相比較,能很好地學習如何使用對象、方法和屬性的相關知識。
■ 使用VBA協助系統。這裡有關於Excel的對象、方法、屬性以及其它知識的詳細資料。您可以在VBE編輯器的右上方“鍵入需要協助的問題”文字框中輸入關鍵字後按Enter鍵,VBE將會顯示出搜尋到的所有相關的結果,您可以從中選擇想要看的主題。單擊所選擇的主題後,會彈出關於這個主題的資訊,您還可以在其中點擊“參閱”、“樣本”、“應用於”、“特性”等文字連結,查看更詳細的資訊。
■ 使用“物件瀏覽器”。在VBE編輯器中,選擇菜單“視圖——物件瀏覽器”或按F2鍵或選擇工具列上的“物件瀏覽器”按鈕,將會顯示出“物件瀏覽器”視窗。在這裡,為每個可用的對象列出了所有的方法、屬性和事件,可查看項目中的過程和常量。其中,飛行的小立方體表徵圖表明該成員是一個方法,亮的閃電表徵圖表明該成員是一個事件,索引卡表徵圖表明該成員是一個屬性。您可以選擇物件程式庫,在搜尋方塊中輸入想要搜尋的值。在搜尋結果視窗中是顯示出相匹配的文本,選擇一個對象後,在“類”視窗中顯示它的類,選擇一個類後,在右側將會顯示它的成員,包括方法、屬性和常量。在底部的視窗中,顯示了有關該對象的更多資訊。可以按F1鍵或單擊?號表徵圖直接進入該對象的說明主題。
除了提供查看Excel物件模型的方法外,“物件瀏覽器”也允許您查看自已正在開發的工程的資訊,可方便地快速探索工程中的所有組件及特定過程的詳細資料。
VBA物件模型(2)