views:

27

answers:

3

What is the best way to manage common user-defined types across VBA modules?

I use the same user-defined types in different modules. For example, I often need to represent (x,y) points, so I end up having this Type in different modules:

Type XYpointType
    x As Double
    y As Double
End Type

I pass arguments of type XYpointType to and from subs and functions in different modules.

However, I suspect this is a poor way to manage user-defined types. The exact same Type definition code ends up in many different modules.

Alternatively, I could have this Type declaration in a single, central "types" module, and all other modules needing this particular type should refer to the types module. The downside is that each module loses its "modularity" in that it must be accompanied byt the "types" module wherever it goes.

Any suggestions?

+2  A: 

Use your second method. The point is to make a reusable Types blob. To be reusable, it must be separated. Then, yes, every module that uses those types must reference that blob. But the same thing may be said about modules calling into each other, forms requiring the modules they call, et c.

Eric Towers
+1  A: 

You can also create a class for your XYPoints. This will allow you to have custom functions, and methods should you need to go down that road. Types are very limited compared to classes.

Here is a good resource to get you started: http://www.cpearson.com/excel/Classes.aspx

Fink
Yeah, but in VBA you can only have one class per module (right?). I have a lot of user-defined types and I hate having a gazillion modules in my project, feels so untidy. That being said, I should at some point start using classes...
JF
@JF: Umm... I've put multiple classes in a VBA module. (Years ago. Times change. But I expect this to work.)
Eric Towers
@Eric, @JF is correct that it takes a whole module just to define one class. This gives me an excuse to repeat my favorite line: OOP in VBA is a PITA (TM)! But of course if you have types that could benefit from encapsulation it's still usually worth it...
jtolle
+1  A: 

This is interesting, because I never knew that you could have two modules both declaring a Public Type with the same name. Now that I do know, I'm horrified.

So first, Eric Towers is correct that you want to put your Type declaration in only one module. Other modules that use this Type will depend on that module being available, but that's just something that comes with modularization. The need to manage dependencies between modules is common to all software development. It's unfortunate that within a single VBA project (like the kind you'd find in a single Excel workbook) the only option for managing module dependencies is manual. (In VBA, "modules" are really "source code files". Other languages/environments have various higher-level packaging systems.)

Now for the horrifying part. If you do declare Types with the same name in different modules, you're setting yourself up for problems. Consider two VBA Modules:

'Module1

Public Type typ
    x As String
End Type

Public Sub useTyp()
    Dim t As typ
    t.x = 42

    Debug.Print t.x + t.x
End Sub

and

'Module2

Public Type typ
    x As Long
End Type

Public Sub useTyp()
    Dim t As typ
    t.x = 42

    Debug.Print t.x + t.x
End Sub

in the same project, your code will "compile" (at least in Excel VBA). But the two 'useTyp' subs give different output. Worse, if you remove one of the Type declarations from one of the modules, you've suddenly changed the behavior of the 'useTyp' routine in the same module! This kind of ambiguity is never desirable.

What's going on is that VBA is really creating two different types, 'Module1.typ', and 'Module2.typ'. When you're in the same module and don't qualify the type name, VBA silently finds the "right" type and uses it.

I'm a little surprised to hear that you're passing around instances of one 'XYpointType' to modules that have a different 'XYpointType' declaration. It's not that important, but could you post the code? I'm interested in nitpicky things like this...

jtolle
Thanks for the detailed answer. That pretty much confirms my gut feeling.
JF