如何将字符串转换为其类似于 Java 的 .valueOf 的枚举值?
How do I convert a String to its Enum value similar to Java's .valueOf?
给定一个枚举:
Public Enum Options
optionA
optionB
optionC
End Enum
和一个字符串myString = "optionB"
,有没有快速的方法将字符串转换为相应的枚举值? (Options.optionB
/ 1
)
即我正在寻找 VBA 相当于 Java 的 .valueOf()
我知道我可以写一个 Select Case
,但这就像重新编写枚举的定义,一旦枚举的值发生变化就很难维护。
已编辑 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 进行初步设置(参见“为了在您的项目中使用此页面上的代码,您必须更改两个设置。 ”到“包含 CAUTION”子句)
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
给定一个枚举:
Public Enum Options
optionA
optionB
optionC
End Enum
和一个字符串myString = "optionB"
,有没有快速的方法将字符串转换为相应的枚举值? (Options.optionB
/ 1
)
即我正在寻找 VBA 相当于 Java 的 .valueOf()
我知道我可以写一个 Select Case
,但这就像重新编写枚举的定义,一旦枚举的值发生变化就很难维护。
已编辑 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 进行初步设置(参见“为了在您的项目中使用此页面上的代码,您必须更改两个设置。 ”到“包含 CAUTION”子句)
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