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

How can I use an Enum for Validation in VBA

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

 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, ","),但对于枚举,它不起作用。如果无法直接使用枚举,我该如何将枚举值添加到数组?

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

枚举的基础值是 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

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

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 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 sheet 中的单元格显示所需的列表。但是我不知道这是不是一个好的设计...