Как я могу использовать перечисление для проверки в 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, ","), если бы счет был массивом, но для перечисления это не работает. И если прямое использование перечисления невозможно, как я могу добавить значения перечисления в массив?
2 ответов:
Это не так просто, как вам хотелось бы, но есть способ сделать это.
Базовое значение перечисления имеет тип Long. Так что это число, а не строка. Только компилятор VBA знает о
AA; это переводится в0везде (иBBявляется1,PPИС2и др.). Поэтому первое, что нужно сделать, - это явно связать строку с каждым параметром enum. Я сделал это с помощью таких функций, которые легко сделать, но требуют немного ручного управления. обслуживание при каждом добавлении, удалении или изменении параметра перечисления: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больше не является последним? Тогда вам придется изменить свой код. Лучший вариант-вложить немного больше работы в само объявление enum:Public Enum account [_First] = 1 AA = 1 BB = 2 PP = 3 ZZ = 4 [_Last] = 4 End EnumЗдесь вы явно назначьте значения каждому параметру (вместо того, чтобы позволить компилятору назначать значения по умолчанию), а также добавьте
FirstиLast, указывающие границы перечисления. Они требуют ручного обслуживания, но это тривиально по сравнению с проблемой поддержания остальной части кода, которая потребовалась бы без этого трюка.Примечание по синтаксису: подчеркивание
_делает элементы_Firstи_Lastскрытыми (они не будут отображаться в автозавершении редактора VB) и квадрат[скобки]делают символ подчеркивания допустимым для использования в качестве первого символа имени переменной. (источник этого трюка )Теперь вы можете перебирать варианты перечисления, собирать связанные строки в массив, соединять его с разделителями
,и использовать это в качестве формулы проверки: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, убедившись, что строки представляют варианты перечисления к вашему удовлетворениюТакже смотрите эти несколько связанные вопросы:
Мне было проще поддерживать счета, жестко закодированные в функции
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 отображается требуемый список. Однако я не знаю, хороший ли это дизайн...
Comments