如何在 VBA 中使用枚举进行验证

Posted

技术标签:

【中文标题】如何在 VBA 中使用枚举进行验证【英文标题】:How can I use an Enum for Validation in VBA 【发布时间】:2015-03-12 08:11:23 【问题描述】:

我正在尝试向单元格添加验证,但我想使用枚举作为源。

 Public Enum account

      AA
      BB
      PP
      ZZ

  End Enum

  Sub Main()

    With Range("C9").Validation
        .Delete
        .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
             Operator:=xlBetween, Formula1:= ...

  End With
End Sub     

如果帐户是一个数组,通常我会输入Join(account, ","),但对于枚举它不起作用。如果无法直接使用 Enum,我该如何将枚举值添加到数组中?

【问题讨论】:

【参考方案1】:

这并不像您希望的那样简单,但是有一种方法可以做到这一点。

Enum 的基础值是 Long 类型。所以它是一个数字,而不是一个字符串。只有 VBA 编译器知道AA;这会在其他任何地方翻译成0BB1PP2,等等)。所以要做的第一件事就是显式地将一个字符串与每个枚举选项关联起来。我已经使用类似这样的函数完成了这项工作,这些函数很容易制作,但每次添加、删除或修改枚举选项时都需要进行一些手动维护:

Function AccountEnumString(a As account) As String
    Select Case a
        Case AA: AccountEnumString = "AA"
        Case BB: AccountEnumString = "BB"
        Case PP: AccountEnumString = "PP"
        Case ZZ: AccountEnumString = "ZZ"
        Case Else: Err.Raise 9999, , "Unexpected enum value."
    End Select
End Function

然后你想遍历所有枚举选项,列出它们相关的字符串。原则上你可以说

Dim a As account
For a = AA To ZZ
'...

但这将很难维护:如果您添加另一个枚举选项以使ZZ 不再是最后一个呢?然后你必须改变你的代码。更好的选择是在枚举声明本身中多做一些工作:

Public Enum account
    [_First] = 1
    AA = 1
    BB = 2
    PP = 3
    ZZ = 4
    [_Last] = 4
End Enum

在这里,您明确地为每个选项分配值(而不是让编译器分配默认值),并且您还添加了一个 First 和一个 Last 来指示枚举的边界。这些需要手动维护,但与维护其余代码的麻烦相比,这是微不足道的,因为没有这个技巧。

语法注意事项:_ 下划线使_First_Last 元素隐藏(它们不会显示在VB 编辑器的自动补全中),[ 方括号] 使下划线字符有效用作变量名的第一个字符。 (source of this trick)

现在您可以遍历枚举选项,将关联的字符串收集到一个数组中,将其与, 分隔符连接起来,并将其用作验证公式:

Dim a As account
Dim arrValidationList() As String

ReDim arrValidationList(account.[_First] To account.[_Last])
For a = account.[_First] To account.[_Last]
    arrValidationList(a) = AccountEnumString(a)
Next

With Range("C9").Validation
    .Delete
    .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
         Operator:=xlBetween, Formula1:=Join(arrValidationList, ",")
End With

请注意,每次添加或删除枚举选项时,以下内容都需要手动维护:

account 枚举定义,确保编号是连续的,并且 FirstLast 元素实际上代表边界,并且 AccountEnumString 函数,确保字符串代表您满意的枚举选项

另请参阅这些有些相关的问题:

Use a builtin Enum in a cell formula with a UDF How can I use enum identifiers in Excel UDF

【讨论】:

感谢您的详细解答。我怕事情有那么复杂。似乎使用Collection 或类似的将是最简单和更清洁... 收藏有什么帮助? 或字典 - 将 Sub 中的硬编码值作为字典维护似乎更容易,然后将单独定义的枚举与函数一起使用,然后必须将其全部转换为 sub 中的数组。或者这会被认为是糟糕的设计? 不确定,我必须先看看它才能发表评论。但这将是一个新问题的内容,而不是冗长的评论。【参考方案2】:

我发现在函数中维护硬编码的帐户更容易

Function getAccounts() As Variant

Dim AccDict As Object

Set AccDict = CreateObject("Scripting.Dictionary")

AccDict.Add 1, "AA"
AccDict.Add 2, "BB"

AccDict.Add 10, "ZZ"
AccDict.Add 11, "PP"

getAccounts = AccDict.Items()

End Function

然后我可以访问 sub 中的值

  Sub Main()
  Dim accountList As Variant
  accountList = getAccounts()

    With Range("C9").Validation
        .Delete
        .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
             Operator:=xlBetween, Formula1:=Join(accountList, ",")

  End With
End Sub  

Excel 工作表中的单元格显示所需的列表。不过不知道这个设计好不好……

【讨论】:

以上是关于如何在 VBA 中使用枚举进行验证的主要内容,如果未能解决你的问题,请参考以下文章

Laravel,如何验证枚举列

无法在 VBA 中创建新枚举

如何在 Joi 字符串验证中使用枚举值

如何使用 VBA(没有 Internet Explorer)下载文件

如何实现动态数据验证,例如作为 Excel VBA 函数?

VBA:如何验证子表单中的绑定文本框