In this section, you will learn about some VBA programming features that you will certainly want to know about. Here, you will learn how to work with enumeration, classes, and external libraries.
We will kick off by looking at enumeration.
The first question that might pop into your mind is, "What the heck is enumeration?" As the name suggests, it enumerates something, but what? As a rule of thumb, enumeration is a group of constants. So, supposing you have an object, it is likely that this object has a color property. Therefore, you could have a "Color" group. Then you could enumerate the colors you want to use in your code. This will make life easier when determining which color to use, given that you simply declare the enumerator and choose one of its values when the times comes.
Take a look at the following screenshot:
Here, we have a FileDialog property (which is a member of the Application class) that takes FileDialogType as an argument, which is in turn enumerated by msoFileDialogType. Therefore, when you try to enter an argument for this property, you are only allowed to choose from those types which have been enumerated, that is, the options that belong to the group of file dialog types.
This is a great way to reduce your workload when you need to use certain types of constants, given that you can use enumeration across your entire VBA project. Furthermore, if you make a mistake in the value of such constants, you do not need to run through your code in order to change the variable wherever it had been used. Instead, you simply change the enumeration value.
Enumerations, such as procedures and functions, can be declared as Public or Private. The scope will depend on its intended use. If you plan to use it across your VBA project, ensure you place it in a standard module.
An enumeration is declared as follows:
Now, let us suppose we want to enumerate some colors to be used in our code, an example could be as follows:
Tip
If you need the value for other colors (or any other constant for that matter), simply record a macro painting the background of a cell, object, and so on. Then, inspect your code and copy the parameters from there.
The next step, of course, is to put it to good use. A screenshot of the code, when calling a subroutine that takes the custom enumeration as argument, is as follows:
The preceding code is shown as a screenshot so that you can have a clearer idea of what happens when you call the enumeration. As explained before, you can pass a parameter to a procedure and you can also declare its type. In this example we do just that. We declare a parameter called Color that is declared as the MyColors enumeration.
When we call the procedure, we are forced to enter such a parameter and we are only given the options declared in our enumeration.
You will now learn a bit about classes. When we program, we are continuously manipulating objects. You have seen this already in this book and it is now time to create your own objects.
Bear in mind that VBA is not a truly object-oriented programming language. However, it gives us a whole lot of possibilities in terms of programming, as we can compartmentalize many tasks by encapsulating the code into such classes. We can then call such encapsulated code when necessary.
VBA provides you with icons that visually identify the types you use. The following screenshot shows a Worksheet object type:
An object can be easily recognized by its icon. As mentioned at the beginning of this book, objects have properties and methods, which in turn are represented by their own set of icons.
When we explicitly dimension an object, all of its methods and properties are exposed. We get to them by adding a dot after the object's name. This is demonstrated in the following screenshot:
A class is simply an abstraction, but what is an abstraction? Abstraction is something that is outside of the concrete realm. In other words, an abstraction is something that has a high level of generalization.
If this sounds strange, picture a tree in your mind. What do you see? A tree is an object with a high level of generalization (abstraction) because we cannot determine what kind of tree it is until we specify its properties such as name, type, and order.
In fact, although most people would think of a tree as a woody plant, the oil industry has something called "Christmas tree", which is neither an artificial Christmas tree that we put up for Christmas nor a woody plant.
A graphical representation of this idea is shown in the following diagram:
So, this is what a class is – a highly generalized object.
Another aspect of classes is that you can group such objects into collections. Collections will always be defined as plurals of such objects. So, taking the tree object as an example, we can build collections of the same type, as shown in the following diagram:
To begin with, we will insert a new class module. In order to do so, open the Visual Basic Editor (VBE) by pressing Alt + F11 simultaneously. Then, go to Insert | Class Module.
Once you have inserted the class module, rename it to clsHouse, as shown in the following screenshot:
The prefix cls indicates that this is a class module. We will call it this way so that we can pretend that this is a generalization of a house, that is, this "house" could be a shack or a mansion for all we care.
We will now code this object and give it some properties and methods. Keep in mind the nomenclature, as for properties we use nouns and for methods we use verbs.
Here is a quick example with explanations:
In this class, we have one property called Address. This is a read-write property, as we can read from and write to it. The keyword that allows us to write to a property is Let. Conversely, to read a property we use the Get keyword.
The next step is to instantiate the object so that we can use it. In order to carry this out, we must add a standard module. Once this is done, we will add the following code (shown as a screenshot so that you get a better idea of what to expect):
Notice that the MyHouse object is dimensioned as a new instance of clsHouse. For now, it only has one property (Address) and its value will be 2 Skinner Street, London.
Once you set the address value, you can retrieve it and show it in a message box, as follows:
Now, let us suppose we want to retrieve the size of this particular house. Let us further suppose that this is a fixed size, that is, we cannot change (write) this value; we can only retrieve (read) it.
We can add the following property to our class. This property is read-only, as its value is hardcoded as "112 square meters":
We can readapt our standard module code so it would look as follows. Notice that this time the message to be shown also contains the size of the house:
Once it is executed, you will get the following message box, which contains both the house's address as well as its size in square meters:
Although the property Size, just specified is read-only, we can create a method that instructs this size to grow. Of course, this requires a redefinition of our code.
We will make the assumption that the fixed size for any house we build is always 112 square meters. We can later add extensions to the house (make the house "grow") and that the growth (extension) must be an integer representing 1 meter at a time. So, if we instruct the size to grow (extend the size of the house) by 2, it means the size will be 2 square meters larger than the default size.
The new code in the class module could look as follows:
We then need to change the code in the standard module. Here, we will have two different moments of the code. First, it will show the default value for the house. We will then instruct it to grow by 5 square meters and show its new size:
Another good use for classes is encapsulation. Basically, what it means is to envelope complex code in a class module and then to expose only the easy part, either through a method or a property. Think of encapsulating and putting that awful-tasting medicine in a capsule with a mint taste. The awful medicine (the code) stays inside the capsule (class module), but you only see and taste what is outside, yet it works wonders all the same.
The next example will return the name of the user currently logged in the machine. In order to do this, we will need to use a Windows API. There is a little application called API Viewer
(refer to the Resources section to find out where you can download this viewer from). API Viewer exposes Windows APIs, which you can copy and paste into your project.
For this particular example, we will use the GetUserName API. So, to begin we will add a new class module, but this time we will name it clsComputer, given that we will work with functions that work together with the operating system.
Here is the API you must add to the top-most part of your class module. There is not much to say about the API, so the explanation will be added to the code we will write on top of it:
Tip
This examples assumes a 32-bit version of the API being used.
The next job is to create a method (in this case, it will be a function) that will translate the API into a value returned by our custom function. (The method that will return the username. We will declare it as Private, so that it is not visible outside the class module):
With the method ready, the next step is to code the property. Basically, the UserName property gets its value from the preceding ShowUserName function:
Finally, in a standard module, we will insert the code that will access this property and return the currently logged-in user:
You have already been introduced to referencing a library. Initially, you were introduced to the Windows Script Host Model. We will now look at other possibilities when it comes to using external libraries.
Tip
Keep in mind that if you plan to have your VBA project used by others, then their machines must have such libraries registered too. Otherwise, your code will fail.
In the examples that will follow, you will learn how to integrate your Excel VBA project with Outlook. Let us start by adding the reference to the Outlook object model:
Open the Visual Basic Editor (VBE) window (press Alt + F11).
Go to Tools | References.
Once the dialog box is open, scroll down until you find the Microsoft Outlook 14.0 Object Library. Once you find it, select it and close the dialog box.
Tip
The version referenced here is for Office 14 (Office 2010). If you open such a project in an earlier version, say, Office 2007, then the code will fail given that we have explicitly said to use version 14. Whenever possible, use references to an earlier version.
Now, we are ready to go. Here are the exercises we will perform:
Create a dialog box so that we can pick one or more files to be attached to an e-mail object.
Code a procedure that will create an Outlook e-mail object and attach the files selected.
Open the e-mail in Outlook so that we can add a message to it before it is sent to its recipient.
Let us start with the definition of our File Picker dialog box, so you should start by adding a new standard module. Then, add the following code. The explanation is embedded in the code:
The preceding code does not handle the cancellation event. If the user cancels the event, an error will be thrown. As an exercise, you can cancel the dialog box and see what happens. By doing so, you expose yourself to issues that will inevitably appear as you start coding in VBA.
With the file dialog out of the way, we can now move on to the e-mail. Once again, the explanation is embedded in the code:
In this section, you learned some important aspects of VBA programming such as enumeration, classes, and external libraries. Enumeration helps you standardize data entry by collecting values that belong to a predetermined category. Classes, on the other hand, help you encapsulate code that would be difficult to handle otherwise and, by doing so, you are able to streamline your programming.
Finally, you revisited referencing external libraries and learned how to interact with Outlook. This method can be used for any other library registered in your system.
Although this book was not supposed to cover all aspects of VBA, it covered the most important aspects so that you can now start digging further in order to discover more under the surface you touched here.