A Little History
I started using a library when I’d finally worked up enough reusable code to make it worth doing and enough applications to care about using that code in multiple places. I have since gone through several iterations of them.
As I’ve mentioned in previous posts, I consider what I build more than “just a library”– though, of course, it is indeed a library. The reason I say that is that I consider much of my effort to be directed towards a framework. I first ran into a framework in the late 80s when I purchased the toolboxes from Borland to go with their Turbo Pascal. They had a graphics toolbox, a database toolbox, etc. I had not yet run across the term framework, at least in programming terms; but, in fact, that is what those were. I later ran into a framework in visual FoxPro around 1996, the name of which escapes me.
A framework is more than just a bunch of modules from which you call functions. That is classically thought of as a library. A framework is a set of interrelated objects that work together to form a whole, and which provide some sort of higher functionality once they work together. Think about the clsFrm which set up many instances of clsCtlTxt and clsCtlCbo so that with just a few lines of code in a form, you suddenly had apparently magical behaviors happening in the form.
From the perspective of OOP, a framework may be considered “bad”– i.e., each object works with and depends on other objects; whereas with OOP, we tend to think of each object as “needing as much as possible to stand alone”. In fact, I still strive for that; but each object is generally only useful in the context of the whole thing.
My first stab at building a framework was before I understood VBA classes — in fact, probably before I even really knew they existed. Remember that I had grown up in Turbo Pascal and Turbo C, so I had already experienced OOP and a framework. However, I got sucked in to Access in the early 90s, I think 1.x or maybe a brand-new 2.0 version. What I had never done prior was event-driven programming, and I spent the next few years learning Event Driven. Coming from “pick a menu item and the program goes until it is done”, I had a very difficult time wrapping my mind around the concept of a button “interrupting my program” whenever a user wanted to click a button. How could I ever possibly control stuff with users wreaking havoc with the program flow?
Anyway, somewhere along the way I got pretty good at the event driven thing, but I just didn’t even see the class thing. Before I discovered classes, I built an entire framework using collections of collections of objects. But the objects in the collections were usually data values or controls I was working on, not class instances. I wrote code that I still wonder how it ever worked. And it was really hard to understand or maintain. And it took a lot of collections, all kept in sync to emulate what I can easily do in a class.
In fact, it was my good friend Shamil Salakhetdinov who, in 1999 or so, pushed me gently towards classes and event handling in classes. However, it took several passes over about a year’s time, studying his code posted on his personal site, before the light bulb finally clicked and I realized that, mixed metaphors aside, there was something to this class thing. You see, Shamil was one of the pioneers in wrapping Access controls and forms in classes and sinking the events, then doing something with it. Unfortunately, the technology at the time wasn’t up to what he wanted to accomplish. VBA classes and event sinks and all that was really buggy, and Shamil finally gave up in disgust and moved on to DotNet.
However, I had the good fortune to finally “get it” just as Microsoft rolled out the fixes that enabled the technology to work. Access 2000 classes and events mostly worked, and Access 2002 completely worked. Today, as long as you don’t have to be backwards-compatible with Access 2000, you can use Classes and WithEvents and RaiseEvent without ever experiencing the problems to be found in those earlier versions.
Down to work
OK, enough history. Today I want to discuss how to place a class in a library and still get at it.
The problem is that classes by default are not visible outside of the Access container they are in. There are two solutions to this problem:
- Build a wrapper function to instantiate a class and return a pointer to the class instance, and do not define the return type for the function. I try very hard not to use this solution for the simple reason that the return type is not defined. Access returns it as type object, and therefore intellisense doesn’t work. We can’t get the public methods and properties displayed for us as we type. That is a critical shortcoming, in my book. I will demonstrate how to use this method, but I do not suggest it.
- The second method of making a class visible outside of the container is to export it to a text file, manually modify it in a text editor, delete the original, then import the modified file back in. While this is not a difficult procedure, it is tedious to have to do for 50 different classes in a library. I will demonstrate this method as well and discuss it in detail since, aside from the tedium, it is nonetheless the preferred method, in my opinion.
Try to compile. Notice that you immediately get a compile error on that line. The reason is that the class is not ‘visible’ outside of the library. Notice that if you have project Explorer open you can see the classes; however, they cannot be compiled into code outside of the library container.
Export and edit class method – has intellisense
- Click Export from the right click context menu.
- Navigate to the directory that contains MyFrameworkLib.
- Create a class subdirectory.
- Select ‘Text files’ in the ‘Save as’ combo box.
- The file name clsFrm should magically appear in the ‘File name’ combo.
- Click Export button to save the class out to a text file.
- Using Windows explorer, navigate to the new class directory you created above.
- Open the file in Notepad (NOT IN WORD!).
- Delete clsFrm from the modules tab.
- Click ‘Insert / Class Module’.
- Click ‘Insert / File’.
- Navigate back to the ‘Classes’ directory.
- Select clsFrm from the directory and click OK.
- Immediately save. Notice that Access will know the name of the class. Just accept that name.