是否有可能限制在一个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 Base
对ParamArray
数组的基本边界没有影响,这似乎是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
如何做到的。
我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将会处理超出范围的错误。