如果Instr函数与命名参数一起使用,且返回值分配给变量,则VBA编译错误
Background:在VBA中,可以在不使用或使用命名参数的情况下调用“InStrRev”函数如果Instr函数与命名参数一起使用,且返回值分配给变量,则VBA编译错误,vba,arguments,named,list-separator,Vba,Arguments,Named,List Separator,Background:在VBA中,可以在不使用或使用命名参数的情况下调用“InStrRev”函数 'Call without named parameters Call InStrRev("AB", "B") 'No compiler error i = InStrRev("AB", "B") 'No compiler error 'Call with named paramet
'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
问题:在VBA中,如果'InStr'函数:
- 使用命名参数和
- 它的返回值被指定给一个变量
'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"
备注:“String1”和“String2”是上述屏幕截图工具提示方括号中“InStr”函数的可选参数。但是,正如下面的答案和Visual Basic语言参考中所述,它们是必需的:
InStr
很奇怪,因为它的第一个参数(Start
)是可选的,但是它随后的String1
/String2
参数不是(尽管工具提示中有[]
)-如果它们是可选的InStr(1)
将进行分析,但不会进行分析,并生成与您看到的相同的错误
具体来说,这很奇怪,因为VBA不允许这样做;这里的规则是非可选参数不能跟在可选参数后面,这是有道理的,因为在某些情况下,编译器无法将参数与函数所期望的匹配。这也迫使它的所有参数都是变体
VB6/A有很多从QBASIC遗留下来的包袱,而且该语言(iirc不允许用户定义可选参数)的INSTR()
具有完全相同的签名,因此我假设您看到的行为是调用INSTR
必须存在的特殊解析规则的产物
奇怪的是它的完全限定名
i = VBA.Strings.InStr(String1:="AB", String2:="B")`
执行解析,但在运行时生成错误,除非提供了Start
:
i = VBA.Strings.InStr(String1:="AB", String2:="B", Start:=1)`
这和预期的一样
调用
表单看起来有效的一个原因是它是一个无操作,可能会被优化掉
VBA.X()vs X() 这很好:
ptr = VBA.CLng(AddressOf someFunc)
这将生成分析时预期的表达式错误:
InStr通过变量参数重载
InStr
函数在设计时有4个可选参数,但在运行时必须至少提供2个参数。InStr
的前3个参数都是Variant
,它允许InStr
支持两种不同的语法,并有效地模拟重载函数。这就是String1
和String2
被定义为Variant
类型而不是String
类型的原因之一<代码>开始可以是长
,但它也是变体
类型
在以下4个示例中,x
始终分配值4
选项1-使用定义的参数顺序或名称含义
函数签名的行为与定义的一样:
函数指令([Start]、[String1]、[String2]、[Compare As VbCompareMethod=vbBinaryCompare])
选项2-使用替代顺序或名称含义
函数签名的行为就像它的定义一样:
函数指令([String1]、[String2]、[Compare As VbCompareMethod=vbBinaryCompare])
这实际上意味着Start
应该像String1
一样使用,而String1
应该像String2
一样使用。必须省略String2
参数,否则会出现类型不匹配
错误
x = VBA.InStr("food", "D", , vbTextCompare) '4
x = VBA.InStr(Start:="food", String1:="D", Compare:=vbTextCompare) '4
使用命名参数
但正如您所发现的,InStr
函数在使用命名参数时会出现语法和/或编译错误:
语法错误:应为列表分隔符
命名所有参数时:
x = InStr(Start:=1, String1:="foo", String1:="foo", Compare:=vbBinaryCompare)
x = InStr(1, String1:="foo", String2:="foo", Compare:=vbBinaryCompare)
你会得到:
语法错误:应为列表分隔符
编译错误:对象不支持命名参数
命名某些参数时:
x = InStr(Start:=1, String1:="foo", String1:="foo", Compare:=vbBinaryCompare)
x = InStr(1, String1:="foo", String2:="foo", Compare:=vbBinaryCompare)
你会得到:
编译错误:对象不支持命名参数
StrComp函数的错误相同
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
但正如OP所发现的那样,InStrRev
不会出现错误
那么,InStr
和StrComp
有什么共同点不同于InStrRev
和所有其他VBA函数
嗯,InStr
和StrComp
都有以下特点:
- 函数在第一个引用的类型库中定义
- 这些功能在TLB/COM模块中定义
- 除最后一个参数外,所有参数均为
类型变量
- 最后一个参数是带有默认值的
Enum
- 返回值是一个变量
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
好问题,在VB6中的行为相同。感谢您的澄清。 还有一件事我还不清楚。你如何解释以下内容? 没有编译器错误① 【i=VBA.Strings.InStr(String1:=“AB”,String2:=“B”,Start:=1)】,② 【i=Strings.InStr】(