1 参数传递时的 byVal 和 byRef 区别的简单总结

1.1 如果不写关键字, VBA默认按地址传递

  • VBA默认按地址传递,是为了方便管理?

1.2  什么是参数的调用和回调?

目的:

  • 主程序调用一些需要参数的子程序,为了给其他程序的主动传递变量,而调用其他程序(被调用程序),并获得回调后的参数
  • 主程序需要调用其他子程序,有些子程序(被调用程序)需要参数就必须传递参数过去。而被调用程序设置的参数关键字不同,会造成不同的调用和回调效果。

vba function传参 参照 vba传参数_子程序

 

参数调用和回调的方法

  • 被调用的程序,可以设定2种传递方式,进而影响给主程序的回调值。
  • 也就是会不会受影响,不由主程序决定!而是由 需参数的被调用的程序自身决定。

1.3 参数调用的两种方式

  • byref ,被调用程序 按地址传递,传回主程序的参数,回调时会受影响。
  • 按地址传递(ByRef),是指主程序直接将数据交给子过程(过程中定义传递方式),在过程中修改、调试、返回给主程序,主程序输出的是修改后的值。
  • VBA默认的是 byref方式
  • byval  ,被调用程序 按值传递,传回主程序的参数,回调时会不受改变。
  • 按值传递(Byval),是指将主程序的值(副本一份)给子过程,过程对副本操作,主程序输出的仍是原值。若想输出值传递后的值,可在子过程中设置输出。

1.4 常量是不变化的

  • 只有变量有这个问题,常量怎么传递本身也不改变

2 例子1,比较byVal 和 byRef的区别

运算函数1:运算函数,定义了自身函数需要的参数,是传值,还是传地址。

                    其他函数在调用时,需要按这种方式传递参数

运算函数2:主函数:因为调用运算函数时,会根据运算函数设定的参数属性,所以主函数的参数发生改变了。

Sub test1(ByRef a)
Debug.Print "test1被调用"
Debug.Print "a=" & a
a = a + 1
Debug.Print "a=" & a
Debug.Print "test1调用结束"
End Sub

Sub test2(ByVal b)
Debug.Print "test2被调用"
Debug.Print "b=" & b
b = b + 1
Debug.Print "b=" & b
Debug.Print "test2调用结束"
End Sub

Sub main1()
Debug.Print "mian1开始执行"
Debug.Print "x=" & x
Debug.Print "y=" & y
x = 3
y = 4
Debug.Print "x=" & x
Debug.Print "y=" & y
Debug.Print "开始调用"
test1 x
test2 y
Debug.Print "调用结束"
Debug.Print "x=" & x
Debug.Print "y=" & y
Debug.Print "mian1执行完毕"
End Sub

执行结果

mian1开始执行
x=
y=
x=3
y=4
开始调用
test1被调用
a=3
a=4
test1调用结束
test2被调用
b=4
b=5
test2调用结束
调用结束
x=4
y=4
mian1执行完毕

3 例子2,如果不带关键字,默认为byref

  • 如果被调用函数的不带关键字,就默认为byref传递
Sub test1(a)
Debug.Print "test1被调用"
Debug.Print "a=" & a
a = a + 1
Debug.Print "a=" & a
Debug.Print "test1调用结束"
End Sub
 
Sub test2(b)
Debug.Print "test2被调用"
Debug.Print "b=" & b
b = b + 1
Debug.Print "b=" & b
Debug.Print "test2调用结束"
End Sub
 
Sub main1()
Debug.Print "mian1开始执行"
Debug.Print "x=" & x
Debug.Print "y=" & y
x = 3
y = 4
Debug.Print "x=" & x
Debug.Print "y=" & y
Debug.Print "开始调用"
test1 x
test2 y
Debug.Print "调用结束"
Debug.Print "x=" & x
Debug.Print "y=" & y
Debug.Print "mian1执行完毕"
End Sub

mian1开始执行
x=
y=
x=3
y=4
开始调用
test1被调用
a=3
a=4
test1调用结束
test2被调用
b=4
b=5
test2调用结束
调用结束
x=4
y=5
mian1执行完毕

4 例子3,继续试验

Sub test1(ByRef a)   '参数默认是按ref调用
Debug.Print "test1被调用"
Debug.Print "a=" & a
a = 1
Debug.Print "a=" & a
End Sub



Sub test2(ByVal b)
Debug.Print "test2被调用"
Debug.Print "b=" & b
b = 2
Debug.Print "b=" & b

End Sub

Sub main1()
Debug.Print "执行main1"
Debug.Print "x=" & x
Debug.Print "y=" & y
x = 3
y = 4
Debug.Print "x=" & x
Debug.Print "y=" & y
Debug.Print "开始调用"
test1 x
test2 y
Debug.Print "调用结束"
Debug.Print "x=" & x
Debug.Print "y=" & y

End Sub

执行结果可以看出

main1函数的x   会因为调用了其他运算函数,这个运算函数要求传地址,之后运算函数改变了a=x,从而x也被改变

而main1函数y参数,因为调用的函数是只需要按值传递,只传了一个副本给运算函数,自身y不会变化

执行main1
x=
y=
x=3
y=4
开始调用
test1被调用
a=3
a=1
test2被调用
b=4
b=2
调用结束
x=1
y=4