【原创】VBA学习笔记(15)VBA的参数传递:ByVal 和 ByRef 的区别,VBA默认按byRef传递

本文通过两个示例对比了VBA中byVal与byRef两种参数传递方式的区别。byRef按地址传递,主程序传给子过程的数据会被修改;byVal按值传递,子过程仅操作数据副本,不影响原始数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

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

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

目的:

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

 

参数调用和回调的方法

  • 被调用的程序,可以设定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

是的,这是VBA学习笔记的第一篇文章,涵盖两个主题:自动添加代码VBA修改注册表。下面是更详细的介绍: ## 自动添加代码 在VBA中,我们可以使用代码自动添加代码。这通常用于在编写宏时自动添加模板代码或辅助代码。下面是一个简单的示例,演示如何使用VBA自动添加代码: ```vb Sub AddCode() '获取当前文档中的VBProject对象 Dim vbProj As VBIDE.VBProject Set vbProj = ActiveWorkbook.VBProject '获取当前文档中的Sheet1模块 Dim sheetMod As VBIDE.CodeModule Set sheetMod = vbProj.VBComponents("Sheet1").CodeModule '添加VBA代码 sheetMod.InsertLines 1, "Sub HelloWorld()" & vbCrLf & _ " MsgBox ""Hello, World!""" & vbCrLf & _ "End Sub" End Sub ``` 上述代码将在当前文档的Sheet1模块中添加一个名为"HelloWorld"的子例程,并在调用该例程时显示一个消息框。 ## VBA修改注册表 VBA可以使用Windows API函数来修改Windows注册表。这对于配置或自定义Windows系统非常有用。下面是一个简单的示例,演示如何使用VBA修改注册表中的一个键值: ```vb Option Explicit Private Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" ( _ ByVal hKey As Long, _ ByVal lpSubKey As String, _ ByVal ulOptions As Long, _ ByVal samDesired As Long, _ ByRef phkResult As Long) As Long Private Declare Function RegSetValueEx Lib "advapi32.dll" Alias "RegSetValueExA" ( _ ByVal hKey As Long, _ ByVal lpValueName As String, _ ByVal Reserved As Long, _ ByVal dwType As Long, _ ByVal lpData As Any, _ ByVal cbData As Long) As Long Private Declare Function RegCloseKey Lib "advapi32.dll" ( _ ByVal hKey As Long) As Long Private Const HKEY_CURRENT_USER = &H80000001 Private Const KEY_SET_VALUE = &H2 Private Const REG_SZ = 1 Sub ModifyRegistryKey() Dim hKey As Long Dim result As Long '打开注册表键 result = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced", 0, KEY_SET_VALUE, hKey) If result = 0 Then '设置键值的值 result = RegSetValueEx(hKey, "Hidden", 0, REG_SZ, "2", 2) '关闭注册表键 result = RegCloseKey(hKey) End If End Sub ``` 上述代码演示了如何将 "Hidden" 键的值设置为 "2",这将隐藏文件资源管理器中的隐藏文件文件夹。请注意,修改注册表可能会导致系统不稳定,因此在进行任何修改之前,请备份您的注册表。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值