Как я могу использовать перечисление для проверки в 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, ","), если бы счет был массивом, но для перечисления это не работает. И если прямое использование перечисления невозможно, как я могу добавить значения перечисления в массив?

758   2  

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

    Ничего не найдено.