可变范围:VBA如何决定何时覆盖变量

时间:2016-12-27 19:24:43

标签: excel-vba variables scope vba excel

我有以下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,即使它有效 要在其函数定义中更改的变量吗?

1 个答案:

答案 0 :(得分:4)

关于范围,FunctionSub的参数仅在声明它们的FunctionSub范围内。对于变量,情况也是如此使用关键字Dim(或数组的ReDim)声明。对于未声明的变量,如果存在匹配的标识符(模块级私有变量,则为全局变量),则作用域是下一个最高的作用域。如果不存在具有更大范围的标识符,则会在 local 范围内将其隐式声明为Variant。所以,在这一行......

Sub convert(speedmph, speedkph, speedfts)

...参数speedmphspeedkphspeedfts都是Sub convert的本地参数(隐含Variant,因为没有As {1}}陈述),并在这一行......

Dim speedmph As Double, speedkph As Double, speedfts As Double

...参数speedmphspeedkphspeedfts都是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)

...您将 引用 传递给speedmphspeedkphspeedfts您在{{ 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