是否可以在运行时更改VBA中变量或函数的类型?

时间:2014-06-28 02:34:21

标签: excel vba excel-vba enums

我很想知道是否可以在枚举类型之间有条件地切换函数或变量的类型。

这样的事情:

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

基本上,我们的目标是拥有一个类似Dim myVar的变量,可能是enumAenumB类型。这些枚举可能是相同的,除了它们的值。

我的猜测是,由于VBA处理枚举的方式,这在任何角度都不会起作用。但只是为了确保我想得到一个解释,因为我经过一个小时的实验后才有一种直觉。


我目前的解决方法,希望能够证明我的目标:

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

2 个答案:

答案 0 :(得分:1)

我能提供的最好的是每个枚举类型的自定义转换功能。虽然我会回应Dans评论:仔细考虑你为什么要这样做。

' 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

答案 1 :(得分:0)

我知道我们现在已经半年了,但万一其他人发现了这个......

您还可以使用classesinterfaces (using the implements keyword)而不是枚举来实现您所寻找的内容。它比枚举更冗长,但我认为它并不像转换选项那样笨重。如果 使用枚举因某些原因未包含在问题中,那么这并不能解决您的问题。但是,如果您只是将枚举用作具有数值的命名变量的集合,那么这应该可以解决问题:

简而言之,您为eA,eB和eC定义了具有公共只读成员的接口(类)。这说明了每个可互换的属性" enum" (班级)必须有。

<强>接口

' 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

然后你为每个特定的&#34; enum&#34;写了另一个班级。您正在寻找 - enmTest和enmDemo。这些定义了每个属性的值。

<强> 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

这是一个如何使用它的演示。

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

您可以将actsLikeAnEnum(这是一个IEnm类型的对象)设置为新的enmDemo或enmTest,因为它们都实现了IEnm。然后,您可以使用actsLikeAnEnum,而无需知道是否恰好存在enmDemo对象或存储在变量中的enmTest对象。