VBA傳遞參數(shù)步驟

2021-12-08 14:27 更新

到目前為止,你已經(jīng)創(chuàng)建了簡單的可以執(zhí)行具體任務的VBA過程,這些過程在它們運行前沒有要求你提供額外的數(shù)據(jù)。然而,在現(xiàn)實生活中,過程(子程序和函數(shù))經(jīng)常需要參數(shù)。參數(shù)(自變量)是過程工作時需要的一個或多個數(shù)值。參數(shù)通常輸入在括號之間,多個參數(shù)用逗號分割開來。使用Excel有一陣了,你已經(jīng)知道Excel內(nèi)置函數(shù)根據(jù)你提供的數(shù)據(jù)可能產(chǎn)生不同的結果。例如,如果單元格A4和A5分別含有數(shù)字5和10,加和公式=SUM(A4:A5)將會返回15,除非你更改單元格里面的數(shù)值。正如你可以傳遞數(shù)值給Excel內(nèi)置函數(shù),你也可以傳遞數(shù)值給自定義VBA過程。



現(xiàn)在,我們來看看如何從子程序傳遞數(shù)值給函數(shù)SumItUp。這個自定義函數(shù)目的是計算一個人的姓和名的字母數(shù)目。


1.在放置函數(shù)SumItUp的模塊里輸入下列子程序NumOfCharacters:


Sub NumOfCharacters()


            Dim f As Integer


            

Dim l As Integer


            

f = Len(InputBox("Enter first name:"))


            

l = Len(InputBox("Enter last name:"))


            

MsgBox SumItUp(f,l)


End Sub


2.  將光標放在過程NumOfCharacters的任意地方并按下F5。VB將顯示信息輸入框問你名字,這個信息框由下面的函數(shù)產(chǎn)生:


InputBox("Enter first name:")


3.  輸入任何名字,回車,VB接受你輸入的文本并且將它作為一個參數(shù)傳遞給函數(shù)Len。函數(shù)Len計算提供的文本的字母數(shù)目。VB將函數(shù)Len的結果儲存于變量f以供以后使用。這之后,VB顯示下一個信息框,這次是問你的姓。


4.  輸入任何姓,回車。VB將輸入的姓傳遞給函數(shù)Len來獲得姓的文本長度,然后數(shù)值儲存于變量l。接下來發(fā)生什么呢?VB遇到了函數(shù)MsgBox,這個函數(shù)告訴VB顯示函數(shù)SumItUp的結果。然而,因為這個結果還沒有準備好,VB很快就跳到函數(shù)SumItUp里,使用變量f和l儲存的數(shù)值來做計算。在函數(shù)內(nèi)部,VB用變量f的值取代參數(shù)m和變量l值取代參數(shù)n。一旦取代工作完成,VB將兩個數(shù)值加和起來,并且將結果返回給函數(shù)SumItUp。函數(shù)SumItUp內(nèi)部沒有其它的任務了,因此,VB又馬上返回子程序并且將函數(shù)SumItUp的結果作為一個參數(shù)提供給函數(shù)MsgBox?,F(xiàn)在這個信


息出現(xiàn)在屏幕上,顯示了字母總數(shù)目。


5.  點擊確定退出信息框,你可以多次運行過程NumOfCharacters,每次輸入不同的姓名。我們來看看另外一個使用變量傳遞參數(shù)的例子:


1.  在工程MyFunctions (Chap04.xls)里添加一個新模塊,并重命名為Sample2


2.  激活模塊Sample2并且輸入子程序EnterText:


Sub EnterText()


             Dim m As String, n As String, r As String


             

m = InputBox ("Enter your first name:")


             

n = InputBox("Enter your last name:")


             

r = JoinText(m, n)


             

MsgBox r


End Sub


3.  輸入下述函數(shù)過程:

Function JoinText(k,o)

             JoinText = k + " " + o

End Function

4.  運行過程EnterText
VB執(zhí)行語句時,它收集用戶輸入的數(shù)據(jù)并且將這些數(shù)據(jù)儲存在變量m和n上,然后傳遞這些數(shù)據(jù)到函數(shù)JoinText。VB將這些變量的值取代函數(shù)JoinText的參數(shù),并且將結果賦到函數(shù)名稱(JoinText)上。當VB返回過程EnterText時,函數(shù)的值儲存于變量r。然后,函數(shù)MsgBox在信息框里顯示變量r的內(nèi)容。結果就是用戶的完整姓名(姓和名用空格分開)。要從函數(shù)傳遞數(shù)值給子程序,需要將該值賦到函數(shù)名稱,例如,下面的函數(shù)NumOfDays將值7傳遞到子程序DaysInAWeek:

Function NumOfDays()
              NumOfDays = 7
End Function
Sub DaysInAWeek()
              MsgBox "There are " & NumOfDays & " days in a week."
End Sub

技巧:函數(shù)過程不能做什么
函數(shù)過程不能進行任何動作,例如,它們不能在工作表里做插入,刪除或設置數(shù)據(jù)格式操作,不能打開文件,或改變屏幕顯示樣式


明確參數(shù)類型

在前面的部分,你學習了函數(shù)根據(jù)它們自變量傳遞的值進行計算,當你聲明函數(shù)時,你將參數(shù)名稱列在一對括號里面。參數(shù)名稱就像變量一樣,每個參數(shù)名稱在函數(shù)調(diào)用時,引用你提供的數(shù)值。當子程序調(diào)用函數(shù)過程時,它以變量形式傳遞參數(shù)。一旦函數(shù)做點什么,它就將結果賦給函數(shù)名稱。注意,函數(shù)過程的名稱當作變量來使用。

象變量一樣,函數(shù)也有類型,函數(shù)的結果可以是字符串型,整型,長整型,等。要明確你函數(shù)的結
果類型,只有在函數(shù)聲明行后添加關鍵字As和你想要的類型即可。例如:

Function MultiplyIt(num1, num2) As Integer

如果你不明確數(shù)據(jù)類型,VB將把你的函數(shù)結果設置為默認類型(Variant數(shù)據(jù)類型)。當你明確你的函數(shù)結果的數(shù)據(jù)類型時,就象你明確變量的數(shù)據(jù)類型那樣有一些好處,你的程序?qū)⒏行У厥褂脙?nèi)存,因此它運行得也更快些。

我們來看看這個例子,盡管其參數(shù)在主調(diào)過程聲明的是單精度浮點型,但是函數(shù)仍然返回整型數(shù)據(jù):

1.  在工程MyFunctions (Chap04.xls)里添加一個新模塊,重命名為Sample3

2.  激活模塊Sample3并且輸入子程序HowMuch,如下所示:

Sub HowMuch()
        Dim num1 As Single
        Dim num2 As Single
        Dim result As Single
        num1 = 45.33
        num2 = 19.24
        result = MultiplyIt(num1, num2)
        MsgBox result
End Sub

3.  在子程序HowMuch下面輸入下列函數(shù)過程:

Function MultiplyIt(num1,num2) As Integer
       MultiplyIt = num1 * num2
End Function

因為儲存于變量num1和num2的數(shù)值不是整數(shù),要確保它們相乘后的結果為整數(shù),你就得將函數(shù)結果設置為整型。如果你不給函數(shù)MultiplyIt的結果設置數(shù)據(jù)類型,過程HowMuch將會將結果按變量,result聲明的數(shù)據(jù)類型顯示,相乘的結果將是872.1492,而不是872。

你可以在每次運行該過程時,提供它們不同的數(shù)值,來使得該函數(shù)更有用,你可以使用InputBox函數(shù)來輸入數(shù)據(jù),而不拘泥于程序代碼給定的數(shù)值。你自己可以依照前面章節(jié)中的子程序EnterText,花幾分鐘來修改過程HowMuch。

按地址和按值傳遞參數(shù)

在一些過程中,當你將參數(shù)作為變量傳遞時,VB可能突然改變該變量的數(shù)值。要確保該被調(diào)函數(shù)不改變傳遞的參數(shù)值,你應該在函數(shù)聲明行在參數(shù)名稱之前加上關鍵字ByVal。我們來看看這個例子:

1.  在工程MyFunctions (Chap04.xls)里添加一新模塊,命名為Sample4

2.  激活模塊Sample4并輸入下列代碼:
Sub ThreeNumbers()
        Dim num1 As Integer, num2 As Integer, num3 As Integer
        num1 = 10
        num2 = 20
        num3 = 30
        MsgBox MyAverage(num1,num2,num3)
        MsgBox num1
        MsgBox num2
        MsgBox num3
End Sub
Function MyAverage(ByVal num1, ByVal num2, ByVal num3)
        num1 = num1 + 1
        MyAverage = (num1 + num2 + num3) / 3
End Function

使用關鍵字ByVal在參數(shù)名稱前,可以防止函數(shù)改變參數(shù)值。子程序ThreeNumbers給三個變量賦值,再調(diào)用函數(shù)MyAverage來計算,最后計算該三個變量的平均值。函數(shù)的參數(shù)就是變量num1,num2和num3。注意,所有變量的前面都有關鍵字ByVal。同時,注意,在計算均值之前,函數(shù)MyAverage改變了變量num1的值,在函數(shù)內(nèi)部,變量num1等于11(10+1),因此,當函數(shù)將計算的均值傳遞給過程ThreeNumbers時,函數(shù)MsgBox顯示的結果是20.3333333333333而不是期望的20,接下來的三個函數(shù)顯示每個變量的內(nèi)容,變量儲存的內(nèi)容和它們開始被賦的值一致——10,20,30。

如果你在函數(shù)聲明行忽略了參數(shù)num1前面的關鍵字ByVal,結果會怎樣呢?函數(shù)的結果仍然相同,但是函數(shù)MsgBox顯示的變量num1的內(nèi)容現(xiàn)在是11了。函數(shù)MyAverage不但返回了出乎意料的結果(20.3333333333333而非20),而且改變了儲存在變量num1里的原始數(shù)值。要避免VB永久地改變提供給函數(shù)的數(shù)值,就得使用關鍵字ByVal。

技巧:了解你的關鍵字:ByRef和ByVal
因為每個要傳遞給函數(shù)過程(或子程序)的變量,都可能在接收時改變數(shù)值,所以知道如何來保護變量的原始數(shù)值是非常重要的。VB有兩個關鍵字,提供或者否認改變變量內(nèi)容的允許——ByRef和ByVal。VB默認地按地址(關鍵字ByRef)給函數(shù)過程(或子程序)傳遞信息,引用函數(shù)被調(diào)用時,函數(shù)參數(shù)明確的數(shù)據(jù)。因此,如果函數(shù)改變了參數(shù)值,原始的數(shù)值就被改變了。

如果你在函數(shù)MyAverage聲明參數(shù)num1的前面忽略了關鍵字ByVal時,你就會得到這種結果。如果你想要函數(shù)過程
改變原始數(shù)值,你不必專門在參數(shù)前加關鍵字ByRef,因為,變量數(shù)值的傳遞默認就是ByRef。當你在參數(shù)名稱前使用關鍵字ByVal時,VB按值傳遞參數(shù),這意味著VB復制一份原始數(shù)據(jù),然后將復制值傳遞給函數(shù),如果函數(shù)改變了參數(shù)的數(shù)值的話,原始數(shù)據(jù)依然不會變——只有復制值變化。這就是為什么函數(shù)MyAverage改變了變量num1的數(shù)值,而它的原始值還保持不變。


使用可選的參數(shù)

有時候,你也許要給函數(shù)提供額外的參數(shù),例如,你有一個計算每個人膳食的函數(shù)。然而,有時你不希望函數(shù)進行相同的計算。在參數(shù)名稱前面加上關鍵字Optional可以指明該參數(shù)不是必須的??蛇x參數(shù)在必須的參數(shù)之后,列在參數(shù)清單的最后;可選參數(shù)總是Variant數(shù)據(jù)類型,這意味著你不能使用關鍵字As來明確可選參數(shù)的類型。在前面部分,你創(chuàng)建了一個計算三個數(shù)值的平均值的函數(shù),假設,你有時只想要計算兩個數(shù)的均值,你就可以將第三個參數(shù)設置為可選的。為了不破壞原來的函數(shù)MyAverage,我們來創(chuàng)建一個新的函數(shù)Avg,來計算兩個或三個數(shù)字的均值:

1.  在工程MyFunctions (Chap04.xls)里添加一新模塊,命名為Sample5

2.  激活模塊Sample5并且輸入下列函數(shù):

Function Avg(num1, num2, Optional num3)
       Dim totalNums As Integer
       totalNums = 3
       If IsMissing(num3) Then
                num3 = 0
                totalNums = totalNums –1
       End If
       Avg = (num1+num2+num3)/totalNums
End Function

3.  現(xiàn)在來從立即窗口調(diào)用該函數(shù):
?Avg(2,3)

一旦你按下回車,VB就顯示結果:2.5
?Avg(2,3,5)

這次結果為:3.3333333333333

你已經(jīng)看到,函數(shù)Avg允許你計算兩個或三個數(shù)字的平均值,你可以決定計算幾個值的平均值。當你在立即窗口開始輸入函數(shù)的參數(shù)時,VB將可選的參數(shù)顯示在方括號里(方括號里的參數(shù)表示是可選的)

我們花幾分鐘來分析一下函數(shù)Avg。該函數(shù)最多可以用三個參數(shù);參數(shù)num1和num2是必須的,而第三個參數(shù)num3是可選的。注意,可選參數(shù)以關鍵字Optional開頭,可選參數(shù)列在參數(shù)清單的后面。因為參數(shù)num1,num2和num3的類型都沒有聲明,VB對待它們?yōu)閂ariant。函數(shù)內(nèi)部,變量totalNums聲明為整型,并且初始賦值為3。因為該函數(shù)必須能夠處理兩個或三個數(shù)字的平均值計算,有關很方便的內(nèi)置函數(shù)IsMissing在檢查參數(shù)的個數(shù)。如果第三個參數(shù)沒有提供,函數(shù)IsMissing的值為0,同時變量totalNums的值被減去1,因此如果沒有可選參數(shù),totalNums為2。

接下來的代碼根據(jù)提供的數(shù)據(jù)計算平均值,并且將結果傳遞到函數(shù)名稱。

函數(shù)IsMissing用來檢測可選參數(shù)是否提供,如果第三個參數(shù)沒有提供,那么該函數(shù)返回邏輯值True,如果提供了第三個參數(shù)時,則返回False。在這里,函數(shù)IsMissing是和一個做判斷的語句If…Then一起使用的(參見第五章有關該語句和VBA中其它判斷語句信息)。如果沒有參數(shù)num3(IsMissing),那么(Then)VB將num3設置為0,并且將變量totalNums減去1(totalNums=totalNums–1)。你還能使用別的方法來運行函數(shù)Avg嗎?使用你自己的方法在工作表里運行該函數(shù),確保你使用兩個和三個參數(shù)來運行該函數(shù)。

技巧:測試函數(shù)過程
可以編寫一個子程序調(diào)用自定義函數(shù),并且顯示它的結果,看它是否能得到設計結果。除此之外,
該子過程還應該能顯示參數(shù)的原始數(shù)據(jù),這樣,你才能很快知道參數(shù)數(shù)值是否改變了。如果該函數(shù)
使用了可選參數(shù),你也需要檢查不使用可選參數(shù)時候的情況。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號