vba中的ByVal和ByRef关键字有什么作用和区别?

vba中的的ByVal和ByRef关键字可以用在以下语句中:

Call Statement
Declare Statement
Function Statement
Property Get Statement
Property Let Statement
Property Set Statement
Sub Statement

其中ByVal表示参数是以值进行传递,ByRef表示参数是以引用进行传递,当一个参数未明示是ByVal或者ByRef时,默认是ByRef。

以值传递的官方解释如下:

A way of passing the value of an argument to a procedure instead of passing the address. This allows the procedure to access a copy of the variable. As a result, the variable's actual value can't be changed by the procedure to which it is passed.

以引用传递的官方解释如下:

A way of passing the address of an argument to a procedure instead of passing the value. This allows the procedure to access the actual variable. As a result, the variable's actual value can be changed by the procedure to which it is passed. Unless otherwise specified, arguments are passed by reference.

当编写VBA代码时,如果不涉及到API函数,基本上不会涉及到参数的传递方式。

但是如果要调用外部的动态链接库中的API函数时,参数的传递方式的不同会产生很大的区别。

接下来以CopyMemory为例,说明ByVal和ByRef的区别。

其中CopyMemory函数的Destination参数指的是拷贝粘贴的目标内存的起始地址。

Source 参数指的是要拷贝的内存的起始地址。

Length参数指的是要拷贝的内存的长度,以字节为单位。

如以下代码所示:

Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Long, ByVal Source As Long, ByVal Length As Long)
Sub xyf()
Dim i As Long
i = 10
Dim j As Long
j = 1
CopyMemory VarPtr(i), VarPtr(j), 4
MsgBox i
End Sub

CopyMemory函数的Destination和Source参数被申明为以值传递,在调用CopyMemory函数时直接以变量i,j的地址作为参数传递,实现了将j的值赋值给i,i的值变成了1。

如以下代码所示:

Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Long, Source As Long, ByVal Length As Long)
Sub xyf()
    Dim i As Long
    i = 10
    Dim j As Long
    j = 1
    i1 = VarPtr(i)
    j1 = VarPtr(j)
    CopyMemory i1, j1, 4
    MsgBox i
End Sub

CopyMemory函数的Destination和Source参数被申明为以引用传递,也就是传递地址,在调用CopyMemory函数时i1,j1传递的是i1,j1的内存地址,而不是i,j 变量的内存地址,i 变量的值最终还是10。

但是如果在调用时添加byval ,则结果就完全变了。

如下所示

Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Long, Source As Long, ByVal Length As Long)
Sub xyf()
    Dim i As Long
    i = 10
    Dim j As Long
    j = 1
    i1 = VarPtr(i)
    j1 = VarPtr(j)
    CopyMemory ByVal i1, ByVal j1, 4
    MsgBox i
End Sub

CopyMemory ByVal i1, ByVal j1, 4 直接传递i1,j1变量的值,也就i,j 变量的内存地址,最终i的值将变成1。

       

发表评论