Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ms-access/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ms access VBA函数调用中括号的使用规则是什么?_Ms Access_Vba_Syntax - Fatal编程技术网

Ms access VBA函数调用中括号的使用规则是什么?

Ms access VBA函数调用中括号的使用规则是什么?,ms-access,vba,syntax,Ms Access,Vba,Syntax,我刚刚在VBA(Access 2003)中遇到了一个令人恼火的“编译器错误”,原因是我在传递给我定义的子对象的参数周围使用了括号 我一直在寻找一篇像样的文章/教程/说明,说明什么时候括号是必要的/合适的/不合适的/禁止的,但找不到任何明确的指南。来自: 使用VBScript Call语句调用子例程 当您希望调用子例程时,Call语句的使用是可选的。Call语句与Sub一起使用时的目的是允许您将参数列表括在括号中。但是,如果子例程不传递任何参数,则在使用Call语句调用子例程时仍不应使用括号 Ca

我刚刚在VBA(Access 2003)中遇到了一个令人恼火的“编译器错误”,原因是我在传递给我定义的子对象的参数周围使用了括号

我一直在寻找一篇像样的文章/教程/说明,说明什么时候括号是必要的/合适的/不合适的/禁止的,但找不到任何明确的指南。

来自:

使用VBScript Call语句调用子例程 当您希望调用子例程时,Call语句的使用是可选的。Call语句与Sub一起使用时的目的是允许您将参数列表括在括号中。但是,如果子例程不传递任何参数,则在使用Call语句调用子例程时仍不应使用括号

Call MySubroutine
如果子例程有参数,则在使用Call语句时必须使用括号。如果有多个参数,则必须用逗号分隔这些参数

Call MySubroutine(intUsageFee, intTimeInHours, "DevGuru") 
调用函数 调用函数有两种可能的方法。可以直接调用函数(仅按名称),也可以使用VBScript call语句调用函数

Call MySubroutine
按名称调用函数 直接按名称调用函数时,如果没有为返回值赋值,则以下所有语法都是合法的:

MyFunction
MyFunction()
MyFunction intUsageFee, intTimeInHours, "DevGuru"
如果需要返回值,可以将函数指定给变量。请注意,如果有一个或多个参数,则必须使用括号

returnval = MyFunction
returnval = MyFunction()
returnval = MyFunction(intUsageFee, intTimeInHours, "DevGuru") 
当你使用
Call MySub
您应该在参数周围使用括号,但如果省略调用,则不需要括号。

我刚刚花了10分钟时间在调用一个Sub时发现了一个“类型不兼容”异常,该Sub通过

CallMe(argument)
事实证明,这是无效的,谷歌搜索最终引导我来到这里

Call CallMe(argument)


成功了。因此,在调用没有call语句的sub时,不能使用括号,因为call语句只接受1个参数。

我刚刚发现调用带有/不带括号的函数时出现了一些奇怪的行为。谷歌把我带到这里

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

我的结论是,当只使用一个参数调用函数时,必须使用Call或省略括号,否则该参数不是通过引用传递的(正如我已经检查过的,它仍然被调用)。

VB(a)中的括号规则有完美的逻辑,它是这样的

如果使用参数调用过程(函数或子过程),并且调用与其他语句或关键字在同一行,则必须将参数括在括号中。这是为了将属于过程调用的参数与行的其余部分区分开来。因此:

1:   If CheckConditions(A, B, C) = DONT_PROCEED Then Exit Sub
是有效行;对CheckConditions的调用需要括号来指示行的其他位是它的参数。相反,这会产生语法错误:

2:   If CheckConditions A, B, C = DONT_PROCEED Then Exit Sub
因为它是不可能解析的

当过程调用作为行中的唯一语句时,不需要括号,因为参数显然属于过程调用:

3:   SaveNewValues Value1, Value2, Value3
虽然这会导致语法错误(原因如下所述):

为了避免关于括号或无括号的混淆(事实上,为了完全避免括号规则),最好使用Call关键字来调用这些调用;这确保过程调用不是该行上的唯一语句,因此需要括号:

5:   Call SaveNewValues(Value1, Value2, Value3)
Dim s As String
Dim l As Long 
s = "Hello World"
l = Len(s)
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
因此,如果您养成了使用Call关键字进行自包含过程调用的习惯,那么您可以忘记括号规则,因为您可以始终将参数括在括号中

括号在VB(A)(和许多其他语言)中扮演的额外角色使问题变得混乱:它们还表示表达式的求值优先级。如果在任何其他上下文中使用括号,但要将过程调用参数括起来,VB(A)将尝试将括号中的表达式求值为生成的简单值

因此,在示例4中,如果圆括号用于封闭参数是非法的,VB(A)将尝试对圆括号中的表达式求值。由于(Value1、value2、Value3)不是可以计算的表达式,因此会出现语法错误

这也解释了为什么当参数被括在括号中时,使用ByRef传递的变量调用的行为就像调用ByVal一样。在上面的示例中,当使用ByRef参数a调用函数p时,对p的这两个调用之间存在很大的差异:

6:  p a

正如上面所讨论的,6是正确的语法:调用在其行上是单独的,因此不应使用括号来括起参数

在第7章中,参数仍然用括号括起来,提示VB(A)将所括表达式求值为简单值。当然,这正是路过的定义。圆括号确保传递的不是指向a的指针,而是a的值,a保持不变

这也解释了为什么圆括号规则似乎并不总是占主导地位。最清晰的示例是MsgBox调用:

8:  MsgBox "Hello World!"

都是正确的,尽管括号规则规定9应该是错误的。当然是这样,但是所发生的只是VB(A)计算括号中的表达式。字符串文字的计算结果与字符串文字完全相同,因此实际调用为8。换句话说:使用常量或字符串文字参数调用单参数过程,无论是否使用括号,结果都是相同的。(这就是为什么即使是my MsgBox调用之前也会有Call关键字。)

最后,这解释了传递对象参数时奇怪的类型不匹配错误和奇怪的行为。假设您的应用程序有一个HighlightContent过程,该过程以文本框作为参数(并且,您永远猜不到,突出显示它的内容)。调用此选项可选择文本框中的所有文本。您可以用三种语法调用此过程
9:  MsgBox ("Hello World!")
10: HighlightContent txtName
11: HighlightContent (txtName)
12: Call HighlightContent(txtName)
MsgBox "Hello World"
Dim s As String
Dim l As Long 
s = "Hello World"
l = Len(s)
Call MsgBox("Hello World")
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