VBA函數中ByVal和ByRef的區別與應用技巧
當前位置:點晴教程→知識管理交流
→『 技術文檔交流 』
一、ByVal和ByRef基礎 ByVal和ByRef是用于限定VBA函數(Function)或子過程(Sub)(以下統稱為函數)參數傳遞方式的關鍵字。它們決定了在調用函數時,參數是按值傳遞還是按引用傳遞。形如:
ByVal(By Value)限定參數a按值傳遞數據。 ByRef(ByReference)限定參數b按引用傳遞數據。 在VBA中,ByRef為默認(省略關鍵字時的)值。如果僅看上面這些一板一眼的說明,對于沒有編程基礎的人,是非常難理解的。 以下這個test函數使用了ByVal參數和ByRef參數,通過示例mExample過程來展示使用這兩個參數傳遞數據以后發生的變化:
示例運行后的結果:
通過示例,再次理解一下: ByVal傳遞的只是值,相當于將變量a的副本傳入函數,無論函數中怎樣改變a的值,在函數外部,都不會影響變量a原始的值; ByRef傳遞的卻是引用(即:變量的內存地址,可以理解為變量自身),在函數中對變量b的重新計算、賦值,都會改變實體變量b的值,所以經過函數的洗禮,這個b變量的值已是物是人非,也不再是它的初始值了。 二、ByVal和ByRef進階 以上的基礎不足以滿足我們對ByVal和ByRef的好奇心。 1、我們注意到,以上示例向函數中傳遞的都是變量,所以才存在這種區別。換句話說,ByVal和ByRef只是對變量參數產生影響,如果函數接收的是兩個常量值:
那么使用ByVal、ByRef的結果是一樣的,VBA也不會報錯。只是這樣做會失去函數設置ByRef限定的意義而已。 ByVal參數設計的初衷,是要接收一個變量或一個具體的常量值。而ByRef參數設計的初衷,是要接收一個變量。 2、既然能讓ByVal、ByRef發揮作用的是傳遞變量,那么又要看這個變量屬于什么類型。下面對普通變量(如上述示例)、數組變量、對象變量分別說明: (1)普通變量,最常使用的一種變量,它的變化情況如上述示例。 (2)數組變量,如果函數的參數是一個數組,則必須傳遞ByRef。 (3)對象變量,同樣只能傳遞ByRef,不能使用ByVal來按值傳遞,VBA不支持對象按值傳遞。 3、對于函數中使用的ByRef傳遞方式,目的可以有兩個:一是要使用這個參數值;二是要改變這個參數值。在實際運用中,這兩項目的并不是每次都想要達成的。 例如,函數設計中使用了ByRef,但是在使用時偶爾又需要只傳遞變量的值,而不要改變參數原始的變量值。 一種方法是使用一個第三方變量,其實就是設置一個變量副本,從而間接保護原來的變量:
這個方法看似笨拙,但很有效。 第二種方法是變量作為參數時,使用小括號(看著要高級一些)括起來:
重點是這個(b),即在傳遞b變量時,使用小括號括起來,這時就會臨時性只傳遞變量b的值(使其變成了ByVal參數),而不會對原實體變量b造成傷害。 使用小括號的方法,同樣適用于數組變量參數。如果要獲取函數的返回值,就需要兩層括號了,類似這種形式:test(a, (b))。 ByRef總結:如果函數的參數使用了ByRef關鍵字,就傳遞一個變量的引用(地址,會改變原變量的值),如果對這個關鍵字參數只想傳遞值,可以將變量單獨用小括號括起來,這樣就只傳遞變量的值,不會修改變量的原始值,也可以直接使用一個實體的變量副本。 三、ByRef應用技巧 當我們了解了ByVal和ByRef的原理后,在編寫VBA代碼時,就需要加以注意了。因為參數的限定關鍵字被省略時,默認是ByRef傳遞。 通常我們只是使用這個參數傳遞的值,而不會在函數中對參數進行運算、賦值等動作,所以使用ByVal或ByRef可能感覺不到有什么區別。如果一個函數中傳遞的變量在該函數運行后,仍需要調用它,就需要注意是否是ByRef傳遞。 其實,利用ByRef傳遞,在函數中對傳遞的變量進行賦值等操作,有時候會收到奇特的效果,如下示例函數(根據身份證號獲取生日,同時根據需要獲取性別信息):
調用該函數時:
不知道你看清這個操作沒有,通過將ByRef參數設置一個可選參數,在函數中對該參數賦值。 使用時,如果沒有特別的要求,只想得到函數的返回值,就省略該參數,也不會影響函數正常發揮。如果想得到這個經過函數洗禮后的變量的值,就如上述示例中所做,這樣,就能夠通過一個函數,同時獲取到多個返回值的奇特效果。 我們在使用一些API函數時也會遇到這些情形,非常實際的技巧。 閱讀原文:原文鏈接 該文章在 2025/1/24 9:26:18 編輯過 |
關鍵字查詢
相關文章
正在查詢... |