是否有可能限制在一个VBA类的子或属性ParamArray的参数?

我创build了一个VBA的Excel类,并试图找出如何让用户设置适用于variables/字段的值组。 从我读过的内容来看,不可能在一个属性上有多个参数,除非你打算要求它们。 我想要做什么是这样的,只有第一个参数是必需的,其余的参数是可选的。 我似乎build议使用一个子需要使随后的参数可选。 这工作正常,例如,当我设置以下小组

Public Sub SetCategories(CategoryOne As String, Optional CategoryTwo As String) pCategories(0) = CategoryOne pCategories(1) = CategoryTwo End Sub 

由于只有两个参数,我只需要一个参数,上面的设置就足够了。 然而,我有其他的属性,我需要允许多达30个值,我真的宁愿不硬编码1所需的值和29可选,因为这只是看起来像不好的devise。 那时候我开始关注ParamArray选项。 ParamArray对于这种情况是完美的,除了我遇到的一个问题。 ParamArray允许尽可能多的参数,我需要能够限制到29(加上所需的)。 那么,有没有办法限制一个ParamArray的上限,只允许一个Sub的这么多的参数?

像下面这样

 Public Sub SetKeywords(KeywordOne As String, Optional ParamArray KeywordTwoThroughThirty(29) as String) End Sub 

那可能吗? 如果是这样,怎么样? 如果不是,你会怎么build议我去做这个scenerio?

这是不可能的。 ParamArray ,作为名称状态,给你一个参数数组

一个ParamArray只能被引用传递(隐式 – 显式的ByRef不会被编译),并且只能是一个Variant项目的数组,并且不能是Optional – 所以这个编译不能:

 Optional ParamArray KeywordTwoThroughThirty(29) as String 

相反,你只需要做:

 ParamArray KeywordTwoThroughThirty() 

可以做的是使用一个guard子句在调用者提供了太多的参数时抛出一个错误 – 有趣的是,似乎Option BaseParamArray数组的基本边界没有影响,这似乎是0,不pipeOption Base设置..这使得更简单的validation指定了多less参数:

 Const maxArgs As Long = 30 If UBound(KeywordTwoThroughThirty) + 1 > maxArgs Then Err.Raise 5, "SetKeywords", _ "Too many arguments were specified. Maximum is " & maxArgs & "." End If 

现在,调用者可以传递多达30个可选参数; 如果他们通过31或更多,他们将不得不处理运行时错误5“无效的程序调用或参数”,在这里特别适合。


智能感知不能帮助你的调用者知道他们传递了多less个参数:

智能感知只显示一个参数

如果你想调用代码的IntelliSense看起来像这样:

智能感知显示所有参数,方括号中的可选参数

…那么你需要为你可以得到的30个参数中的每一个指定显式的可选参数。

这就是Application.Run如何做到的。

Application.Run智能感知

我build议尽可能传递他们所有明确的ByVal

你可以打的一个问题是,一个聪明的来电者可以做到这一点:

 DoSomething arg1:="foo", arg14:="bar" 

而现在如果你的实现假定一个空的arg2意味着一个空的arg3和一个空的arg14 ,那么你会有错误…而ParamArray解决scheme并不完全允许用户使用命名参数搞砸了,你的实现可以迭代数组,如果需要的话,这取决于这个目的。


我会推荐一个不同的方法。

 Public Sub SetCategories(CategoryOne As String, Optional CategoryTwo As String) pCategories(0) = CategoryOne pCategories(1) = CategoryTwo End Sub 

如果调用者没有调用SetCategories ,那么你的类将不会有pCategories(0)的值 – 所以我会用你的第一个想法:一个索引属性:

 Public Property Get Category(ByVal index As Long) As String Category = pCategories(index) End Property Public Property Let Category(ByVal index As Long, ByVal value As String) pCategories(index) = value End Property 

然后暴露一些Init方法:

 Public Sub Init(ByVal category1 As String) ReDim pCategories(0 To 29) As String pCategories(0) = category1 End Sub 

这样的来电可以做到这一点:

 With foo .Init "bar" .Category(1) = "smurf" .Category(2) = "blah" '... End With 

他们可以使用循环和其他数据结构来访问和操作封装的项目; 如果他们尝试使用超过30个元素,VBA将会处理超出范围的错误。