VBA中的函数至少只能返回1 thing 。那个东西可能包含多个值,但它仍然是1个包。
我想创建一个Sub / Function,它对多于1个变量的值有影响。据我所知,这有三种方法:
Private val1 As Long, val2 As Long
Sub Caller()
val1 = 1
val2 = 2
valueChanger
Debug.Print val1 + val2 'Prints 5
End Sub
Sub valueChanger() 'no need to pass any values, but could pass both byVal
val1 = val1 + 1
val2 = val2 + 1
End Sub
Sub Caller()
Dim val1 As Long, val2 As Long
val1 = 1
val2 = 2
valueChanger val1, val2
Debug.Print val1 + val2 'Prints 5
End Sub
Sub valueChanger(ByRef value1 As Long, ByRef value2 As Long)
value1 = value1 + 1
value2 = value2 + 1
End Sub
Sub Caller()
Dim val1 As Long, val2 As Long, results() As Long
val1 = 1
val2 = 2
results = valueChanger(val1, val2)
Debug.Print results(1) + results(2) 'Prints 5
End Sub
Function valueChanger(ByVal value1 As Long, ByVal value2 As Long) As Long() 'return an array, could equally return a collection or even a string
Dim resultVals(1 To 2) As Long
resultVals(1) = value1 + 1
resultVals(2) = value2 + 1
valueChanger = resultVals
End Function
我可以看到选项3可能是最独立的,选项1可能是最不重要的。选项3可能是最耗费内存的,也需要将结果分散得相当混乱。
我个人认为选项2是一个中间立场,我认为只要你知道byRef
的风险,因为你正在输入例行程序,一旦'完成之后,您可以基本忘记它,因为变量在代码中的其他任何地方都不会显示 - 与选项1不同。
但我错过了什么吗?我应该遵循这些标准实践中的任何一种方法吗?
答案 0 :(得分:1)
您的第三种方法在概念上最简单,因此可能更容易调试(并且首先不太可能需要调试)。您可以简化机制:
1)只需使用Variant
将数组传递给函数
2)使用Array()
打包返回信息
3)编写一个与Array()
相反的子,一个可以将数组解包到提供的变量列表中的子句(隐式使用VBA的默认byRef
语义:
Sub UnPack(A As Variant, ParamArray Vars() As Variant)
'A is a 0-based array of the same length as Vars
'The elements of A are assigned to the variables in Vars
Dim i As Long
For i = 0 To UBound(Vars)
Vars(i) = A(i)
Next i
End Sub
然后你的valueChanger()
就可以了:
Function valueChanger(ByVal value1 As Long, ByVal value2 As Long) As Variant
valueChanger = Array(value1 + 1, value2 + 1)
End Function
用过:
Sub Caller()
Dim val1 As Long, val2 As Long, results As Variant
val1 = 1
val2 = 2
results = valueChanger(val1, val2)
UnPack results, val1, val2
Debug.Print val1 + val2 'Prints 5
End Sub
甚至只是:
Sub Caller()
Dim val1 As Long, val2 As Long
val1 = 1
val2 = 2
UnPack valueChanger(val1, val2), val1, val2
Debug.Print val1 + val2 'Prints 5
End Sub
或者,您可以通过扩展“数据包”的含义来实现方法3。当某些意义上的值一起出现时,通常只有从函数返回多个值才有意义。这表明将这些值包装在类型甚至类中是很自然的:
'at top of module:
Type Pair
val1 As Long
val2 As Long
End Type
然后:
Function valueChanger(p As Pair) As Pair 'can't pass a user-defined type ByVal
Dim q As Pair
q.val1 = p.val1 + 1
q.val2 = p.val2 + 1
valueChanger = q
End Function
用过:
Sub Caller()
Dim p As Pair
p.val1 = 1
p.val2 = 2
p = valueChanger(p)
Debug.Print p.val1 + p.val2 'Prints 5
End Sub
答案 1 :(得分:0)
第一个代码将值传递给Module Level Variables。因此可以从该模块的任何过程访问它。
第二个ByRef会改变变量的值。
第3个ByVal不会更改变量的值,只会从变量中获取值。
所有这些都是根据编程需要使用的。
希望它清楚。