如何在 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
;这在其他任何地方都被翻译成 0
(BB
是 1
,PP
是 2
,等等)。所以要做的第一件事就是明确地将一个字符串关联到每个枚举选项。我已经使用这样的函数完成了这项工作,这些函数很容易制作,但每次添加、删除或修改枚举选项时都需要一些手动维护:
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
枚举定义,确保编号是连续的并且 First
和 Last
元素实际代表边界,并且
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 中的单元格显示所需的列表。但是我不知道这是不是一个好的设计...
我正在尝试向单元格添加验证,但我想使用枚举作为源。
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
;这在其他任何地方都被翻译成 0
(BB
是 1
,PP
是 2
,等等)。所以要做的第一件事就是明确地将一个字符串关联到每个枚举选项。我已经使用这样的函数完成了这项工作,这些函数很容易制作,但每次添加、删除或修改枚举选项时都需要一些手动维护:
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
枚举定义,确保编号是连续的并且First
和Last
元素实际代表边界,并且 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 中的单元格显示所需的列表。但是我不知道这是不是一个好的设计...