VBA 函数调用中括号的使用规则是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5413765/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What are the rules governing usage of brackets in VBA function calls?
提问by HorusKol
I've just had an irritating 30 minutes on a "compiler error" in VBA (Access 2003) caused by my use of brackets around the arguments I'm passing to a Sub I defined.
由于我在传递给我定义的 Sub 的参数周围使用了括号,因此在 VBA (Access 2003) 中出现了“编译器错误”,这让我感到恼火 30 分钟。
I've been searching to find a decent article/tutorial/instruction as to when brackets are necessary/appropriate/inappropriate/forbidden, but can't find any clear guidelines.
我一直在寻找关于何时需要/适当/不适当/禁止使用括号的体面文章/教程/说明,但找不到任何明确的指导方针。
采纳答案by Mitch Wheat
From Here:
从这里:
Using the VBScript Call Statement to Call a SubroutineThe use of Call statement is optional when you wish to call a subroutine. The purpose of the Call statement when used with a Sub is to allow you to enclose the argument list in parentheses. However, if a subroutine does not pass any arguments, then you still should not use parentheses when calling a Sub using the Call statement.
使用 VBScript Call 语句调用子例程 当您希望调用子例程时,Call 语句的使用是可选的。与 Sub 一起使用时,Call 语句的目的是允许您将参数列表括在括号中。但是,如果子例程不传递任何参数,则在使用 Call 语句调用 Sub 时仍然不应使用括号。
Call MySubroutine
If a subroutine has arguments, you must use parentheses when using the Call statement. If there is more than one argument, you must separate the arguments with commas.
如果子例程有参数,则在使用 Call 语句时必须使用括号。如果有多个参数,您必须用逗号分隔参数。
Call MySubroutine(intUsageFee, intTimeInHours, "DevGuru")
Calling the FunctionThere are two possible ways to call a function. You may either call the function directly, by name only, or you may call it by using the VBScript Call statement.
调用函数有两种可能的方法来调用函数。您可以直接调用该函数,仅通过名称,或者您可以使用 VBScript Call 语句调用它。
Calling a Function by NameWhen calling a function directly by name and when there is no assignment to a returned value, all of the following are legal syntax:
按名称调用函数当直接按名称调用函数并且没有对返回值赋值时,以下所有语法都是合法的:
MyFunction
MyFunction()
MyFunction intUsageFee, intTimeInHours, "DevGuru"
If you want a returned value, you can assign the function to a variable. Note that if there is one or more arguments, you must use the parentheses.
如果需要返回值,可以将函数分配给变量。请注意,如果有一个或多个参数,则必须使用括号。
returnval = MyFunction
returnval = MyFunction()
returnval = MyFunction(intUsageFee, intTimeInHours, "DevGuru")
回答by Floris Kleijne
There is perfect logic to the Parentheses Rule in VB(A), and it goes like this.
VB(A) 中的括号规则有完美的逻辑,它是这样的。
If a procedure (function or sub) is called with arguments, and the call is on a line with other statements or keywords, the arguments must be enclosed in parentheses. This to distinguish the arguments belonging to the procedure call from the rest of the line. So:
如果使用参数调用过程(函数或子),并且调用与其他语句或关键字在同一行,则参数必须括在括号中。这是为了将属于过程调用的参数与行的其余部分区分开来。所以:
1: If CheckConditions(A, B, C) = DONT_PROCEED Then Exit Sub
is a valid line; the call to CheckConditions needs the parentheses to indicate what other bits of the line are its arguments. Conversely, this would produce a syntax error:
是有效的行;对 CheckConditions 的调用需要括号来指示该行的其他哪些位是其参数。相反,这会产生语法错误:
2: If CheckConditions A, B, C = DONT_PROCEED Then Exit Sub
Because it is impossible to parse.
因为无法解析。
With a procedure call as the only statement on the line, parentheses aren't needed because it is clear that the arguments belong to the procedure call:
将过程调用作为该行中唯一的语句,不需要括号,因为很明显参数属于过程调用:
3: SaveNewValues Value1, Value2, Value3
While this results in a syntax error (for sound reasons discussed below):
虽然这会导致语法错误(出于下面讨论的合理原因):
4: SaveNewValues(Value1, Value2, Value3)
To avoid confusion about parentheses or no parentheses (in fact, to avoid the Parentheses Rule entirely), it is always a good idea to use the Call keyword for calls like these; that ensures that the procedure call is not the only statement on the line, thus requiring parentheses:
为了避免括号或没有括号的混淆(实际上,完全避免括号规则),对此类调用使用 Call 关键字始终是一个好主意;这确保过程调用不是该行中唯一的语句,因此需要括号:
5: Call SaveNewValues(Value1, Value2, Value3)
So if you get in the habit of preceding self-contained procedure calls with the Call keyword, you can forget the Parentheses Rule, because you can then always enclose your arguments in parentheses.
因此,如果您习惯于使用 Call 关键字在自包含过程调用之前,您可以忘记括号规则,因为您可以始终将参数括在括号中。
The matter is confused by the additional role parentheses play in VB(A) (and many other languages): they also indicate evaluation precedence for expressions. If you use parentheses in any other context but to enclose procedure call arguments, VB(A) will attempt to evaluate the expression in the parentheses to a resulting simple value.
括号在 VB(A)(和许多其他语言)中扮演的额外角色混淆了这个问题:它们还表示表达式的评估优先级。如果您在任何其他上下文中使用括号但将过程调用参数括起来,VB(A) 将尝试将括号中的表达式计算为结果简单值。
Thus, in example 4, where parentheses are illegal for enclosing the arguments, VB(A) will instead attempt to evaluate the expression in the parentheses. Since (Value1, Value 2, Value3) is not an expression that can be evaluated, a syntax error ensues.
因此,在示例 4 中,括号用于封闭参数是非法的,VB(A) 将尝试计算括号中的表达式。由于 (Value1, Value 2, Value3) 不是可以计算的表达式,因此会出现语法错误。
This also explains why calls with a variable passed ByRef act as if called ByVal if the argument is enclosed in parentheses. In the example above, where function p is called with ByRef parameter a, there is a big difference between these two calls to p:
这也解释了为什么如果参数被括在括号中,则使用传递 ByRef 的变量的调用就像调用 ByVal 一样。在上面的例子中,函数 p 是用 ByRef 参数 a 调用的,这两次调用 p 之间有很大的不同:
6: p a
And
和
7: p(a)
As discussed above, 6 is the correct syntax: the call is alone on its line, so parentheses should not be used to enclose the arguments.
如上所述,6 是正确的语法:调用单独在一行中,因此不应使用括号将参数括起来。
In 7, the argument is enclosed in parentheses anyway, prompting VB(A) to evaluate the enclosed expression to a simple value. Which of course is the very definition of passing ByVal. The parentheses ensure that instead of a pointer to a, the value of a is passed, and a is left unmodified.
在 7 中,参数无论如何都被括在括号中,提示 VB(A) 将封闭的表达式计算为一个简单的值。这当然是传递 ByVal 的定义。括号确保传递的是 a 的值而不是指向 a 的指针,并且 a 保持不变。
This also explains why the parentheses rule doesn't always seem to hold sway. Clearest example is a MsgBox call:
这也解释了为什么括号规则似乎并不总是占主导地位。最清楚的例子是 MsgBox 调用:
8: MsgBox "Hello World!"
And
和
9: MsgBox ("Hello World!")
Are both correct, even though the parentheses rule dictates that 9 should be wrong. It is, of course, but all that happens is that VB(A) evaluates the expression in the parentheses. And the string literal evaluates to the exact same string literal, so that the actual call made is 8. In other words: calls to single-argument procedures with constant or string literal arguments have the identical result with or without parentheses. (This is why even my MsgBox calls are preceded by the Call keyword.)
两者都是正确的,即使括号规则规定 9 应该是错误的。当然是这样,但所发生的一切只是 VB(A) 计算括号中的表达式。并且字符串文字计算为完全相同的字符串文字,因此实际调用是 8。换句话说:对带有常量或字符串文字参数的单参数过程的调用具有相同的结果,带或不带括号。(这就是为什么即使我的 MsgBox 调用也以 Call 关键字开头。)
Finally, this explains odd Type Mismatch errors and weird behavior when passing Object arguments. Let's say your application has a HighlightContent procedure that takes a TextBox as argument (and, you'll never guess, highlights it contents). You call this to select all text in the textbox. You can call this procedure in three syntactically correct ways:
最后,这解释了传递 Object 参数时奇怪的类型不匹配错误和奇怪的行为。假设您的应用程序有一个将 TextBox 作为参数的 HighlightContent 过程(而且,您永远猜不到,突出显示了它的内容)。你调用它来选择文本框中的所有文本。您可以通过三种语法正确的方式调用此过程:
10: HighlightContent txtName
11: HighlightContent (txtName)
12: Call HighlightContent(txtName)
Let's say your user has entered "John" in the textbox and your application calls HighlightContent. What will happen, which call will work?
假设您的用户在文本框中输入了“John”,并且您的应用程序调用了 HighlightContent。会发生什么,哪个调用会起作用?
10 and 12 are correct; the name John will be highlighted in the textbox. But 11 is syntactically correct, but will result in a compile or runtime error. Why? Because the parentheses are out of place. That will prompt VB(A) to attempt an evaluation of the expression in the parentheses. And the result of the evaluation of an object will most often be the value of its default property; .Text, in this case. So calling the procedure like 11 will not pass the TextBox object to the procedure, but a string value "John". Resulting in a Type Mismatch.
10 和 12 是正确的;John 的名字将在文本框中突出显示。但是 11 在语法上是正确的,但是会导致编译或运行时错误。为什么?因为括号不合适。这将提示 VB(A) 尝试对括号中的表达式求值。对象的评估结果通常是其默认属性的值;.Text,在这种情况下。所以调用像 11 这样的过程不会将 TextBox 对象传递给过程,而是一个字符串值“John”。导致类型不匹配。
回答by alex1234231
I just found some weird behavior calling a function with / without parentheses. Google took me here.
我刚刚发现一些奇怪的行为,调用带有 / 不带括号的函数。谷歌把我带到了这里。
sub test()
dim a as double
a = 1#
p(a) 'this won't change a's value
Debug.Print a '1
p a ' this is expected behavior
Debug.Print a '2
Call p(a) 'this is also valid
Debug.Print a '3
end sub
Function p(a as Double) 'default is byref
a = a + 1
end function
My conclusion is that you have to use either Call or omitting the parentheses when calling a function with only one parameter, otherwise the parameter isn't passed by reference (it's still get called, as I checked already).
我的结论是,在调用只有一个参数的函数时,您必须使用 Call 或省略括号,否则该参数不会通过引用传递(它仍然被调用,正如我已经检查过的那样)。
回答by metacircle
I just spent 10 minutes figuring out an "types incompatible" exception while calling a Sub which takes 1 argument via
我只花了 10 分钟找出一个“类型不兼容”异常,同时调用一个 Sub ,它通过 1 个参数
CallMe(argument)
As it turns out, this is invalid, googling lead me here and finally
事实证明,这是无效的,谷歌搜索引导我到这里,最后
Call CallMe(argument)
or
或者
CallMe argument
did the trick. So you must not use the brackets when calling a sub without the call-statement which only takes 1 argument.
成功了。因此,在没有只接受 1 个参数的调用语句的情况下调用 sub 时,您不能使用括号。
回答by Alexan
When you use
Call MySub
you should use parentheses around parameters, but if you omit Call, you don't need parentheses.
使用
Call MySub
时应该在参数周围使用括号,但如果省略Call,则不需要括号。
回答by Christophe Keller
1 - By default, do not use parentheses when calling procedures or functions:
1 - 默认情况下,调用过程或函数时不使用括号:
MsgBox "Hello World"
2 - If you are calling a function, and are interested in its result, then you must enclose its arguments with parentheses:
2 - 如果您正在调用一个函数,并且对其结果感兴趣,那么您必须用括号将其参数括起来:
Dim s As String
Dim l As Long
s = "Hello World"
l = Len(s)
3 - If you want to use the call keyword with a procedure, then you must enclose the arguments with parentheses (e.g. when you want to assign the result in a variable or to use the function in an expression):
3 - 如果您想在过程中使用 call 关键字,那么您必须用括号将参数括起来(例如,当您想在变量中分配结果或在表达式中使用函数时):
Call MsgBox("Hello World")
4 - If you want to force a ByRef argument (the default) to be passed ByVal, then enclose the ByRef argument with parentheses:
4 - 如果您想强制通过 ByVal 传递 ByRef 参数(默认值),请用括号将 ByRef 参数括起来:
Sub Test
Dim text As String
text = "Hello World"
ChangeArgument((text))
MsgBox text
End Sub
Sub ChangeArgument(ByRef s As String)
s = "Changed"
End Sub
This displays "Hello World"
这将显示“Hello World”