是否可以在VBA Class Sub或Property中限制ParamArray的args?

时间:2017-04-12 17:04:39

标签: arrays excel vba excel-vba parameters

我正在创建一个vba excel类,并试图弄清楚如何允许用户设置适用于变量/字段的值组。根据我的阅读,除非您打算要求它们,否则不可能在属性上有多个参数。我要做的是让它只需要第一个参数,剩下的参数数量是可选的。我似乎建议在需要使后续参数可选时使用sub。这很好,例如,当我设置以下Sub

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

由于只有两个参数,我只需要一个参数,上述设置就足够了。但是,我有其他属性,我需要允许最多30个值,我真的宁愿不硬编码1所需的值和29可选,因为这似乎是糟糕的设计。那是我开始研究ParamArray选项的时候。 ParamArray非常适合这种情况,除了我遇到的一个问题。 ParamArray允许你想要的任意数量的args,我需要能够将它限制为29(加上所需的)。那么,有没有办法限制ParamArray的上限只允许Sub的这么多参数?

如下所示

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

End Sub

这可能吗?如果是这样,怎么样?如果没有,你会怎么建议我去看看这个场景?

1 个答案:

答案 0 :(得分:2)

这是不可能的。 ParamArray,如名称所示,为您提供参数数组

ParamArray只能通过引用传递(隐式 - 显式ByRef不会编译),并且只能是Variant项的数组,并且可以' t Optional - 所以这不能编译:

Optional ParamArray KeywordTwoThroughThirty(29) as String

相反,您只需:

ParamArray KeywordTwoThroughThirty()

可以做什么,使用保护条款在他们提供太多参数时向调用者抛出错误 - 有趣的是它似乎{ {1}}对Option Base数组的基本边界没有影响,无论ParamArray设置如何,这似乎都为0 ..这使得验证指定了多少参数变得更加简单:

Option Base

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

IntelliSense 不会帮助您的来电者知道他们通过了多少参数:

IntelliSense showing only one argument

如果您希望调用代码的 IntelliSense 看起来像这样:

IntelliSense showing all arguments, optional ones in square brackets

...然后你需要为你可以得到的30个参数中的每一个都指定显式的可选参数

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 是如何做到的。

Application.Run intellisense

我建议明确地传递它们Application.Run

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

ByVal

现在,如果您的实施假定为空DoSomething arg1:="foo", arg14:="bar" 表示空arg2而空arg3,那么您就会有错误...而{{1}解决方案并不能完全允许用户使用命名参数搞乱,如果需要,您的实现可以迭代数组,具体取决于此目的。

我建议采用不同的方法。

arg14

如果来电者无法致电ParamArray,您的班级将无法获得Public Sub SetCategories(CategoryOne As String, Optional CategoryTwo As String) pCategories(0) = CategoryOne pCategories(1) = CategoryTwo End Sub 的价值 - 所以我会按照您的第一个想法:索引属性:

pCategories(0)

然后公开一些SetCategories方法:

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

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