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