VBA中括号效果不同的原因是什么?

Rob*_*tSF 1 vba ms-word word-vba

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

    tbl.Rows.SetHeight InchesToPoints(1), wdRowHeightExactly
Run Code Online (Sandbox Code Playgroud)

表格的行确实设置为72点或1英寸高。但是,如果将参数括在括号中(这是我本能地执行的操作),则VBA会给出错误- expected:=

我可以通过使用一个抛弃型变量来解决这个问题

x = tbl.Rows.SetHeight (InchesToPoints(1), wdRowHeightExactly)
Run Code Online (Sandbox Code Playgroud)

或者,当然,我不能简单地将参数括在括号中。

Microsoft的SetHeight方法文档没有提及任何返回值,但是无论如何,此行为在整个VBA中都是广泛的。它不特定于SetHeight方法。

我的问题:这叫什么?我应该使用扔掉的变量还是扔掉括号?从微软的角度来看,逻辑是什么?使用我无法想象的结果是否会产生后果(因为它们是未知的未知数)?

Mat*_*don 5

Definitely don't introduce a "throw-away variable", especially if it's not declared, and especially if what you're invoking is a Sub, a procedure that doesn't return any value. Well you can, if you don't mind a compile-time error:

Expected Function or variable.

Now...

this behavior is extensive throughout VBA. It's not specific to the SetHeight method.

@Yoe3k put it nicely:

As for what it is called, I would guess "correct syntax" is the most appropriate word.

That's the whole answer: it's not about SetHeight, it's about how VBA's implicit procedure/member call syntax works. The explicit Call syntax has been obsolete since the wonderful advent of implicit calls, about a quarter of a century ago. So splattering Call keywords left & right and all over your code will, indeed, keep you the parentheses... if you hold them so dear.

But the "logic" of the implicit call syntax isn't all that complicated, really.

What follows is what I wrote on Documentation.SO about VBA and parentheses, hope it helps.


This is confusing. Why not just always use parentheses?

Parentheses are used to enclose the arguments of function calls. Using them for procedure calls can cause unexpected problems.

Because they can introduce bugs, both at run-time by passing a possibly unintended value to the procedure, and at compile-time by simply being invalid syntax.

Run-time

Redundant parentheses can introduce bugs. Given a procedure that takes an object reference as a parameter...

Sub DoSomething(ByRef target As Range)
End Sub
Run Code Online (Sandbox Code Playgroud)

...and called with parentheses:

DoSomething (Application.ActiveCell) 'raises an error at runtime
Run Code Online (Sandbox Code Playgroud)

This will raise an "Object Required" runtime error #424. Other errors are possible in other circumstances: here the Application.ActiveCell Range object reference is being evaluated and passed by value regardless of the procedure's signature specifying that target would be passed ByRef. The actual value passed ByVal to DoSomething in the above snippet, is Application.ActiveCell.Value.

Parentheses force VBA to evaluate the value of the bracketed expression, and pass the result ByVal to the called procedure. When the type of the evaluated result mismatches the procedure's expected type and cannot be implicitly converted, a runtime error is raised.

Compile-time

This code will fail to compile:

MsgBox ("Invalid Code!", vbCritical)
Run Code Online (Sandbox Code Playgroud)

Because the expression ("Invalid Code!", vbCritical) cannot be evaluated to a value.

This would compile and work:

MsgBox ("Invalid Code!"), (vbCritical)
Run Code Online (Sandbox Code Playgroud)

But would definitely look silly. Avoid redundant parentheses.