【问题标题】:How do I convert a String to its Enum value similar to Java's .valueOf?如何将字符串转换为类似于 Java 的 .valueOf 的枚举值?
【发布时间】:2016-08-27 07:58:25
【问题描述】:

给定一个枚举:

Public Enum Options
    optionA
    optionB
    optionC
End Enum

和一个字符串myString = "optionB",有没有一种快速的方法可以将字符串转换为相应的枚举值? (Options.optionB/1)

即我正在寻找与 Java 的 .valueOf() 等效的 VBA

我知道我可以写一个Select Case,但这就像再次编写枚举的定义一样,一旦枚举的值发生变化就很难维护。

【问题讨论】:

  • 不在 VBA 中,您必须构建自己的函数才能做到这一点。
  • 我认为没有比制作包含Select Case 的函数更简洁的方法了。我通常做两个:OptionStringToEnum 和反向操作OptionEnumToString。 “一旦枚举值发生变化就很难维护”当然,但是如果 OptionC 发生变化,像 .valueOf("OptionC") 这样的代码同样难以维护。我没有看到相对的好处。
  • @Jean-FrançoisCorbett 你说得对,维护 .valueOf() 会很困难。这就是为什么我要求一种无需维护即可对.valueOf() 进行编码的方法。这在 Java 中是可能的,所以我认为在 VBA 中也可能 - 但它似乎并不/非常困难。

标签: vba string-conversion


【解决方案1】:

已编辑 2:添加解决方案 #3 其中

  • 具有解决方案 #2 的所有优点,即

    • valueOf 功能

    • 单个枚举声明(嗯,有点……)

    • 智能感知

  • 对于 Class 和 Enum 需要(即使略有不同)不同的名称(在解决方案 #2 中它们是“OptionsC”和“Options”)没有缺点

  • 仍然基于 VBE 对象模型 -> 需要一些初步步骤(参见步骤 2))


解决方案 #3

1) 在您的项目中添加一个 Class 模块,将其命名为“EnumClass”(或其他)并输入以下代码

Option Explicit

Private Enums_ As Variant

Public optionA As String
Public optionB As String
Public optionC As String

Private Sub Class_Initialize()
    optionA = "optionA"
    optionB = "optionB"
    optionC = "optionC"
    Enums_ = GetEnums
End Sub

Public Property Get valueOf(enumText As String) As Long
    Dim i As Long
    valueOf = -1
    For i = LBound(Enums_) To UBound(Enums_)
        If enumText = Enums_(i) Then
            valueOf = i
            Exit For
        End If
    Next i
End Property

Private Function GetEnums() As Variant
    Dim VBProj As VBIDE.VBProject
    Dim CodeMod As VBIDE.CodeModule
    Dim lineCount As Long
    Dim strEnum As String

    Set CodeMod = ActiveWorkbook.VBProject.VBComponents("EnumClass").CodeModule

    lineCount = 9 'if you keep class code as this one, you'd need checking lines from line 9. otherwise set it to 1 as a general setting
    With CodeMod

        Do Until InStr(UCase(.Lines(lineCount, 1)), UCase("Class_Initialize")) > 0
            lineCount = lineCount + 1
        Loop

        lineCount = lineCount + 1
        Do Until InStr(.Lines(lineCount, 1), "Enums_ = GetEnums") > 0
            strEnum = strEnum & GetTextWithingQuotes(.Lines(lineCount, 1)) & ","
            lineCount = lineCount + 1
        Loop
    End With
    GetEnums = Split(Left(strEnum, Len(strEnum) - 1), ",")

End Function

Private Function GetTextWithingQuotes(strng As String) As String
    Dim i1 As Long, i2 As Long

    i1 = InStr(strng, "=")
    i1 = InStr(i1, strng, Chr(34))
    i2 = InStr(i1 + 1, strng, Chr(34))
    GetTextWithingQuotes = Mid(strng, i1 + 1, i2 - i1 - 1)

End Function

2) 按照here 进行初步设置(参见“为了在您的项目中使用此页面上的代码,您必须更改两个设置。”到“注意”子句)

3) 在您的主子中利用它,如下所示

Option Explicit

Sub main()
Dim Options As New EnumClass '<== declare a variable of the EnumClass (or whatever the name you chose) and set it to a new instance of it
Dim myString As String

myString = "optionB"
MsgBox "string value of 'Options.optionB' = " & Options.optionB 'exploit intellisense
MsgBox "long Value of 'OptionB' =" & Options.valueOf(myString) 'convert the string to corresponding "enum" value

End Sub

这里遵循之前的解决方案#2

1) 在您的项目中添加一个模块,将其命名为“OptionsModule”(或其他任何名称)并将您的“Enum”放在那里

Public Enum Options
    optionA
    optionB
    optionC
End Enum

2) 在您的项目中添加一个 Class 模块,将其命名为“EnumClass”(或其他)并放入以下代码

Option Explicit

Private Enums_ As Variant

Public Property Let Enums(enumArr As Variant)
  Enums_ = enumArr
End Property

Public Property Get valueOf(enumText As String) As Long
    Dim i As Long
    valueOf = -1
    For i = LBound(Enums_) To UBound(Enums_)
        If enumText = Enums_(i) Then
            valueOf = i
            Exit For
        End If
    Next i
End Property

3) 添加对“Microsoft Visual Basic for Applications Extensibility Library”的引用

4) 添加此函数(在项目的任何模块中)

Function GetEnums() As Variant
    Dim VBProj As VBIDE.VBProject '<== this needs that reference to "Microsoft Visual Basic for Applications Extensibility Library"
    Dim CodeMod As VBIDE.CodeModule '<== this needs that reference to "Microsoft Visual Basic for Applications Extensibility Library"
    Dim lineCount As Long
    Dim strEnum As String

    Set CodeMod = ActiveWorkbook.VBProject.VBComponents("OptionsModule").CodeModule

    lineCount = 2
    With CodeMod
        Do Until InStr(UCase(.Lines(lineCount, 1)), UCase("End Enum")) > 0
            strEnum = strEnum & WorksheetFunction.Trim(.Lines(lineCount, 1)) & ","
            lineCount = lineCount + 1
        Loop
    End With
    GetEnums = Split(Left(strEnum, Len(strEnum) - 1), ",")

End Function

5) 在你的主子中利用它,如下所示

Sub main()
Dim OptionsC As New EnumClass '<== declare a variable of the EnumClass (or whatever the name you chose) and set it to a new instance of it
Dim myString As String

OptionsC.Enums = GetEnums() '<== fill your "Enum" class reading Module with enum

myString = "optionB"

MsgBox OptionsC.valueOf(myString) 'convert the string to corresponding "enum" value

End Sub

这里遵循之前的解决方案#1

1) 添加一个 Class 模块,将其命名为“EnumClass”(或其他)并放入以下代码

Option Explicit

Private Enums_ As Variant

Public Property Let Enums(enumArr As Variant)
  Enums_ = enumArr
End Property

Public Property Get valueOf(enumText As String) As Long
    Dim i As Long
    valueOf = -1
    For i = LBound(Enums_) To UBound(Enums_)
        If enumText = Enums_(i) Then
            valueOf = i
            Exit For
        End If
    Next i
End Property

2) 然后在你的主要子利用它如下

Option Explicit

Sub main()
Dim Options As New EnumClass '<== declare a variable of the EnumClass (or whatever the name you chose) and set it to a new instance of it
Dim myString As String

Options.Enums = Array("optionA", "optionB", "optionC") '<== fill your "Enum" class with string values

myString = "optionB"

MsgBox Options.valueOf(myString) 'convert the string to corresponding "enum" value

End Sub

【讨论】:

  • 感谢这个好建议!不幸的是,这仍然需要我写两次枚举的值。我想把这个问题留多一点,看看是否有更好的答案,但如果找不到,我会选择你的。
  • 只是指出你必须只写一次枚举值:当你填写类“枚举”属性时
  • 在定义实际的 Enum 时我是否也需要先编写它们? (或错过一些功能,如智能感知)
  • 使用“Enum”类,您根本不需要真正的 Enum。前者只是替换后者。
  • @Jean-François Corbett:我也不会!但这对我来说很有趣也很有启发性,我把它看作是由这种特殊的 OP 需求驱动的挑战。
猜你喜欢
  • 1970-01-01
  • 2013-07-03
  • 1970-01-01
  • 2018-02-14
  • 2017-10-13
  • 1970-01-01
  • 2015-06-29
  • 1970-01-01
相关资源
最近更新 更多