以编程方式分配Bang参数?

时间:2017-04-05 22:58:28

标签: vba excel-vba excel

我没有成功使用Bang(!)运算符而没有将其参数硬编码,即Me.VBProject.References!Excel。在此示例中, Excel 引用是硬编码的。 出于挫败感,我尝试了所有可以想到的排列,试图利用它:

[Me.VBProject.References!(str)]
[Me.VBProject.References! & (str)]
["Me.VBProject.References!" & str]
["Me.VBProject.References!" & (str)]

以及更多的parens添加,以确保适当的预评估,包括速记Application.evaluate方法。纳达!

2 个答案:

答案 0 :(得分:5)

不,你不能这样做。

bang运算符只是调用对象默认成员的快捷方式,并将bang之后的文本作为字符串传递给默认成员的第一个参数:

轰号:

Me.VBProject.References!Excel

完全等同于:

Me.VBProject.References.Item("Excel")

并且,因为它是默认成员,所以可以省略Item函数调用:

Me.VBProject.References("Excel")

所以,要使用你的(命名非常严重)变量str

str = "Excel"
Debug.Print Me.VBProject.References.Item(str).Name

答案 1 :(得分:2)

这是一个X-Y问题。

Bang符号是达到目的的手段。

它是您可以使用的工具之一,从集合中检索项目

没有更多,没有更少。

  

你想要的是使用带有变量的爆炸操作符
  你想要的是使用变量从集合中检索一个项目。

集合类型具有默认成员,通常名为Item。可以显式指定默认成员,也可以隐式访问默认成员:

Dim foo As New Collection
foo.Add Item:=42, Key:="test"
Debug.Print foo.Item("test") 'explicit reference to the default member
Debug.Print foo("test") 'implicit reference to the same default member

bang运算符只是对集合的默认成员进行隐式调用的另一种方式:

Debug.Print foo!test

上述所有3条Debug.Print语句都会调用foo.Item默认成员输出与密钥42相关联的"test"

方括号

正如您所看到的,!运算符后面的内容实际上是字符串文字。因为字符串文字可以包含空格,所以VB6 / VBA解析器需要一种方法来支持它们。

那是[square brackets]的用途:

foo.Add 72, "spaces in the key"
Debug.Print foo![spaces in the key]

当他们没有为bang表示法分隔字符串文字时,方括号通常 1 被解释为主机应用程序要评估的运行时表达式。例如,这在Excel VBA中是合法的(尽管可疑):

Debug.Print [A1]

VBA解析器识别括号内的表达式,并将其评估推迟到主机应用程序 - 这里是Excel; 在运行时,指令最终等同于:

Debug.Print ActiveSheet.Range("A1").Value

如果您不相信对括号内的表达式的评估被推迟到主机应用程序,请考虑该指令要打印4需要做什么:

Debug.Print [Sum(2,2)]

因此,您帖子中的每一次尝试/排列都错过了标记,并使 Excel 尝试评估只有VBA才能解析的表达式,因为Me.VBProject.References表示绝对没有Excel。

通常应避免使用方括号表达式,因为您将丢失编译时检查,并且只能在运行时捕获任何错误。

1 通常,因为它们也可用于某些标识符,  例如,在Enum类型中,创建[_hidden]枚举成员。

底线

Bang notation是一种通过利用默认成员并使字符串文字看起来像作为标识符来从集合中检索项目的方法。没有"硬编码"你不能让它工作。字符串文字,因为需要字符串文字

如果您想参数化集合检索,则无法使用bang运算符。

对于更快地输入代码非常有用。如果您不完全了解 它是如何工作的,以及它为您做了什么,它是一个双刃剑,隐藏了真正发生的事情< / strong>并最终使代码更难阅读和理解。代码不应该只是为了运行而编写。应将代码编写为 read 理解

注意:Bang符号实际上 仅适用于集合。它实际上将其参数作为字符串文字传递给具有默认成员的任何内容的第一个参数。我强烈建议避免使用除集合类以外的任何内容(例如Collection.ItemWorkbooks.ItemWorksheets.ItemRecordset.Fields等),以便将来维护者和#39;理智。