如何在VBA中使用Enum进行验证

时间:2015-03-12 08:11:24

标签: vba validation enums

我正在尝试向Cell添加验证,但我想使用Enum作为源。

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

2 个答案:

答案 0 :(得分:3)

这并不像你希望的那样简单,但有办法做到这一点。

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功能,确保字符串代表您满意的枚举选项

另见这些有些相关的问题:

答案 1 :(得分:0)

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

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