Reputation: 4692
I am riddling about if it is possible to conditionally switch the type of a function or variable between enum types.
Something like this:
Public Enum enmTest
eA = 1
eB = 2
eC = 3
End Enum
Public Enum enmDemo
eA = 10
eB = 50
eC = 100
End Enum
Public Function demoFunction() as enmDemo
Dim eDemo as enmDemo
ReDim eDemo as enmTest
ReDim demoFunction as enmDemo
End Function
'this does not work, but is there no way to make this work?
Public Sub test()
debug.print demoFunction().eA 'should be 1
End Sub
'this does not work, but is there no way to make this work?
Public Sub test2
Dim temp as Variant
temp = demoFunction()
debug.print temp.eB 'should be 2
End Sub
Basically the goal is to have a variable like Dim myVar
which might be an enumA
or enumB
type. These enums might be identicall, except their values.
My guess is this won't work at no angle, because of the way VBA handles enums. But just to make sure I would like to get an explanation, as I only have a gut feeling after an hour of experimenting.
My current workaround, which hopefully demonstrates my goal:
Public Enum enmTest
eA = 1
eB = 2
eC = 3
End Enum
Public Enum enmDemo
eA = 10
eB = 50
eC = 100
End Enum
Public Function demo()
Debug.Print Str(getValues(1)(1)) 'prints 1
Debug.Print Str(getValues(2)(1)) 'prints 10
End Function
Public Function getArray(val1, val2, val3) as Variant
Dim result as Variant
ReDim result(1 to 3)
result(1) = val1
result(2) = val2
result(3) = val3
getArray = result
End Function
Public Function getValues(myInt as Integer) as Variant
If (myInt = 1) Then
getValues = getArray(enmDemo.eA, enmDemo.eB, enmDemo.eC)
Else
getValues = getArray(enmTest.eA, enmTest.eB, enmTest.eC)
End If
End Function
Upvotes: 1
Views: 4137
Reputation: 4228
I know we're half a year later now, but in case someone else finds this...
You could also achieve what you're looking for with classes and interfaces (using the implements
keyword) instead of enumerations. It's a little more verbose than enumerations, but it's not as clunky as the conversion options, I think. If you have to use enums for some reason not included in the question, then this doesn't solve your problem. But, if you're just using the enum as a collection of named variable with numeric values, then this should do the trick:
In short, you define an interface (a class) with public read only members for eA, eB, and eC. This spells out what properties each interchangeable "enum" (class) must have.
interface:
' In a class module called IEnm
Public Property Get eA() As Long
End Property
Public Property Get eB() As Long
End Property
Public Property Get eC() As Long
End Property
Then you write another class for each specific "enum" that you're looking for - enmTest and enmDemo. These define the values of each property.
enmTest:
' In a class module called enmTest
Implements IEnm 'promises that this class defines each required property
Public Property Get IEnm_eA() As Long
IEnm_eA = 1
End Property
Public Property Get IEnm_eB() As Long
IEnm_eB = 2
End Property
Public Property Get IEnm_eC() As Long
IEnm_eC = 3
End Property
enmDemo:
' In a class module called enmDemo
Implements IEnm
Public Property Get IEnm_eA() As Long
IEnm_eA = 10
End Property
Public Property Get IEnm_eB() As Long
IEnm_eB = 50
End Property
Public Property Get IEnm_eC() As Long
IEnm_eC = 100
End Property
Here's a demo of how to use it.
Private actsLikeAnEnum As IEnm ' doesn't care if its enmTest, enmDemo,
' or enmSomethingElse
Public Function demoFunction() As IEnm ' you don't know what you'll get out
'Dim eDemo As enmDemo
'ReDim eDemo as enmTest
'ReDim demoFunction as enmDemo
Set actsLikeAnEnum = New enmTest
Set demoFunction = actsLikeAnEnum ' you could just return a new enmTest,
' but I wanted to show that the single IEnm typed variable (actsLikeAnEnum) can
' store both enmTest type objects and enmDemo type objects
End Function
Public Sub test()
Debug.Print demoFunction().eA 'prints 1
End Sub
Public Sub test2()
Dim temp As Variant
' since IEnm is an object, need to use the Set keyword
Set temp = demoFunction()
Debug.Print temp.eB 'prints 2
End Sub
'Or, if you want it to return 10 and 50....
Public Function demoFunctionTwo() As IEnm
Set actsLikeAnEnum = New enmDemo
Set demoFunctionTwo = actsLikeAnEnum
End Function
Public Sub test3()
Debug.Print demoFunctionTwo().eA 'prints 10
End Sub
Public Sub test4()
Dim temp As Variant
Set temp = demoFunctionTwo()
Debug.Print temp.eB 'prints 50
End Sub
You can set actsLikeAnEnum (which is an IEnm type object) to either a new enmDemo or an enmTest because they both implement IEnm. Then you can use actsLikeAnEnum without knowing whether there happens to be an enmDemo object or an enmTest object stored in the variable.
Upvotes: 0
Reputation: 53166
The best I can offer is a custom conversion Function for each Enum type. Although I would echo Dans comment: consider carefully why you want this.
' write one of these for each conversion you want
Function CastToDemo(ByRef v As enmTest) As enmDemo
Select Case v
Case enmTest.eA
CastToDemo = enmDemo.eA
Case enmTest.eB
CastToDemo = enmDemo.eB
Case enmTest.eC
CastToDemo = enmDemo.eC
End Select
End Function
' Use like this
Public Sub test()
Dim a As enmTest
Dim b As enmDemo
a = enmTest.eA
b = CastToDemo(a)
Debug.Print b
End Sub
Upvotes: 1