Hor*_*Kol 33 syntax ms-access vba
我刚刚在VBA(Access 2003)中出现了一个令人恼火的30分钟因为我在传递给我定义的Sub的参数周围使用了括号而引起的.
我一直在寻找一个体面的文章/教程/说明何时括号是必要/适当/不适当/禁止,但找不到任何明确的指导方针.
小智 55
VB(A)中的圆括号规则有完美的逻辑,它就是这样的.
如果使用参数调用过程(函数或子),并且调用与其他语句或关键字一致,则参数必须括在括号中.这是为了区分属于过程调用的参数与行的其余部分.所以:
1: If CheckConditions(A, B, C) = DONT_PROCEED Then Exit Sub
Run Code Online (Sandbox Code Playgroud)
是有效的; 对CheckConditions的调用需要括号来指示该行的其他位是其参数.相反,这会产生语法错误:
2: If CheckConditions A, B, C = DONT_PROCEED Then Exit Sub
Run Code Online (Sandbox Code Playgroud)
因为无法解析.
使用过程调用作为行上的唯一语句,不需要括号,因为很明显参数属于过程调用:
3: SaveNewValues Value1, Value2, Value3
Run Code Online (Sandbox Code Playgroud)
虽然这会导致语法错误(出于下面讨论的声音原因):
4: SaveNewValues(Value1, Value2, Value3)
Run Code Online (Sandbox Code Playgroud)
为了避免混淆括号或没有括号(实际上,为了完全避免使用括号规则),对这些调用使用Call关键字总是一个好主意; 确保过程调用不是该行的唯一语句,因此需要括号:
5: Call SaveNewValues(Value1, Value2, Value3)
Run Code Online (Sandbox Code Playgroud)
因此,如果您习惯使用Call关键字进行自包含过程调用,则可以忘记括号规则,因为您可以随后将参数括在括号中.
这个问题被括号在VB(A)(和许多其他语言)中扮演的额外角色所混淆:它们还表明了表达式的评估优先级.如果在任何其他上下文中使用括号但是要包含过程调用参数,VB(A)将尝试将括号中的表达式计算为生成的简单值.
因此,在示例4中,括号对于包含参数是非法的,VB(A)将尝试评估括号中的表达式.由于(Value1,Value 2,Value3)不是可以计算的表达式,因此会出现语法错误.
这也解释了为什么如果参数括在括号中,带有传递ByRef的变量的调用就像调用ByVal一样.在上面的示例中,使用ByRef参数a调用函数p时,这两个p调用之间存在很大差异:
6: p a
Run Code Online (Sandbox Code Playgroud)
和
7: p(a)
Run Code Online (Sandbox Code Playgroud)
如上所述,6是正确的语法:调用在其行上是单独的,因此不应使用括号来包含参数.
在7中,无论如何,参数都括在括号中,提示VB(A)将包含的表达式计算为一个简单的值.这当然是传递ByVal的定义.括号确保不是指向a的指针,而是传递a的值,并且a保持不变.
这也解释了为什么括号规则似乎并不总是占据主导地位.最清楚的例子是MsgBox调用:
8: MsgBox "Hello World!"
Run Code Online (Sandbox Code Playgroud)
和
9: MsgBox ("Hello World!")
Run Code Online (Sandbox Code Playgroud)
两者都是正确的,即使括号规则规定9应该是错误的.当然,所有发生的事情都是VB(A)评估括号中的表达式.字符串文字的计算结果与完全相同的字符串文字,因此实际调用是8.换句话说:使用常量或字符串文字参数调用单参数过程具有相同的结果,有或没有括号.(这就是为什么即使我的MsgBox调用前面都有Call关键字.)
最后,这解释了奇怪的类型不匹配错误和传递Object参数时的奇怪行为.假设您的应用程序有一个HighlightContent过程,它将TextBox作为参数(并且,您永远不会猜测,突出显示它的内容).您可以调用它来选择文本框中的所有文本.您可以通过三种语法正确的方式调用此过程:
10: HighlightContent txtName
11: HighlightContent (txtName)
12: Call HighlightContent(txtName)
Run Code Online (Sandbox Code Playgroud)
假设您的用户已在文本框中输入"John",您的应用程序将调用HighlightContent.会发生什么,哪个电话有效?
10和12是正确的; John的名称将在文本框中突出显示.但11语法正确,但会导致编译或运行时错误.为什么?因为括号不合适.这将促使VB(A)尝试评估括号中的表达式.而对象的评估结果通常是其默认属性的值; .Text,在这种情况下.所以调用像11这样的过程不会将TextBox对象传递给过程,而是传递字符串值"John".导致类型不匹配.
Mit*_*eat 22
从这里:
使用VBScript调用语句 调用子例程当您希望调用子例程时,可以选择使用Call语句.与Sub一起使用时,Call语句的目的是允许您将参数列表括在括号中.但是,如果子例程未传递任何参数,则在使用Call语句调用Sub时仍不应使用括号.
Call MySubroutine
Run Code Online (Sandbox Code Playgroud)
如果子例程具有参数,则在使用Call语句时必须使用括号.如果有多个参数,则必须用逗号分隔参数.
Call MySubroutine(intUsageFee, intTimeInHours, "DevGuru")
Run Code Online (Sandbox Code Playgroud)
调用函数调用函数 有两种可能的方法.您可以直接通过名称调用函数,也可以使用VBScript调用语句调用它.
按名称 调用函数直接按名称调用函数时,如果没有赋值给返回值,则以下所有内容都是合法语法:
MyFunction
MyFunction()
MyFunction intUsageFee, intTimeInHours, "DevGuru"
Run Code Online (Sandbox Code Playgroud)
如果需要返回值,可以将该函数分配给变量.请注意,如果有一个或多个参数,则必须使用括号.
returnval = MyFunction
returnval = MyFunction()
returnval = MyFunction(intUsageFee, intTimeInHours, "DevGuru")
Run Code Online (Sandbox Code Playgroud)
我刚发现一些奇怪的行为调用带/不带括号的函数.谷歌把我带到了这里.
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
Run Code Online (Sandbox Code Playgroud)
我的结论是,在调用只有一个参数的函数时,你必须使用Call或省略括号,否则参数不会通过引用传递(它仍然被调用,因为我已经检查过了).
我只花了10分钟找出一个"类型不兼容"的异常,同时调用一个带有1个参数的Sub
CallMe(argument)
Run Code Online (Sandbox Code Playgroud)
事实证明,这是无效的,谷歌搜索引导我到这里,最后
Call CallMe(argument)
Run Code Online (Sandbox Code Playgroud)
要么
CallMe argument
Run Code Online (Sandbox Code Playgroud)
做了伎俩.因此,在调用没有call-statement的sub时,不能使用括号,而call语句只需要1个参数.