LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

VBA函數中ByVal和ByRef的區別與應用技巧

admin
2025年1月23日 21:31 本文熱度 150

一、ByVal和ByRef基礎



ByVal和ByRef是用于限定VBA函數(Function)或子過程(Sub)(以下統稱為函數)參數傳遞方式的關鍵字。它們決定了在調用函數時,參數是按值傳遞還是按引用傳遞。形如:

Function GetName(ByVal a As Integer , ByRef b As Integer) As String

    '代碼區

End Function

ByVal(By Value)限定參數a按值傳遞數據。

ByRef(ByReference)限定參數b按引用傳遞數據。

在VBA中,ByRef為默認(省略關鍵字時的)值。如果僅看上面這些一板一眼的說明,對于沒有編程基礎的人,是非常難理解的。

以下這個test函數使用了ByVal參數和ByRef參數,通過示例mExample過程來展示使用這兩個參數傳遞數據以后發生的變化:

'測試用test函數:

Function test(ByVal myval As Integer, ByRef myref As Integer)

    myval = myval + 10

    myref = myref + 10

End Function

'示例子過程:

Sub mExample()

    Dim a As Integer, b As Integer

    a = 10: b = 10

    

    Debug.Print "test前: a=" & a & ",b=" & b

    test a, b

    Debug.Print "test后: a=" & a & ",b=" & b

End Sub

示例運行后的結果:

test前: a=10,b=10

test后: a=10,b=20

通過示例,再次理解一下:

ByVal傳遞的只是值,相當于將變量a的副本傳入函數,無論函數中怎樣改變a的值,在函數外部,都不會影響變量a原始的值;

ByRef傳遞的卻是引用(即:變量的內存地址,可以理解為變量自身),在函數中對變量b的重新計算、賦值,都會改變實體變量b的值,所以經過函數的洗禮,這個b變量的值已是物是人非,也不再是它的初始值了。



二、ByVal和ByRef進階



以上的基礎不足以滿足我們對ByVal和ByRef的好奇心。

1、我們注意到,以上示例向函數中傳遞的都是變量,所以才存在這種區別。換句話說,ByVal和ByRef只是對變量參數產生影響,如果函數接收的是兩個常量值:

test 100, 150

那么使用ByVal、ByRef的結果是一樣的,VBA也不會報錯。只是這樣做會失去函數設置ByRef限定的意義而已。

ByVal參數設計的初衷,是要接收一個變量或一個具體的常量值。而ByRef參數設計的初衷,是要接收一個變量。

2、既然能讓ByVal、ByRef發揮作用的是傳遞變量,那么又要看這個變量屬于什么類型。下面對普通變量(如上述示例)、數組變量、對象變量分別說明:

(1)普通變量,最常使用的一種變量,它的變化情況如上述示例。

(2)數組變量,如果函數的參數是一個數組,則必須傳遞ByRef。

(3)對象變量,同樣只能傳遞ByRef,不能使用ByVal來按值傳遞,VBA不支持對象按值傳遞。

3、對于函數中使用的ByRef傳遞方式,目的可以有兩個:一是要使用這個參數值;二是要改變這個參數值。在實際運用中,這兩項目的并不是每次都想要達成的。

例如,函數設計中使用了ByRef,但是在使用時偶爾又需要只傳遞變量的值,而不要改變參數原始的變量值。

一種方法是使用一個第三方變量,其實就是設置一個變量副本,從而間接保護原來的變量:

'示例子過程:

Sub mExample2()

    Dim a As Integer, b As Integer, c As Integer

    a = 10: b = 10: c = b

    

    Debug.Print "test前: a=" & a & ",b=" & b

    test a, c

    Debug.Print "test后: a=" & a & ",b=" & b

End Sub

這個方法看似笨拙,但很有效。

第二種方法是變量作為參數時,使用小括號(看著要高級一些)括起來:

'示例子過程:

Sub mExample3()

    Dim a As Integer, b As Integer

    a = 10: b = 10

    

    Debug.Print "test前: a=" & a & ",b=" & b

    test a, (b)

    Debug.Print "test后: a=" & a & ",b=" & b

End Sub

重點是這個(b),即在傳遞b變量時,使用小括號括起來,這時就會臨時性只傳遞變量b的值(使其變成了ByVal參數),而不會對原實體變量b造成傷害。

使用小括號的方法,同樣適用于數組變量參數。如果要獲取函數的返回值,就需要兩層括號了,類似這種形式:test(a, (b))。

ByRef總結:如果函數的參數使用了ByRef關鍵字,就傳遞一個變量的引用(地址,會改變原變量的值),如果對這個關鍵字參數只想傳遞值,可以將變量單獨用小括號括起來,這樣就只傳遞變量的值,不會修改變量的原始值,也可以直接使用一個實體的變量副本。



三、ByRef應用技巧



當我們了解了ByVal和ByRef的原理后,在編寫VBA代碼時,就需要加以注意了。因為參數的限定關鍵字被省略時,默認是ByRef傳遞。

通常我們只是使用這個參數傳遞的值,而不會在函數中對參數進行運算、賦值等動作,所以使用ByVal或ByRef可能感覺不到有什么區別。如果一個函數中傳遞的變量在該函數運行后,仍需要調用它,就需要注意是否是ByRef傳遞。

其實,利用ByRef傳遞,在函數中對傳遞的變量進行賦值等操作,有時候會收到奇特的效果,如下示例函數(根據身份證號獲取生日,同時根據需要獲取性別信息):

Function GetBirthDate(ByVal idCard As String, Optional ByRef gender As String) As Date

    Dim birthDate As Date    

    birthDate = DateSerial(CInt(Mid(idCard, 7, 4)), CInt(Mid(idCard, 11, 2)), CInt(Mid(idCard, 13, 2)))

    ' 提取性別

    If Val(Mid(idCard, 17, 1)) Mod 2 = 0 Then

        gender = "女"

    Else

        gender = "男"

    End If    

    GetBirthDate = birthDate

End Function

調用該函數時:

Sub 測試GetBirthDate()

    Dim idCard As String

    Dim gender As String

    

    idCard = "420624199610030080"

    

    '僅獲取生日:

    Debug.Print GetBirthDate(idCard)

    

    '獲取生日及性別:

    Debug.Print GetBirthDate(idCard, gender)

    Debug.Print gender

    

    '僅獲取性別:

    GetBirthDate idCard, gender

    Debug.Print gender

End Sub

不知道你看清這個操作沒有,通過將ByRef參數設置一個可選參數,在函數中對該參數賦值。

使用時,如果沒有特別的要求,只想得到函數的返回值,就省略該參數,也不會影響函數正常發揮。如果想得到這個經過函數洗禮后的變量的值,就如上述示例中所做,這樣,就能夠通過一個函數,同時獲取到多個返回值的奇特效果。

我們在使用一些API函數時也會遇到這些情形,非常實際的技巧。


閱讀原文:原文鏈接


該文章在 2025/1/24 9:26:18 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業的專業生產管理軟件系統,系統成熟度和易用性得到了國內大量中小企業的青睞。
點晴PMS碼頭管理系統主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業務管理,結合碼頭的業務特點,圍繞調度、堆場作業而開發的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業的高效ERP管理信息系統。
點晴WMS倉儲管理系統提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統,標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協同辦公管理系統。
Copyright 2010-2025 ClickSun All Rights Reserved

黄频国产免费高清视频,久久不卡精品中文字幕一区,激情五月天AV电影在线观看,欧美国产韩国日本一区二区
亚洲欧美人成网站在线看 | 亚洲国产91一区二区 | 在线影片亚洲视频 | 亚洲欧美老师机在线AⅤ | 六月婷婷国产精品综合 | 日本按摩高潮A级不卡片 |