简体   繁体   中英

VBA: function that takes multiple types of input?

I have some user-defined types and a function for each that takes those types and does something to them.

The thing is though, I'd like to write one, generic function that takes any of those types, and then just uses TypeName to figure out which one it is, and treats it like it needs to.

How do I do this? I tried taking the parameter as Function Foo(Param As Object) , but then it fails when I try to pass in a user-defined type into the function.

User Defined Types ( UDT ) are not classes (they are similar to Structures in C or Records in Pascal), therefore instances of an UDT are not objects - that's the reason you can not use them as an argument to your function foo .

VBA has a universal data type Variant . So when you have Function Foo(Param As Variant) , you can pass anything to the function, Foo 3 or Foo ActiveSheet or Foo "Hello world" . Anything, except a UDT... If you try so, you will get a compiler error stating "Only user defined types defined in public object modules can be coerced to or from a variant or passed to late-bound functions." :

Public Type tMyType
    i As Integer
    s As String
End Type

Sub Test
    Dim bar as tMyType
    ' Compiler complains
    foo bar

    Dim myUniversalVariant as Variant
    ' Compiler complains also
    myUniversalVariant = bar
End Sub

The official documentation of Variant states that "Variant types now support user-defined types." , however at least on Excel 2016 this is not working (or at least I was not able to do so).

Your best bet is to use Classes. If you're lazy, just create a class module (per Type) and put all members of the type as public members, nothing more needed (I will not start to describe the pros and cons of getter and setter ). You just need to remember that now you have to use the New statement to create and Set to assign an instance.

In class module (I named it clsMyType ):

 public i As Integer
 public s As String

In the regular module:

 Sub Test
    Dim bar as clsMyType
    Set bar = new clsMyType
    foo bar

    Dim myUniversalVariant as Variant
    Set myUniversalVariant = bar
    foo myUniversalVariant 
End Sub

Now depending if your function wants to receive only object or also other stuff (like integers or strings), parameter type can be Variant or Object

Function foo(Param as Object) 
    Debug.Print TypeName(Param)
End Function 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM