Fab*_*nay 6 vba arguments named list-separator
背景:在VBA中,可以在没有命名参数或使用命名参数的情况下调用" InStrRev "函数.
'Call without named parameters
Call InStrRev("AB", "B") 'No compiler error
i = InStrRev("AB", "B") 'No compiler error
'Call with named parameters
Call InStrRev(StringCheck:="AB", StringMatch:="B") 'No compiler error
i = InStrRev(StringCheck:="AB", StringMatch:="B") 'No compiler error
Run Code Online (Sandbox Code Playgroud)
关注:在VBA中,如果' InStr '函数,编译器返回"Expected:list separator"错误:
其返回值分配给变量
'Call without named parameters
Call InStr("AB", "B") 'No compiler error
i = InStr("AB", "B") 'No compiler error
'Call with named parameters
Call InStr(String1:="AB", String2:="B") 'No compiler error
i = InStr(String1:="AB", String2:="B") 'Compiler error : "Expected: list separator"
Run Code Online (Sandbox Code Playgroud)问题:当' Instr '函数与命名参数一起使用并且其返回值被赋值给变量时,为什么会出现VBA编译器错误?它是语言或编译器错误的限制吗?
参考:' InstrRev '和' Instr '功能工具提示的VBA编辑器截图.差异以红色突出显示.
备注:" 字符串1 "和" String2的 "是"的可选参数InStr函数 "功能根据上面的截图工具提示方括号中.但是,它们是必需的,如下面的答案和Visual Basic语言参考中所述:https://msdn.microsoft.com/EN-US/library/office/gg264811.aspx
该InStr函数在设计时有 4 个可选参数,但在运行时必须至少提供 2 个参数。前 3 个参数都是InStrall , Variant它允许InStr支持两种不同的语法并有效地模拟重载函数。String1这就是和String2被定义为Variant类型而不是类型的原因之一String。Start可能是一个Long,但它是一个Variant类型。
在以下 4 个示例中,始终x分配值4
选项 1 - 使用定义的参数顺序或名称含义
函数签名的行为与定义相同:
Function InStr([Start], [String1], [String2], [比较为 VbCompareMethod = vbBinaryCompare])
x = VBA.InStr(1, "food", "D", vbTextCompare) '4
x = VBA.InStr(Start:=1, String1:="food", String2:="D", Compare:=vbTextCompare) '4
Run Code Online (Sandbox Code Playgroud)
选项 2 - 使用替代顺序或名称含义
函数签名的行为就好像它的定义如下:
Function InStr([String1], [String2], , [比较为 VbCompareMethod = vbBinaryCompare])
这实际上意味着Start应该像它是一样使用String1并且String1应该像它一样使用String2。必须省略该String2参数,否则会出现错误。Type Mismatch
x = VBA.InStr("food", "D", , vbTextCompare) '4
x = VBA.InStr(Start:="food", String1:="D", Compare:=vbTextCompare) '4
Run Code Online (Sandbox Code Playgroud)
但正如您所发现的,该InStr函数在使用命名参数时会出现语法和/或编译错误:
语法错误:预期的列表分隔符
当所有参数都被命名时:
x = InStr(Start:=1, String1:="foo", String1:="foo", Compare:=vbBinaryCompare)
Run Code Online (Sandbox Code Playgroud)
你得到:
语法错误:预期的列表分隔符
编译错误:对象不支持命名参数
当某些参数被命名时:
x = InStr(1, String1:="foo", String2:="foo", Compare:=vbBinaryCompare)
Run Code Online (Sandbox Code Playgroud)
你得到:
编译错误:对象不支持命名参数
该StrComp函数似乎没有任何重载类型功能,但它存在与语法和编译错误相同的问题:
x = StrComp(String1:="foo", String2:="foo", Compare:=vbBinaryCompare) 'Syntax Error: Expected List Separator???
x = StrComp("foo", String2:="foo", Compare:=vbBinaryCompare) 'Compile error: Object doesn't support named arguments
Run Code Online (Sandbox Code Playgroud)
但正如OP发现的那样,错误不会发生在InStrRev.
那么,与看似所有其他 VBA 函数InStr有何StrComp共同点InStrRev和不同点呢?
好吧,InStr两者StrComp都有以下特征:
Variant类型。Enum带有默认值的我在 VBA 库中找不到任何其他具有这些特征的函数,因此我怀疑存在与这些特征相关的编译错误。
如果函数由库名称或模块名称限定,则和 都InStrRev可以StrComp与所有/部分命名参数一起使用:
'InStr Vanilla usage:
x = Strings.InStr(Start:=1, String1:="food", String2:="D", Compare:=vbTextCompare) '4
x = VBA.InStr(Start:=1, String1:="food", String2:="D", Compare:=vbTextCompare) '4
'InStr Alternate usage:
x = Strings.InStr(Start:="food", String1:="D", Compare:=vbTextCompare) '4
x = VBA.InStr(Start:="food", String1:="D", Compare:=vbTextCompare) '4
'StrComp usage
x = Strings.StrComp(String1:="food", String2:="D", Compare:=vbTextCompare) '1
x = VBA.StrComp(String1:="food", String2:="D", Compare:=vbTextCompare) '1
Run Code Online (Sandbox Code Playgroud)
InStr奇怪的是,它的第一个参数 ( Start) 是可选的,但其后续String1/String2参数不是(尽管[]工具提示中有) - 如果它们是可选的,InStr(1)则会解析,但不会解析,并生成与您看到的相同的错误。
具体来说,这很奇怪,因为 VBA 不允许这样做;规则是非可选参数不能跟随可选参数,这是有道理的,因为在某些情况下编译器无法将参数与函数期望的参数匹配。这也迫使它的所有参数都是变体。
VB6/A 有很多从 QBASIC 继承下来的包袱,并且该语言(iirc 不允许用户定义可选参数)具有完全相同的签名,因此INSTR()我假设您看到的行为是特殊解析规则的产物必须存在才能调用InStr.
奇怪的是它的完全限定名称
i = VBA.Strings.InStr(String1:="AB", String2:="B")`
Run Code Online (Sandbox Code Playgroud)
确实解析,但在运行时会产生错误,除非Start提供:
i = VBA.Strings.InStr(String1:="AB", String2:="B", Start:=1)`
Run Code Online (Sandbox Code Playgroud)
其按预期工作。
Call该表单看起来有效的一个原因是它是一个无操作并且可以被优化掉。
VBA.X() 与 X()
这完全没问题:
ptr = VBA.CLng(AddressOf someFunc)
Run Code Online (Sandbox Code Playgroud)
这会生成解析时间预期表达式错误:
ptr = CLng(AddressOf someFunc)
Run Code Online (Sandbox Code Playgroud)