在VBA中,括号中的差异效应背后是什么?

在VBA中,括号中的差异效应背后是什么?,vba,ms-word,Vba,Ms Word,我没有在其他语言中看到这一点,但我在VBA(我刚开始使用VBA)中看到了很多。假设您在Word中有一个表,并希望将行设置为某个高度。如果你这样做 tbl.Rows.SetHeight InchesToPoints(1), wdRowHeightExactly 该表的行确实设置为72点或1英寸高。但是,如果将参数括在括号中(我本能地这样做),VBA会给出一个错误--预期:= 我可以用一个一次性变量来解决这个问题,就像这样 x = tbl.Rows.SetHeight (InchesToP

我没有在其他语言中看到这一点,但我在VBA(我刚开始使用VBA)中看到了很多。假设您在Word中有一个表,并希望将行设置为某个高度。如果你这样做

    tbl.Rows.SetHeight InchesToPoints(1), wdRowHeightExactly
该表的行确实设置为72点或1英寸高。但是,如果将参数括在括号中(我本能地这样做),VBA会给出一个错误--
预期:=

我可以用一个一次性变量来解决这个问题,就像这样

x = tbl.Rows.SetHeight (InchesToPoints(1), wdRowHeightExactly)
当然,我也不能简单地用括号括住这些论点

微软没有提到任何返回值,但在任何情况下,这种行为在整个VBA中都是广泛存在的。它不是特定于SetHeight方法的


我的问题:这叫什么?我应该使用抛弃变量还是抛弃括号?微软的逻辑是什么?使用其中一个或另一个是否会产生我无法想象的后果(因为它们是未知的未知数)?

不恰当地使用括号的最严重后果可以通过以下代码得到最好的证明:

Sub Test()
    Dim r As Range
    Set r = Range("A1")
    TestSub r
    TestSub (r)
End Sub

Sub TestSub(parm As Range)
    MsgBox parm.Address
End Sub
在该代码中,
TestSub r
正确地将范围对象传递给
TestSub
。但是,在
r
周围放置括号,即
TestSub(r)
会导致VBA使用其
Value
属性计算
r
,因此相当于
TestSub r.Value
。然后,当它将
变量
(可能是值为
123.45
变量/双精度
)传递给需要
范围
的子例程时,会出现错误


将参数括在括号内的子例程中基本上是不正确的语法。它们只应在函数返回值时使用



另外,我很抱歉我的例子是Excel VBA。我没有注意到问题是Word VBA,而且我可以比研究Word VBA给出一个例子更快地写出一个Excel示例。但两者的原理是相同的。

绝对不要引入“丢弃变量”,尤其是当未声明时,尤其是当您调用的是
,一个不返回任何值的过程时。如果您不介意编译时错误,您可以:

期望的函数或变量

现在

这种行为在VBA中广泛存在。它不是特定于SetHeight方法的

:

至于它叫什么,我想“正确的语法”是最合适的词

这就是全部答案:它不是关于
SetHeight
,而是关于VBA的隐式过程/成员调用语法如何工作。自从大约四分之一世纪前隐式调用的奇妙出现以来,显式
调用
语法已经过时。因此,将
Call
关键字向左和向右以及代码上的所有内容都飞溅开来,确实会让您保留括号。。。如果你如此珍视它们

但是隐式调用语法的“逻辑”其实并不那么复杂

下面是我在文档中写的内容。关于VBA和括号,希望能有所帮助


这令人困惑。为什么不总是用括号呢? 括号用于括起函数调用的参数。将它们用于过程调用可能会导致意外问题

因为它们可能会在运行时通过向过程传递可能无意的值引入错误,在编译时通过无效语法引入错误

运行时 多余的括号可能会引入错误。给定一个将对象引用作为参数的过程

Sub DoSomething(ByRef target As Range)
End Sub
…并用括号调用:

DoSomething (Application.ActiveCell) 'raises an error at runtime
这将引发“需要对象”运行时错误#424。在其他情况下可能会出现其他错误:此处对
应用程序.ActiveCell
范围对象引用进行求值并按值传递,而不管过程的签名指定目标将通过
ByRef
。在上面的代码段中,传递给
DoSomething
ByVal
的实际值是
Application.ActiveCell.value

括号强制VBA计算括号内表达式的值,并将结果
ByVal
传递给被调用的过程。当计算结果的类型与过程的预期类型不匹配且无法隐式转换时,将引发运行时错误

编译时 此代码将无法编译:

MsgBox ("Invalid Code!", vbCritical)
因为表达式(“无效代码!”,vbCritical)无法计算为值

这将编译并运行:

MsgBox ("Invalid Code!"), (vbCritical)

但是看起来肯定很傻。避免使用多余的括号。

除非调用函数(即返回值的函数),否则不应在参数周围使用括号。至于它的名称,我想“正确的语法”是最合适的词。除了@YowE3K的注释而不是一次性变量外,您可以在函数前面添加
call
,然后使用括号:
call tbl.Rows.SetHeight(InchesToPoints(1),wdRowHeightExactly)
call
已过时,已经有20多年了。这是一个很好的例子,也解释了为什么变量作为参数是危险的。使用
Call
,就像在
calltestsub(r)
中一样,也可以让它像预期的那样工作。@ainwood是的,
Call
允许这样做,但是
Call
是非常老式的做事方式。使用它有点像使用
Let
赋值(例如
Let i=10
)。