我有以下VBA代码。
Option Explicit
Sub problem1()
Dim speedmph As Double, speedkph As Double, speedfts As Double
speedmph = Val(InputBox("Enter a speed (mph)"))
Call convert(speedmph, speedkph, speedfts)
MsgBox "The speed is " & speedkph & " km/hr and " & speedfts & "ft/s."
End Sub
Sub convert(speedmph, speedkph, speedfts)
speedkph = speedmph * 1.609
speedfts = speedmph * 1.467
End Sub
我注意到当我调用上面显示的转换过程时,它起作用了。
但是,如果我尝试为speedkph插入一个值(例如0),convert
procedure不会覆盖它,而MsgBox为speedkph打印出0。
为什么convert
不会覆盖0
,即使它有效
要在其函数定义中更改的变量吗?
答案 0 :(得分:4)
关于范围,Function
或Sub
的参数仅在声明它们的Function
或Sub
范围内。对于变量,情况也是如此使用关键字Dim
(或数组的ReDim
)声明。对于未声明的变量,如果存在匹配的标识符(模块级私有变量,则为全局变量),则作用域是下一个最高的作用域。如果不存在具有更大范围的标识符,则会在 local 范围内将其隐式声明为Variant
。所以,在这一行......
Sub convert(speedmph, speedkph, speedfts)
...参数speedmph
,speedkph
和speedfts
都是Sub convert
的本地参数(隐含Variant
,因为没有As
{1}}陈述),并在这一行......
Dim speedmph As Double, speedkph As Double, speedfts As Double
...参数speedmph
,speedkph
和speedfts
都是Sub problem1()
的本地参数。
这样,让我们解决 为什么 你的MsgBox
显示任何内容。传递参数的默认方法是ByRef
,因此如果您要实际指定Sub
声明的所有隐式部分,它将如下所示:
Public Sub convert(ByRef speedmph As Variant, ByRef speedkph As Variant, _
ByRef speedfts As Variant)
当你这样称呼它时......
Call convert(speedmph, speedkph, speedfts)
...您将 引用 传递给speedmph
,speedkph
,speedfts
您在{{ 1}}。 Sub problem1()
为这些引用分配值,但每个过程仅保留本地范围内引用的自己的 副本 。此时标识符完全不相关。实际上,这与示例代码完全相同(仅标识符已更改):
Sub convert
现在回答您的具体问题,您不能使用Sub problem1()
Dim speedmph As Double, speedkph As Double, speedfts As Double
speedmph = Val(InputBox("Enter a speed (mph)"))
Call convert(speedmph, speedkph, speedfts)
MsgBox "The speed is " & speedkph & " km/hr and " & speedfts & "ft/s."
End Sub
Sub convert(foo, bar, baz)
bar = foo * 1.609
baz = foo * 1.467
End Sub
的“占位符”值的原因是0
不是变量 - 它是文字。当它传递给0
时,引用存在的唯一位置是作为调用堆栈上的变量 - Sub convert
不包含对它的引用,因此Sub problem1()
没有办法告诉 Sub problem1()
做什么。当Sub convert
返回并且调用堆栈展开时,堆栈变量将被销毁。基本上,将文字传递给Sub convert
参数在功能上等同于传递ByRef
。