過程是指由一組完成指定任務(wù)的VBA語句組成的代碼集合。在VBA中,可執(zhí)行的代碼都必須放置在過程中。VBA中的過程可分為事件過程、屬性過程和通用過程。
事件過程是當發(fā)生某個事件(如單擊、雙擊)時,對該事件做出響應的程序段。事件過程位于對象所在模塊中,例如有關(guān)工作簿的事件代碼放置在ThisWorkbook對象的代碼模塊中。在打開工作簿時將調(diào)用的程序代碼可放置在Workbook對象的Open事件中,如圖9-1所示。
有時在不同的事件過程中需要執(zhí)行一段相同的代碼,可以把這段代碼獨立出來,作為一個過程,這樣的過程稱為“通用過程”。在VBA中,通用過程又分為兩類:Sub(子程序)過程和Function(函數(shù))過程。
在使用之前,需要先在模塊中定義過程。VBA中有兩種定義過程的方法:一種方法是使用窗體創(chuàng)建過程的結(jié)構(gòu),再在過程中編寫相應的代碼;另一種方法是在模塊中直接輸入代碼來定義過程?!?/div>
9.2.1 添加過程
通用過程一般保存在模塊中,在創(chuàng)建過程前可先通過選擇“插入”ㄧ“模塊”命令向工程中添加一個模塊。VBA開發(fā)環(huán)境中提供了一個“添加過程”對話框,通過該對話框可方便地向當前模塊中添加過程。具體操作步驟如下。
步驟1 在VBE環(huán)境中選擇“插入”ㄧ“過程”命令,打開如圖9-2所示的“添加過程”對話框。
使用圖9-2所示對話框除了可以插入一個新的Sub過程、Function過程或?qū)傩赃^程,還可以設(shè)置Public或Private有效范圍,并使得過程中所有的局部變量成為靜態(tài)變量。
步驟2 在“名稱”文本框中輸入過程的名稱。
步驟3 在“類型”中選擇“子程序”單選按鈕。它有三種類型可以選擇:
●子程序,為Sub過程;
●函數(shù),為Function過程;
●屬性,為Property過程。
步驟4 在“范圍”中選中“公共的”單選按鈕,設(shè)置過程為全局的(即在工程的各模塊中都可以調(diào)用該過程),將在過程前面添加Public關(guān)鍵字。還可根據(jù)需要選中下方的“把所有局部變量聲明為靜態(tài)變量”復選框,如果選中該復選框,將在過程名前面添加Static關(guān)鍵字。
步驟5 設(shè)置好以上參數(shù)后,單擊“確定”按鈕,VBA將自動生成過程的結(jié)構(gòu)代碼,如圖9-3所示。
在該過程結(jié)構(gòu)中編寫以下代碼:
Public Sub TestSub()
MsgBox "這是使用對話框創(chuàng)建的Sub過程!"
End Sub
9.2.2 使用代碼創(chuàng)建Sub過程
大多數(shù)開發(fā)人員更習慣于通過手工輸入的方式來創(chuàng)建Sub過程,因為這更利于了解創(chuàng)建Sub過程中各元素的作用。Sub過程的結(jié)構(gòu)如下:
[Private ㄧPublic ㄧFriend] [Static] Sub 過程名 [(參數(shù)列表)]
[語句序列1]
[Exit Sub]
[語句序列2]
End Sub
過程由Sub和End Sub及之間的VBA代碼構(gòu)成。其中在Sub前面可加上限制過程作用域的關(guān)鍵字,主要有以下幾個:
●Privat,表示只有在包含其聲明的模塊中的其他過程可以訪問該Sub過程。
●Public,表示所有模塊的所有其他過程都可訪問這個Sub過程。如果在Sub前面省略關(guān)鍵字,則表示其為Public。
●Friend,只能在類模塊中使用,表示該Sub過程在整個工程中都是可見的,但對象實例的控制者是不可見的。
●Static,表示在調(diào)用時保留Sub過程的局部變量的值。Static屬性對在Sub之外聲明的變量不會產(chǎn)生影響,即使過程中也使用了這些變量。
注意:每一個過程都必須對應一個名稱,通過過程名稱可以調(diào)用該過程。過程名稱的命名應符合標識符命名規(guī)則。
End Sub語句標志著Sub過程的結(jié)束。為了能正確運行,每個Sub過程必須有一個End Sub語句,當程序執(zhí)行到該語句時就結(jié)束該過程的運行。另外,在過程中可以使用一個或多個Exit Sub語句直接退出過程的執(zhí)行。
注意:Sub過程的定義不能嵌套,即不能將過程的定義放在另一個過程中。
在了解了Sub過程結(jié)構(gòu)及各語句的作用后,就可在代碼窗口中創(chuàng)建Sub過程了。具體操作步驟如下。
步驟1 雙擊“工程資源管理”窗口中的“模塊1”,打開代碼窗口。
步驟2 在代碼窗口中輸入“Sub手工創(chuàng)建Sub過程”,并按回車鍵。
步驟3 系統(tǒng)自動在過程名后面添加一對括號,并自動生成“End Sub”語句,如圖9-4所示。
步驟4 在過程結(jié)構(gòu)中輸入以下代碼:
Sub 手工創(chuàng)建Sub過程()
MsgBox "這是手工輸入代碼創(chuàng)建的Sub過程!"
End Sub
9.3 調(diào)用Sub過程
使用過程的目的就是將一個應用程序劃分為多個小模塊,每個小模塊完成一個具體的功能,最后通過組合這些過程來完成一個大任務(wù)。
在VBA中,通過調(diào)用定義好的過程來執(zhí)行程序。Sub過程的調(diào)用分兩種方式:一種是在VBA代碼中調(diào)用Sub過程;另一種是在Excel中以調(diào)用宏的方式來執(zhí)行Sub過程。
93.1 調(diào)用Sub過程
在程序中調(diào)用Sub過程有兩種方式:一是把過程名字放在一個Call語句中,另一種是把過程名作為一個語句來使用。
1. 用Call語句調(diào)用Sub過程
用Call語句可將程序執(zhí)行控制權(quán)轉(zhuǎn)移到一個Sub過程或Function過程中,在過程中遇到End Sub或Exit Sub語句后,再將控制權(quán)返回到調(diào)用程序的下一行。Call語句的語法格式很簡單:
Call 過程名(過程參數(shù)列表)
如果使用Call語句來調(diào)用一個需要參數(shù)的過程,“參數(shù)列表”必須要加上括號;如果過程沒有參數(shù),可省略過程名后的括號。例如,以下代碼:
Call TestSub
將調(diào)用上節(jié)定義的過程“TestSub”。
2. 將過程作為一個語句
在調(diào)用過程時,如果省略Call關(guān)鍵字,過程也可調(diào)用。與使用Call關(guān)鍵字不同的是,如果過程有參數(shù),這種調(diào)用方式必須要省略“參數(shù)列表”外面的括號。例如:
Call Test(a,b)
可改為以下形式:
Test?。?,b
下面以實例演示Sub過程的定義和調(diào)用。本例首先創(chuàng)建一個名為“延時”的過程,該過程根據(jù)傳遞的參數(shù)來決定程序延時的長度;然后再創(chuàng)建一個調(diào)用“延時”過程的過程,具體步驟如下。
步驟1 在“模塊1”中輸入以下代碼:
Sub 延時(ByVal DelayTime As Integer)
Dim NewTime As Long '保存延時到達的時刻
NewTime = Timer + DelayTime '計算延時后的時刻
Do While Timer < NewTime '如果未達到規(guī)定的時間,空循環(huán)
Loop
End Sub
程序中使用Timer函數(shù)獲得系統(tǒng)從午夜開始計算的秒數(shù)(數(shù)值較大,需將NewTime變量聲明為Long,用Integer類型的話將出現(xiàn)溢出),把這個時間加上需要延時的秒數(shù),得到延時到達時的秒數(shù);然后程序通過一個空循環(huán)語句反復檢查是不是超過這個時間,超過就退出程序,達到延時的效果。
步驟2 接著輸入以下測試過程的代碼:
Sub 測試延時()
Dim?。锳s Integer
i= Val(InputBox("開始測試延時程序,請輸入延時的秒數(shù):","延時測試",1))
延時 i
MsgBox?。⒁蜒訒r"?。Α。椤。Α。⒚?。"
End Sub
該過程要求用戶輸入需要延時的時長,然后調(diào)用“延時”過程,該過程執(zhí)行完畢后,返回調(diào)用過程執(zhí)行下一條語句(用MsgBox顯示一條提示信息)。程序中使用
延時?。?/div>
的方式來調(diào)用過程,也可使用Call的方式,代碼如下:
Call 延時(i)
使用Call語句,就需要將參數(shù)i用括號引起來。
9.3.2 以宏方式調(diào)用Sub過程
在Excel中錄制宏時,將創(chuàng)建一個Sub過程,所以也可將Sub過程作為一個宏來調(diào)用。具體步驟如下。
步驟1 切換到Excel工作界面(或關(guān)閉VBE環(huán)境)。
步驟2 在工作表中繪制一個按鈕,打開如圖9-5所示的“指定宏”對話框。
步驟3 在對話框中選擇宏“手工創(chuàng)建Sub過程”,單擊“確定”按鈕,即可將該宏與插入的按鈕綁定在一起。單擊該按鈕執(zhí)行“手工創(chuàng)建Sub過程”過程。
注意:以宏方式調(diào)用Sub過程無法給過程傳遞參數(shù),所以需用參數(shù)的過程不會顯示在圖9-5所示的宏列表中。
9.4 傳遞參數(shù)
為了使過程更具有通用性,很多過程都需要設(shè)置參數(shù)。傳遞不同的參數(shù)給過程,可使執(zhí)行的結(jié)果不同。對于有參數(shù)的過程,在調(diào)用時必須將實際參數(shù)傳遞給過程,完成形參與實參的結(jié)合,過程再使用實參執(zhí)行代碼。
9.4.1 形參與實參的結(jié)合
形參是形式參數(shù)的簡稱,是在Sub過程的定義中出現(xiàn)的變量名。因其沒有具體的值,只是形式上的參數(shù),所以稱為形參。
實參是實際參數(shù)的簡稱,是在調(diào)用Sub過程時傳遞給Sub過程的值。在VBA中實參可為常量、變量、數(shù)組或?qū)ο箢惖臄?shù)據(jù)。在VBA中,形參與實參的結(jié)合有兩種方式。
1. 按位置結(jié)合
大多數(shù)程序語言調(diào)用子過程時都位置結(jié)合形參與實參。在這種方式下,調(diào)用Sub過程時使用的實參次序必須與定義Sub過程時設(shè)置的參數(shù)次序相對應。例如,使用以下代碼定義Sub子過程:
Sub Test(argl As Integer, arg2 As Long,arg3 As String)
……
End Sub
子過程中定義了三個參數(shù),可使用以下語句調(diào)用該子過程:
Call Test(1,2,"abc")
此時,Test子過程的形參與實參的結(jié)合如圖9-6所示。
2. 按命名參數(shù)方式結(jié)合
形參與實參的另一種結(jié)合方式是按形參名稱來進行,即在調(diào)用Sub過程時,輸入形參的名稱,將形參名稱與實參用“:=”符號連接起來。與按位置結(jié)合方式不同,使用這種方式時,調(diào)用過程的參數(shù)位置可隨意設(shè)置。
例如,使用名結(jié)合的方式調(diào)用上面定義的“Test”子過程:
Call Test(arg1:=1, arg3:="abc", arg2:=2)
或
Call Test(arg3:="abc", arg1:=1, arg2:=2)
都可得到同樣的效果。
按命名參數(shù)方式結(jié)合形參和實參,在輸入代碼時要增加一些工作量,但其好處也顯而易見;通過這種方式可改變過程調(diào)用的可讀性,減少程序出錯的相對性。
9.4.2 傳地址
在VBA中,實參可通過兩種方式將數(shù)據(jù)傳遞給形參,即傳地址和傳值。傳地址是VBA默認的方式,在定義過程時,如果在形參前面有關(guān)鍵字ByRef,則該參數(shù)通過傳地址的方式傳遞。
傳地址是指將實參變量的地址傳遞給形參,這讓形參和實參都代表同一個內(nèi)存區(qū)域。所以,在過程中對形參的值進行了改變,返回到調(diào)用程序后,使用實參變量名也可訪問到改變后的值。例如,有以下子過程,形參使用傳地址方式進行傳遞。
Sub 傳地址測試(ByRef?。帷s Integer)
a=a+1
Debug.Print "子過程中的變量A=" & a
End Sub
使用以下過程調(diào)用“傳地址測試”子過程。
Sub 調(diào)用過程()
Dim?。狻s Integer
?。猓?
Debug.Print"主程序中變量B=" & b
傳地址測試 b
Debug.Print "主程序中變量B=" & b
End Sub
程序首先給變量b賦初始值,并輸出變量b的值(為3),接著調(diào)用“傳地址測試”子過程,使用傳地址方式傳遞變量,使子過程的形參變量a的地址與調(diào)用過程中的實參變量b的地址相同。在子過程中將變量a增加1,并輸出變量a的值(為4),返回調(diào)用過程后,因為變量b和為題a是指向同一內(nèi)存單元的,所以變量b的值也為4。
運行以上程序后,“立即窗口”的顯示結(jié)果如圖9-7所示。
前面說過,Sub過程不能返回運算結(jié)果。如果需要Sub過程返回值時,通過使用ByRef方式來定義形參就可將子過程的運算數(shù)據(jù)返回到調(diào)用程序中。
注意:當形參定義為ByRef形式時,只有當實參為一個變量時,才能按傳地址方式傳遞參數(shù);如果實參為一個表達式或常量,則不能按地址方式傳遞參數(shù)。
9.4.3 傳值
傳值就是將實參的值作為一個副本,賦值給形參(相當于執(zhí)行一次賦值操作),而不是傳送實參的地址給形參。定義過程時,在形參的前面添加ByVal關(guān)鍵字,則該參數(shù)就按傳值方式傳遞,否則用傳地址方式傳遞。
使用傳值方式傳遞參數(shù)時,傳遞的只是變量的副本。如果過程改變了形參的值,所做改變也只在過程內(nèi)部起作用,不會影響到調(diào)用程序中變量的值。例如,將上例中的代碼改寫為以下形式:
Sub 傳值測試(ByVal?。帷s Integer)
a=a+1
Debug.Print "子過程中的變量A=" & a
End Sub
過程中用ByVal關(guān)鍵字將參數(shù)傳遞定義為傳值方式:
Sub 調(diào)用傳值測試()
Dim?。狻s Integer
b=3
Debug。Print "主程序中變量B=" & b
傳值測試 b
Debug.Print "主程序中變量B=" & b
End Sub
執(zhí)行以上過程后“立即窗口”顯示的內(nèi)容如圖9-8所示。
從圖9-8的運行結(jié)果可以看出,主程序中的變量b和子過程中的變量a之間是被隔離的,即在子過程中改變了變量a的值的情況下,并不會影響主程序中的變量b的值。
在程序中使用傳地址比傳值效率高,但是傳地址方式中,形參不是一個真正的局部變量,有可能對程序產(chǎn)生不必要的影響。如果沒有特殊要求,應盡量使用傳值方式。
9.4.4 傳遞數(shù)組參數(shù)
數(shù)組作為在內(nèi)存中的一片連續(xù)區(qū)域,也可作為一個參數(shù)傳遞給Sub子過程進行處理。數(shù)組一般是通過傳地址方式進行傳遞的。例如,編寫一個求數(shù)組中最大數(shù)的過程。
Sub 求最大數(shù)(a() As Integer)
Dim i As Integer,max As Integer
max = a(LBound(a))
For i = LBound(a) To UBound(a)
If a(i) > max Then max = a(i)
Next
Debug.Print "最大數(shù):" & max
End Sub
在該過程中,將形參定義為一個數(shù)組。使用數(shù)組作為形參時,必須輸入數(shù)組名并跟上一對空括號。對傳遞過程的數(shù)組,應使用LBound函數(shù)和UBound函數(shù)獲取其下標的下界和上界,然后程序才能遍歷數(shù)組,或?qū)?shù)組,進行其他相關(guān)的操作。
在本例中,將最大值保存在另一個變量max和每個數(shù)組元素進行比較,如果數(shù)組元素比max大,則將其值賦給max ,確保max中始終保存著最大數(shù)。
接下來編寫調(diào)用“求最大數(shù)”的代碼:
在程序中,調(diào)用“求最大數(shù)”子過程,并將數(shù)組MyArray作為參數(shù)傳遞到該子過程中進行處理。
9.5 可選參數(shù)和可變參數(shù)
在創(chuàng)建VBA的過程時,除了可使用前面介紹的方法設(shè)置參數(shù)按地址或按值傳遞之外,還可以根據(jù)需要為過程設(shè)置可選參數(shù)和可變參數(shù)。
9.5.1 可選參數(shù)
通常情況下,一個VBA過程中的形參數(shù)量是固定的,調(diào)用時提供的實參數(shù)量也是固定的。在有的過程中,可能有必需收集信息和可選信息,如收集顧客的信息時必須提供“姓名”、“性別”,而“身份證號碼”則是可選的(可提供,也可不提供)。
?。郑拢恋倪^程可以通過在形參前面加上Optional關(guān)鍵字來設(shè)置該形參為可選參數(shù)。在過程內(nèi)部通過使用IsMissing函數(shù)可測試調(diào)用程序是否傳遞了該可選。例如:
該過程有三個參數(shù),前兩個參數(shù)為必須使用的,最后一個參數(shù)使用了Optional關(guān)鍵字,表示該參數(shù)是可選參數(shù)。調(diào)用該過程時,可以提供兩個參數(shù),也可以提供三個參數(shù):
'可選參數(shù) "王小鳳","女"
或:
可選參數(shù) "王小鳳","女","410214198501012345"
注意:過程中可定義多個可選參數(shù),但可選參數(shù)必須放在參數(shù)表的最后,而且必須是Variant類型。
9.5.2 可變參數(shù)
無論是固定參數(shù)還是可選參數(shù),在定義過程時都已經(jīng)指定了參數(shù)的個數(shù)。在VBA中,還可以定義可變參數(shù),即參數(shù)的個數(shù)在定義時是未知的。
在定義過程的參數(shù)表時,在最后一個參數(shù)前面加上ParamArray關(guān)鍵字,過程將接受任意個數(shù)的參數(shù)。例如,使用可變參數(shù)編寫求和函數(shù)SUM.
科學試驗中定義了兩個形參,第一個用于返回計算的結(jié)果;第二個參數(shù)使用ParamArray關(guān)鍵字將其定義為可變參數(shù)。
可變參數(shù)為一個數(shù)組。程序中使用LBound函數(shù)和UBound函數(shù)獲得數(shù)組下標的上下界,然后進行累加,并將累加的結(jié)果保存在第一個參數(shù)中,用于返回給調(diào)用程序。
調(diào)用以上子過程的代碼如下:
程序中定義了一個變量i,用來獲得子過程運算的結(jié)果。
參數(shù)傳遞時,將參數(shù)i用傳地址方式傳遞給“MySum”子過程的形參intTotal,將后面的“1,2,3,4,5,6,7,8”作為一個數(shù)組傳遞給形參intNum。
注意:ParamArray只能用于參數(shù)列表的最后一個參數(shù),指明最后這個參數(shù)是一個Variant元素的Optional數(shù)組。ParamArray關(guān)鍵字不能與ByVal,
ByRef,或Optional一起使用。
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請
點擊舉報。