Reputation: 53
I'm trying to add validation to a Cell but I would like to use an Enum as Source.
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
Normally I would put Join(account, ",")
if account would be an array, but for an Enum it doesn't work. And if direct usage of Enum is not possible how can I add enum values to an array?
Upvotes: 2
Views: 1784
Reputation: 53
I found it easier to maintain the accounts hard coded in a function
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
Then I can access the values in the 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
The Cell in the excel sheet displays the required list. However I don't know if this is a good design...
Upvotes: 0
Reputation: 38520
It's not as straightforward as you would wish, but there is a way to do this.
The underlying value of an Enum is of type Long. So it's a number, not a string. Only the VBA compiler knows about AA
; this gets translated into 0
everywhere else (and BB
is 1
, PP
is 2
, etc.). So the first thing to do is to explicitly associate a string to each enum option. I've done this using functions like this, which are easy to make but do require a little bit of manual maintenance each time you add, remove, or modify an enum option:
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
Then you want to loop through all enum options, making a list of their associated string. You could in principle say
Dim a As account
For a = AA To ZZ
'...
But that will be very difficult to maintain: what if you add another enum option such that ZZ
isn't the last anymore? Then you'll have to change your code. A better option is to put a little more work in the enum declaration itself:
Public Enum account
[_First] = 1
AA = 1
BB = 2
PP = 3
ZZ = 4
[_Last] = 4
End Enum
Here you explicitly assign values to each option (rather than letting the compiler assign defaults) and you also add a First
and a Last
indicating the bounds of the enum. These require manual maintenance, but this is trivial in comparison to the trouble of maintaining the rest of the code as would be required without this trick.
Note on syntax: the _
underscore makes the _First
and _Last
elements hidden (they will not be displayed in the VB Editor's autocompletion) and the [
square brackets ]
make the underscore character valid for use as the first character of a variable name. (source of this trick)
Now you can loop through your enum options, collect the associated strings in an array, join it with ,
delimiters, and use that as validation formula:
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
Note that each time you add or remove enum options, the following things will require manual maintenance:
account
enum definition, making sure that the numbering is sequential and that the First
and Last
elements actually represent the bounds, andAccountEnumString
function, making sure the strings are representative of the enum options to your satisfactionAlso see these somewhat related questions:
Upvotes: 3