【问题标题】:VBA: Usage of parentheses for a methodVBA:方法的括号用法
【发布时间】:2019-06-20 19:34:53
【问题描述】:

在使用或省略括号时调用方法的正确方法是什么?如果我正确理解我的谷歌搜索结果:在将方法(或函数)的返回值分配给变量时,您必须使用括号。下面是一些例子:

  1. wbData.Sheets.Add '-> works

  2. Set wsData = wbData.Sheets.Add '-> works

  3. wbData.Sheets.Add(Before:=wbData.Sheets(wbData.Sheets.Count)) '-> syntax error

  4. Set wsData = wbData.Sheets.Add(Before:=wbData.Sheets(wbData.Sheets.Count)) '-> works

  5. wbData.Sheets.Add Before:=wbData.Worksheets(wbData.Worksheets.Count) '-> works

  6. Set wsData = wbData.Sheets.Add Before:=wbData.Worksheets(wbData.Worksheets.Count) '-> syntax error

只是为了确保我得到了 VBA 逻辑:#3 给了我一个错误,因为 VBA 的括号意味着值(= 新工作表)被返回,但是没有变量可以分配给它? #6是相反的情况?

即使我的解释尝试是正确的,有人可以向我解释why the example on the official help page 对我不起作用:

ActiveWorkbook.Sheets.Add(Before:=Worksheets(Worksheets.Count))

这给了我一个语法错误,与上面列表中的 #3 相同。对此我感到很困惑。

【问题讨论】:

  • 根据我的经验,当您使用参数设置对象/变量时需要()
  • @DavidZemens - 该链接指向“Office VBA 参考”...
  • 他们的参考/示例错误或包含错误信息也不是第一次了 :)
  • @DavidZemens - 好点:我没有注意到“VB”标签
  • 我真的不知道。可能不是。就像我上面提到的,它们都曾经是 VB 或 C#,而 VB 的对 VBA 来说准确率为 99%。我只是听听 Tim 的最后评论:需要注意的一点是,当 Vb 编辑器在方法名称和左括号之间放置一个空格时——如果发生这种情况,这表明你可能根本不需要括号.

标签: excel vba


【解决方案1】:

“官方帮助页面”在 GitHub 上,它得到积极维护,每天都在合并多个更改。如果示例中有错误,open an issue for it,或者更好的是submit a fix yourself

示例错误,不应该有括号,或者表达式应该在 Set 分配给某个对象变量的右侧。

将方法(或函数)的返回值赋给变量时必须使用括号

正确。

当你不捕获返回值时,你不放括号。如果你这样做了,VBE 会给你一个提示。如果您从文档中复制了示例,它在编辑器中将如下所示:

ActiveWorkbook.Sheets.Add (Before:=Worksheets(Worksheets.Count))

注意空格。如果你捕获了返回值:

Set newSheet = ActiveWorkbook.Sheets.Add(Before:=Worksheets(Worksheets.Count))

没有空间。

只是为了确保我得到了 VBA 逻辑:#3 给了我一个错误,因为 VBA 的括号意味着值(= 新工作表)被返回,但是没有变量可以分配给它?而#6 是相反的情况?

不止于此。考虑一个更简单的例子:

MsgBox "hi", vbOkCancel

如果我们想捕获或以其他方式使用返回值,我们需要括号:

If MsgBox("hi", vbOkCancel) = vbOk Then

如果我们在不捕获/使用返回值的情况下添加括号,我们会这样:

MsgBox ("hi", vbOkCancel)

那么这个空间是什么意思呢?

对于 VBA 编译器,这意味着“这不是参数列表,它是第一个参数,这是一个值表达式:计算它,然后发送结果ByVal 到被调用的过程”。当然,问题在于("hi", vbOkCancel) 不是表达式,无法计算,而且我们有一个编译错误。

回到文档示例:Before:=Worksheets(Worksheets.Count) 也不是合法的表达式 - 它是一个由一个命名参数组成的参数列表...但在语法上它是not the 参数列表:用括号括起来,它是一个表达式,如果它可以被计算,将被传递给参数列表的 first 参数,ByVal - 就像这样:

ActiveWorkbook.Sheets.Add Argument1:=(the result of the expression)

带括号的参数的ByVal 本质基本上是一个意外:当 VBA 计算表达式时,它会得到一个值...但是那个值是悬而未决的,没有本地 引用对它 - 所以即使被调用的过程接受ByRef 参数,由于调用者没有持有对该参数的引用,它被丢弃 - 有效地产生与函数采用参数ByVal 完全相同的结果。

令人困惑?这应该会有所帮助:

Public Sub Test()
    Dim foo As Long

    DoSomething (foo) ' evaluates the expression, passes the result of that expression
    Debug.Print foo ' prints 0

    DoSomething foo ' passes a reference to the local variable
    Debug.Print foo ' prints 42
End Sub

Private Sub DoSomething(ByRef value As Long)
    value = 42
End Sub

【讨论】:

    【解决方案2】:

    该方法是否返回您需要的值?使用括号(但如果没有将任何参数传递给方法除非您在同一行中使用返回值,则为可选)。

    例如 - 在RowRange 下方返回一个Range 对象,但是您不能使用 (2,1) 直接对其进行索引,因为这被解释为将参数传递给RowRange(不需要任何)

    s = myPivotTable.RowRange(2, 1).Value   'fails with "too many parameters"
    

    添加括号将其清除:

    s = myPivotTable.RowRange()(2, 1).Value 'OK
    

    使用呼叫?使用括号。但 Call 通常被认为已弃用。

    还有什么?括号不是必需的,并且可能会通过在传递参数之前对参数进行评估而产生意想不到的结果。

    需要注意的一点是,当 Vb 编辑器在方法名称和左括号之间放置一个空格时 - 如果发生这种情况,则表明您可能根本不需要括号。

    【讨论】:

    • 比我漫无边际的评论更简洁,解释得更好 =)
    • 不,我认为花更多的时间是值得的——尤其是当你使用不需要的括号时会发生什么
    • @TimWilliams 已经有 stackoverflow.com/a/10262247/11683 了。
    • @GSerg 用vba(和vbscript)重新标记那个是不合适的吗?我将其标记为有用的欺骗目标(应该将 this 问题标记为欺骗吗?)
    • @MathieuGuindon 我会拒绝re标签。至于添加标签,它肯定有利于未来的读者,即使从 OP 的角度来看添加标签似乎是错误的。这个问题,我认为关闭是重复的,然后我没有,因为 byval 行为只是一个在答案中值得一提的极端情况,这正是这个答案和我最初的评论所发生的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多