The words you are searching are inside this book. To get more targeted content, please make full-text search by clicking here.
Discover the best professional documents and content resources in AnyFlip Document Base.
Search
Published by anquoc.29, 2016-02-21 07:41:16

Writing Excel Macros with VBA, 2nd Edition

Creating Your Own Objects  ❘  265

Figure 21-2

There is a one-to-one relationship between a class and a class module. A
class module provides for only one class to be defined. If you need to define
three classes in your workbook, you’ll need three class modules, one for each
class. For example, suppose you have several CheckBox controls on your
UserForm, and you want to color the CheckBoxes green when they are checked,
and red when they are unchecked. Instead of coding this functionality for
every CheckBox’s Click event, you can use a class module that groups all the
CheckBoxes as a single collection object. That way, all CheckBoxes respond to
the same Click event, with one VBA class procedure. If you also want some (or
all) of the CommandButtons on a UserForm in that same workbook to respond
to, say, a MouseMove event, you’d create another class module for that.

Creating Your Own Objects

I started this lesson saying that many VBA programmers have avoided the topic of class modules,
and it wouldn’t surprise me if a primary culprit is VBA’s intentionally vague concept of class objects.
Seeing actual VBA examples of class modules in everyday situations is the best way to pick up the
concept of class objects.

www.it-ebooks.info

   266 ❘ lesson 21  Class Modules

Here’s the theoretical synopsis: A class is defined in a class module, and you
can think of a class as a blueprint or template for an object. In the context
of class modules, the term object can be almost any object in Excel whose
functionality you want to expand. This concept becomes clearer with VBA
examples you’ll see in this lesson dealing with controls that are embedded in
a worksheet, or are placed onto UserForms. You can have those controls all
respond to one single event, instead of needing to write numerous redundant
procedures for each control.

As you’ll see, a class module only serves the purpose of holding the code that defines (but does not
create) a class object. In some other module that is not a class module, such as a UserForm module
or workbook module (depending on the task you are solving), you can declare a variable of the class
type and create an instance of that class (known as instantiating the class) with the New keyword.
Upon instantiation, your declared variable becomes an object whose events, properties, and meth-
ods are defined by your code in the class module.

An Important Benefit of Class Modules

Suppose you have a UserForm with 12 TextBoxes, into which
a dollar figure for budgeted expenses is to be entered for each
month of the year, as in the example shown in Figure 21-3.

It’s important that only numbers are entered, so you want to
validate every TextBox entry to be numeric, while disallowing
entry of an alphabetic letter, symbol, or any character other
than a number. The following example can handle that for
TextBox1 in the UserForm module:

Private Sub TextBox1_KeyPress _

(ByVal KeyAscii As MSForms.ReturnInteger)

Select Case KeyAscii

Case 48 To 57 ‘numbers 0-9

Case Else

KeyAscii = 0

MsgBox “You entered a non-numeric character.”, _

vbCritical, _

“Numbers only please!”

End Select

End Sub Figure 21-3

You can maybe get away with the redundancy of writing 12

separate events to monitor the entries in each TextBox. But what happens if your project requires

100 TextBoxes, or if the numeric validation process expands to allow decimals or negative numbers?

You’d have to do a lot of updates for each TextBox, and the volume of redundant code will create a

bad design that’s destined for human error and runtime failure.

www.it-ebooks.info

   An Important Benefit of Class Modules ❘ 267

If you insert a class module instead, you can define an object that would be a group of 12 TextBoxes.
You can name your group object TxtGroup and declare it as a TextBox type variable. There is nothing
special about the variable name TxtGroup. I chose it because the idea is to group TextBoxes, but what-
ever object variable name makes sense to you will work just as well.

The following VBA declaration statement is a common example that gets placed at the top of your
class module. It defines the class object, and includes the WithEvents keyword, which exposes the
events associated with TextBoxes:

Public WithEvents TxtGroup As MSForms.TextBox

Now that you have defined the TxtGroup variable as a TextBox type object, you can invoke it to
handle the same KeyPress event that you might have written individually for all 12 TextBoxes. As
shown in the following code, you now use the TxtGroup object to have VBA recognize the KeyPress
event triggered by keyboard data entry upon any one of the 12 TextBoxes in your TxtGroup object.
The code to handle an event for all 12 TextBoxes is the same for TxtGroup as it is for TextBox1,
except for the name of the object.

Private Sub TxtGroup_KeyPress _
(ByVal KeyAscii As MSForms.ReturnInteger)
Select Case KeyAscii
Case 48 To 57 ‘numbers 0-9
Case Else
KeyAscii = 0
MsgBox “You entered a non-numeric character.”, _
vbCritical, _
“Numbers only please!”
End Select
End Sub

Keep in mind that, so far, all you have done is define the object, but it still exists only as a concept.
The next step is to create your defined object (formally known as instantiating it) to make it a work-
ing object that responds to events, and becomes associated with methods and properties. At this
moment, with the UserForm created and the class module selected with the preceding code in it,
your work in the class module is complete. Your VBE window will look similar to Figure 21-4.

The final step is to go into the UserForm module and instantiate the TxtGroup object that will be a
group of 12 TextBoxes. At the top of the UserForm module, declare a variable for 12 TextBoxes to
instantiate the TxtGroup class object, with the New keyword for the Class1 module name:

Dim txtBoxes(1 To 12) As New Class1

Using the Initialize event, declare an Integer type variable that will assist in looping through the
12 TextBoxes. Set each TextBox as a member of the TxtGroup class.

Private Sub UserForm_Initialize()
Dim intCounterTextBox As Integer
For intCounterTextBox = 1 To 12
Set txtBoxes(intCounterTextBox).TxtGroup = _
Controls(“TextBox” & intCounterTextBox)
Next intCounterTextBox
End Sub

www.it-ebooks.info

   268 ❘ lesson 21  Class Modules

Your entire coding process relating to the class module is complete, and it is quite a bit shorter than
all the code you’d have amassed if you coded the KeyPress event for every TextBox! If you were to
open the UserForm and attempt a non-numeric character in any of the 12 TextBoxes, that character
would be disallowed and the Message Box would appear, looking like Figure 21-5.

Figure 21-4 Figure 21-5

Creating Collections

In the preceding example, you created a class for 12 TextBoxes. You knew ahead of time the number
of TextBoxes was 12 because there was a TextBox for each of the 12 calendar months. The question
becomes, what do you do if the count of inclusive TextBoxes is not known? What if your project is
so wide in scope that TextBoxes are being frequently added and subtracted from the UserForm, and
you don’t want to keep modifying the code with every change in TextBox count?

The answer is, you create a collection of TextBoxes by looping through all the controls in the
UserForm. Then, when a TextBox is encountered in the loop, it is automatically added to the collec-
tion, which is then transferred to the class object. Assuming the event code you placed in the class
module has not changed, all that needs to be adjusted is the code in the UserForm module using the
previous example. The first item of business is to prepare a declaration statement at the top of the
module that does not specify a count of TextBox names, such as the following example:

Dim TxtGroup() As New Class1

Next, the following code in the UserForm’s Initialize event will wrap up all the TextBoxes into
one array package using the ReDim Preserve keywords. This method does not depend on how many
TextBoxes are embedded on Sheet1; it simply collects all the ones into the TxtGroup object that it finds.

Private Sub UserForm_Initialize()
Dim intCounterTextBox As Integer, ctl As Control
intCounterTextBox = 0
For Each ctl In Controls
If TypeName(ctl) = “TextBox” Then
intCounterTextBox = intCounterTextBox + 1

www.it-ebooks.info

Class Modules for Embedded Objects  ❘  269

ReDim Preserve TxtGroup(1 To intCounterTextBox)
Set TxtGroup(intCounterTextBox).TxtGroup = ctl
End If
Next ctl
End Sub

Class Modules for Embedded Objects

So far, UserForms have been the backdrop for objects in a class module. You can also create a class
of objects embedded on worksheets, such as charts, pivot tables, and ActiveX controls. In the case of
ActiveX controls, it’s worth mentioning a syntax difference when referring to them.
Suppose you have an unknown number of CommandButtons on Sheet1 and you want to create a class
module to determine which button was clicked, without having to program every CommandButton’s
Click event. This example of code in a class module named Class1 demonstrates how to extract the
name, caption, and address of the cell being touched by the top-left corner of the CommandButton
object. Figure 21-6 shows the Message Box that appears when you click one of the CommandButtons.

Figure 21-6

Public WithEvents cmdButtonGroup As CommandButton
Private Sub cmdButtonGroup_Click()
MsgBox _
“Hello, my name is ‘’” & _
cmdButtonGroup.Name & “‘’.” & vbCrLf & _
“My caption is ‘’” & _
cmdButtonGroup.Caption & “‘’.” & vbCrLf & _
“My top left corner is set in cell “ & _
cmdButtonGroup.TopLeftCell.Address(0, 0) & “.”, _
64, “You just clicked me, here’s my info :”
End Sub

www.it-ebooks.info

   270 ❘ lesson 21  Class Modules

You can also tap into other events in the same class module. All that’s required is that you use the
same class object (cmdButtonGroup in this example), and that the event is supported by the object.
With CommandButtons, the MouseOver event can help you identify which button you are hovering
your mouse over by shading it orange, while all other CommandButtons on the sheet are colored gray.

I used hex codes in this example for the buttons’ BackColor property, to show
how you’d use hex in code to refer to colors. These hex values are always shown
in the Properties window of ActiveX controls for BackColor and ForeColor
properties, and I personally find them very reliable in VBA code
with any version of Excel.

Private Sub cmdButtonGroup_MouseMove _
(ByVal Button As Integer, _
ByVal Shift As Integer, _
ByVal X As Single, _
ByVal Y As Single)
Dim myBtn As Object
For Each myBtn In ActiveSheet.OLEObjects
If TypeName(myBtn.Object) = “CommandButton” Then _
myBtn.Object.BackColor = &HC0C0C0 ‘turn all to gray
Next
cmdButtonGroup.BackColor = &H80FF& ‘orange
End Sub

As you can probably tell, despite the appearance of differently shaped
CommandButtons with comical captions, the larger point of this example
is that you can capture various properties of class objects, assign them to a
variable, and utilize that variable information in other macros, or even as
part of the class module’s event code. For example, in real practice, you
don’t need or want a Message Box to pop up and tell you which button
you just clicked; you already know that. If, for example, your project is
such that the CommandButtons’ captions have a word or phrase to be used
as a criterion for automatically filtering a table of data, this application of
flexible class module coding will save you a lot of work.

For embedded ActiveX controls, you can instantiate the collection of OLE objects, in this example
for CommandButtons, with the following code that goes into the ThisWorkbook module. Be sure to
place this example declaration statement at the top of the ThisWorkbook module:

Dim cmdButtonHandler() As New Class1

www.it-ebooks.info

Class Modules for Embedded Objects  ❘  271

Finally, utilize the Open event to collect the CommandButtons that are only on Sheet1. Notice the ref-
erences to the OLEObject and OLEObjects keywords when dealing with embedded ActiveX controls.

Private Sub Workbook_Open()
Dim cmdButtonQuantity As Integer, MYcmdButton As OLEObject
cmdButtonQuantity = 0
With ThisWorkbook
For Each MYcmdButton In .Worksheets(“Sheet1”).OLEObjects
If TypeName(MYcmdButton.Object) = “CommandButton” Then
cmdButtonQuantity = cmdButtonQuantity + 1
ReDim Preserve cmdButtonHandler(1 To cmdButtonQuantity)
Set cmdButtonHandler(cmdButtonQuantity).cmdButtonGroup _
= MYcmdButton.Object
End If
Next MYcmdButton
End With
End Sub

Not all controls recognize the same event types though, Figure 21-7
so you’d need to set a class event that the object type can
recognize.

There is another technique using the Collection keyword
for grouping the same types of objects into a class. In this
example, Sheet1 has a number of embedded CheckBox
controls, and you want to write one small piece of VBA
code that will apply to all CheckBoxes.

The visual effect you want is for any CheckBox on
Sheet1 to be shaded black if it is checked, and white if it
is unchecked. Figure 21-7 shows the differences in color
shading depending on the status of the CheckBoxes.

The code to do this is surprisingly minimal. Insert a new
class module, and assuming it is named Class2 because
you already have a Class1 module established, this code
will go into the Class2 module:

Public WithEvents grpCBX As MSForms.CheckBox

Private Sub grpCBX_Click()
With grpCBX
If .Value = True Then

.BackColor = &H0& ‘Black background

.ForeColor = &HFFFFFF ‘While font

Else

.BackColor = &HFFFFFF ‘White background
.ForeColor = &H0& ‘Black font
End If
End With
End Sub

www.it-ebooks.info

   272 ❘ lesson 21  Class Modules

The rest of the code goes into the ThisWorkbook module. It instantiates the grpCBX object and is
refreshed each time the workbook opens by utilizing the Workbook_Open event.

Public myControls As Collection

Private Sub Workbook_Open()
Dim oleCtl As OLEObject, ctl As Class2
Set myControls = New Collection
For Each oleCtl In Worksheets(“Sheet1”).OLEObjects
If TypeOf oleCtl.Object Is MSForms.CheckBox Then
Set ctl = New Class1
Set ctl.grpCBX = oleCtl.Object
myControls.Add ctl
End If
Next
End Sub

Try It

In this lesson you create a class module to handle the Click event of some of the OptionButtons on
a UserForm, purposely not involving all OptionButtons in the class.

Lesson Requirements

For this lesson, you design a simple UserForm with eight OptionButtons, of which only five will be
a part of a class module that identifies which OptionButton by name and caption was clicked. To
get the sample database files, you can download Lesson 21 from the book’s website at http://www
.wrox.com/.

Step-by-Step

1. Open a new workbook.
2. Press Alt+F11 to get into the Visual Basic Editor.
3. From the menu bar, click Insert ➪ UserForm, and size the UserForm to a Height of 200 and a

Width of 400.

4. Draw a Label control near the top-left corner of your UserForm, and caption it as

OptionButtons In Class Module.

5. Draw a Label control near the top-right corner of your UserForm and caption it as Other

OptionButtons. Figure 21-8 shows how your UserForm should look so far.

www.it-ebooks.info

Try It  ❘  273

Figure 21-8

6. Under the first Label control, draw a vertical column of five OptionButtons. A fast way to do
this is to draw one OptionButton, and then copy and paste it four times. Change the captions
of those five OptionButtons to Apples, Bananas, Peaches, Grapes, and Oranges, as shown in
Figure 21-9.

Figure 21-9

7. Paste three more OptionButtons below the second Label control. Change the captions of those
three OptionButtons to Plums, Pears, and Tangerines. You now have eight OptionButtons
on your UserForm, all with different captions that are the names of fruits. The actual VBA
names of the eight OptionButtons have not changed  — ​they all are still named by default as
OptionButton1, OptionButton2, and so on, to OptionButton8. For example, if you were to
select the OptionButton that is captioned Oranges, you would see in its Properties window that
it is named OptionButton5. Figure 21-10 shows how your UserForm looks at this point.

Figure 21-10

www.it-ebooks.info

   274 ❘ lesson 21  Class Modules

8. Draw a CommandButton in the lower-right corner of the UserForm. Name it cmdExit and
9. caption it as Exit.

Double-click the cmdExit button, which will take you into the UserForm’s module, with the
cmdExit button’s Click event ready for your code. Type Unload Me, and your UserForm
module in the VBE will look like Figure 21-11.

Figure 21-11

10. Insert a class module. From the menu bar, click Insert ➪ Class Module and accept the default
11. name of Class1. Your cursor will be blinking in the Class1 module’s Code window.

The purpose of this particular class module is to capture an event that is associated with
OptionButton controls. At the top of the Class1 module, publicly declare a variable that
refers to the group of OptionButtons you will involve in the class module code. In that same
statement, expose the events associated with OptionButtons using the WithEvents keyword.
The following statement accomplishes this task:

Public WithEvents OptGroup As msforms.OptionButton

There is nothing special about the OptGroup variable name; you can give your
class module variable whatever name makes sense to you. What makes sense to
me is that I am grouping some OptionButton controls for a demonstration, so
OptGroup is an intuitive name.

12. To demonstrate the point of this lesson, you can use the Click event for your OptGroup
class. A Message Box will display the name and caption of the OptionButton that was clicked
if that OptionButton is included in the class. Figure 21-12 shows how the VBE will look after
inputting the following class module code.

www.it-ebooks.info

Try It  ❘  275

Figure 21-12

Private Sub OptGroup_Click()
MsgBox _
“Hello, my name is “ & OptGroup.Name & “.” & vbCrLf & _
“My caption is “ & OptGroup.Caption & “.”, _
vbInformation, _
“You just clicked me, here’s my info :”
End Sub

If this were an actual workbook project, you would not need a Message Box
to tell you which OptionButton was just clicked. More realistically, you might
assign a String type variable to the selected OptGroup.Caption if that caption
string is needed as part of an operation elsewhere in your project.

13. Return to the UserForm module. At the top of the module, identify which OptionButtons you
want to be grouped into the OptGroup class. For this example, the first five OptionButtons
will be grouped, so create an instance of the OptGroup class with the New keyword for the
Class1 module name:

Dim optButtons(1 To 5) As New Class1

14. The UserForm’s Initialize event is a good opportunity to do the actual grouping of the
five OptionButtons. From the Object drop-down list select UserForm, and in the Procedure
drop-down list select Initialize. VBA will enter the UserForm_Initialize and End Sub
statements with an empty space between the two lines, as follows:

Private Sub UserForm_Initialize()

End Sub

www.it-ebooks.info

   276 ❘ lesson 21  Class Modules

15. Declare an Integer type variable that will help loop through the five OptionButtons that will
become a part of the class module:

Dim intCounterOptionButton As Integer

16. Open a For Next loop to loop through the five OptionButtons:

For intCounterOptionButton = 1 To 5

17. Set each of the five OptionButtons as members of the OptGroup class:

Set optButtons(intCounterOptionButton).OptGroup = _
Controls(“OptionButton” & intCounterOptionButton)

18. Continue and close the For Next loop with the Next statement:

Next intCounterOptionButton

19. All of your coding is complete. The entire UserForm module contains the following
VBA code:

Option Explicit

Dim optButtons(1 To 5) As New Class1

Private Sub UserForm_Initialize()
Dim intCounterOptionButton As Integer
For intCounterOptionButton = 1 To 5
Set optButtons(intCounterOptionButton).OptGroup = _
Controls(“OptionButton” & intCounterOptionButton)
Next intCounterOptionButton
End Sub

Private Sub cmdExit_Click()
Unload Me
End Sub

20. Test your class module by showing the UserForm. Press Ctrl+G to open the Immediate win-
21. dow, type the statement UserForm1.Show, and then press the Enter key.

Click any of the five OptionButtons on the left to display the Message Box that identifies the
name and caption of the OptionButton you click. In Figure 21-13 I clicked OptionButton4,
having the caption Grapes. The OptionButtons on the right side of the UserForm are not
included in the class, and if clicked will not invoke a Message Box.

www.it-ebooks.info

Try It  ❘  277

Figure 21-13

To view the video that accompanies this lesson, please select Lesson 21, available
at the following website: www.wrox.com/go/excelvba.

www.it-ebooks.info

www.it-ebooks.info

22

Add-Ins

Add-ins are a useful feature in Excel, considered by many Excel developers to be an indispens-
able tool when distributing their custom projects to a wider audience. Anyone can create an
add-in — i​t’s the kind of thing that’s easy to do once you know how. This lesson discusses the
concept of add-ins and how to incorporate them into your Excel projects.

This lesson discusses standard Excel add-ins. Two other types of add-ins exist that
are not developed with VBA and are not discussed in this lesson. One of the other
types is called COM add-ins, developed with languages such as Visual Basic, C++,
and J++ that support Component Object Model components. The other type is
DLL add-ins, which are Windows files known as Dynamic Link Library files.

What Is an Excel Add-in?

An Excel add-in is a special type of Excel workbook that has been converted to an add-in file.
There is no magic to the add-in conversion process, but after you create an add-in file, you’ll
notice its unique characteristics:

➤➤ The file extension is.xla for Excel versions prior to 2007, and .xlam for Excel versions
2007 and 2010.

➤➤ Add-ins are always hidden; you do not open and view them as you would an Excel
workbook.

➤➤ You cannot show sheets of any kind belonging to the add-in file.
➤➤ The add-in file is not recognized as an open workbook in the Workbooks collection.

www.it-ebooks.info

   280 ❘ lesson 22  Add-Ins

Why Create an Excel Add-in?
Add-ins commonly use VBA macros, event procedures, User Defined Functions,
and UserForms to make everyday tasks faster and easier to accomplish. Many Excel
users don’t find the need to create an add-in, but here are some reasons why you
might want to:
➤➤ Add-in files are hidden and therefore provide seamless integration to open

Excel workbooks. Novice Excel users won’t need to worry about opening
an add-in once it’s been loaded, and they won’t wonder about an extra open
Excel file because add-ins cannot be seen or unhidden.
➤➤ Even if the macro security is set to its most restrictive level, the VBA program-
ming for an installed add-in can still run.
➤➤ Add-ins open automatically when Excel starts.
➤➤ The custom feature(s) contained within the add-in file are usually available to
any of the open workbooks.
➤➤ The programming code is contained in the add-in file itself, and does not travel
with the workbooks that use it. This gives you more control over how the file
is distributed and who can access its code.
➤➤ Where add-ins really shine is in their ability to perform actions on several
objects, such as cells or sheets, that if done manually would be cumbersome,
time-consuming, and require some knowledge of Excel for the user to com-
plete. Novice Excel users will especially appreciate the ease of clicking a but-
ton to do tasks that they might not know how to do manually, or might not
know the most efficient methods by which to handle those tasks quickly.

Creating an Add-In

You create an Excel add-in file manually, but you make its features available by using VBA. To cre-
ate an add-in, the first thing you do is open a new workbook. Because you’ll be adding VBA code
that will become the add-in’s functionality, you’ll want to test and retest your code before releasing
the add-in for others to use. I mention this obvious point because if your add-in deals with manipu-
lating worksheets in the active file, you’ll need to observe the code’s effect on those worksheets to
make sure everything is working properly. Once you convert the workbook to an add-in, you’ll no
longer be able to view the worksheets, so you’ll want to construct and test all your code before con-
verting your workbook as an add-in.

www.it-ebooks.info

Creating an Add-In  ❘  281

Plan Ahead for Best Results

Any workbook can be converted to an add-in file, but not every workbook after
it is created is a good candidate as an add-in. When I create an add-in, I know in
advance what features I want the add-in to have, and what kind of code to avoid.
This is important, because the add-in file is a hidden workbook that cannot contain
code for activating a sheet or a range of cells.

You are allowed to write data to your add-in file, but you cannot activate the add-
in file at any time. If you want to keep any data you’ve written to the add-in file,
you’ll need to save the file in the Workbook_BeforeClose event, because when an
add-in closes, it does not prompt the user to save unsaved changes.

Suppose you want to create an add-in that offers the options to hide, unhide, protect, or unprotect mul-
tiple worksheets. A novice Excel user might perform these tasks one sheet at a time — q​ uite an under-
taking if the workbook contains dozens or hundreds of worksheets, and the tasks are a frequent chore.

In your new workbook that is destined to become an add-in, press the Alt+F11 keys to go to the
Visual Basic Editor. From the VBE menu bar, click Insert ➪ UserForm. If the Properties window is
not visible, press the F4 key. Follow these steps to create the add-in:

1. Select your new UserForm in its design area. In the Properties window, name the UserForm
2. frmSheetManager, enter its caption as Sheet Manager, and set its Height property to 210 and
its Width property to 276.

Place the following controls on your UserForm:

➤➤ A Label control near the top, setting its Width property to 228, and its Caption prop-
erty to Please select your action.

➤➤ An OptionButton control below the Label control, keeping the default name
OptionButton1, setting its BackColor property to white, its Width property to 228,
and its Caption property to Unhide all sheets.

➤➤ A second OptionButton control below OptionButton1, keeping the default name
OptionButton2, setting its BackColor property to white, its Width property to 228,
and its Caption property to Hide all sheets except active sheet.

➤➤ A third OptionButton control below OptionButton2, keeping the default name
OptionButton3, setting its BackColor property to white, its Width property to 228,
and its Caption property to Protect all sheets.

➤➤ A fourth OptionButton control below OptionButton3, keeping the default name
OptionButton3, setting its BackColor property to white, its Width property to 228,
and its Caption property to Unprotect all sheets.

www.it-ebooks.info

   282 ❘ lesson 22  Add-Ins

➤➤ A CommandButton near the bottom-left corner
of the UserForm, setting its Name property to
cmdOK, and its Caption property to OK.

➤➤ A CommandButton near the bottom-right cor-
ner of the UserForm, setting its Name property
to cmdExit, and its Caption property to Exit.

Your UserForm will end up looking like Figure 22-1. Figure 22-1

The design work is complete for your UserForm. In the
UserForm module, enter the following code, which is mostly
triggered by the cmdOK button’s Click event. The requested
task will be performed depending on whichever OptionButton
was selected.

Private Sub cmdOK_Click()

‘Declare an Integer type variable to help loop
‘through the worksheets.
Dim intSheet As Integer

‘Open a Select Case structure to evaluate each OptionButton.
Select Case True

‘If OptionButton1 was selected:
‘Unhide all sheets.
Case OptionButton1.Value = True
For intSheet = 1 To Sheets.Count
Sheets(intSheet).Visible = xlSheetVisible
Next intSheet

‘If OptionButton2 was selected:
‘Hide all sheets except active sheet.
Case OptionButton2.Value = True
For intSheet = 1 To Sheets.Count
If Sheets(intSheet).Name <> ActiveSheet.Name Then
Sheets(intSheet).Visible = xlSheetHidden
End If
Next intSheet

‘If OptionButton3 was selected:
‘Protect all sheets.
Case OptionButton3.Value = True
For intSheet = 1 To Sheets.Count
Sheets(intSheet).Protect
Next intSheet

‘If OptionButton4 was selected:
‘Unprotect all sheets.
Case OptionButton4.Value = True
For intSheet = 1 To Sheets.Count
Sheets(intSheet).Unprotect
Next intSheet

www.it-ebooks.info

Creating an Add-In  ❘  283

‘If no OptionButton was selected:
Case Else
MsgBox “No Action option was selected”, , _
“Please select an option”

‘Close the Select Case structure.
End Select

End Sub

Private Sub cmdExit_Click()
Unload Me
End Sub

Create a small macro to call the UserForm. From the VBE menu bar, click Insert ➪ Module and
enter the following macro:

Private Sub SheetManager()
frmSheetmanager.Show
End Sub

After completing the VBA functionality that your add-in will provide to its users, it’s almost time to
convert the workbook to an add-in. There is an additional step you can take to add a description to
the file’s Properties information. It’s purely optional that you do this, but it’s a good habit to get into
because it will help the add-in’s users know what the add-in does.

The process for accessing the file’s Properties information depends on your version of Excel. To
access the Properties dialog box in Excel versions prior to 2007, click File ➪ Properties from the
worksheet menu bar as shown in Figure 22-2. In the Properties dialog box, some fields may already
be entered for you by default. As you will see later in this lesson, the most useful information to
enter is the Title and Comments fields, as indicated in Figure 22-3.

Figure 22-2 Figure 22-3

www.it-ebooks.info

   284 ❘ lesson 22  Add-Ins

To reach the Properties information in Excel version 2007,
click the round Office button near the top-left corner
of your window. You will see a vertical pane on the
left side of the window. Click Prepare, and then in the
pane on the right, click Properties, as shown in
Figure 22-4.

To reach the Properties information in Excel version
2010, click the File tab on the Ribbon, and in the ver-
tical pane at the left, click Info. At the far right, you
will see a Properties label with a drop-down arrow.
As indicated in Figure 22-5, selecting the Advanced
Properties item in the drop-down list displays the
Properties dialog box.

Figure 22-4

Figure 22-5

Converting a File to an Add-In

The easiest way to convert a file to an add-in is to save the file as an Excel Add-in type. In ver-
sions of Excel prior to 2007, from the worksheet menu click File ➪ Save As. In the Save As dialog
box, navigate to the folder where you want the add-in to reside. In Figure 22-6, I named the file
SheetManager, and I created a subfolder named My Addins. From the Save As Type field’s drop-
down list, select Microsoft Office Excel Add-In, as shown in Figure 22-6, and click the Save button.
For version 2007, click the Office button and select Save As. For version 2010, click the File tab and
select Save As. In the Save As dialog box, navigate to the folder where you want the add-in to reside,
and give the file a name. As shown in Figure 22-7, select Excel Add-In from the Save As Type drop-
down list and click the Save button.

www.it-ebooks.info

Converting a File to an Add-In  ❘  285

Figure 22-6

Figure 22-7

www.it-ebooks.info

   286 ❘ lesson 22  Add-Ins

While saving a file as an add-in, you must have a worksheet be the active sheet.
If by chance you have a chart sheet in your file and it is the active sheet, the Save
As Type drop-down list won’t include an Add-in file type.

Installing an Add-In

If your add-in is being distributed to other users,
the first thing you do is to deliver the add-in file to
them in some way, such as by e‑mail, or on a Flash
drive if by hand delivery. In any case, your users
would save the add-in file to whatever folder they
prefer, similar to how you saved your add-in file
into a folder on your computer.

The easiest way to install an add-in is to use the Figure 22-8
Add-Ins dialog box, which you can do from any
open workbook. In versions of Excel prior to 2007,
from the worksheet menu click Tools ➪ Add-Ins
as shown in Figure 22-8. In versions 2007 and
2010, click the Developer tab on the Ribbon, and
select the Add-Ins icon as shown in Figure 22-9.
An example of the Add-Ins dialog box is shown
in Figure 22-10.

The Add-Ins dialog box shows a list of all the add-ins that Excel is
aware of. An add-in is open if a checkmark is next to its name in the
list. You’ll notice in Figure 22-10 that no add-ins are selected, and
that the SheetManager add-in is not listed in the Add-Ins dialog box.
When a new add-in is created, it does not automatically appear in the
Add-Ins dialog box. To install a new add-in, you first need to list it
in the Add-Ins dialog box, and then select it in the list.

Figure 22-9 Figure 22-10

The Developer tab is a very useful item to place on your Ribbon. See the section
named “Accessing the VBA Environment” in Lesson 2 for the steps to display
the Developer tab.

www.it-ebooks.info

Installing an Add-In  ❘  287

A quick way to open the Add-Ins dialog box from any version of Excel is to press
the Alt+TI keys  — ​that is, hold down the Alt key and with your other hand press
the T key and the I key. If you prefer to work with a mouse instead of the keyboard,
and you prefer not to show the Developer tab, you can access the Add-Ins dialog
box another way. In Excel version 2007, click the Office button, then click the
Excel Options button. In Excel version 2010, click the File tab, click the Options
menu item, and select the Add-Ins menu item. At the bottom of the window, select
Excel Add-Ins from the Manage drop-down list, and click the Go button.

To include an add-in on the Add-Ins list, click the Browse button on the Add-Ins dialog box.
Navigate to the folder where you saved the add-in file, select the filename, and click OK to exit the
Browse dialog box as indicated in Figure 22-11.

You now will see your selected file listed in the Add-Ins dialog box. By default, Excel places a check-
mark next to the selected add-in’s name. If you don’t want the add-in to be open — t​hat is, for its
features to be available to you — s​ imply deselect the add-in by unchecking the box next to its name.

If and when you do select your new add-in, you and the users of that add-in will appreciate the extra
time you spent in the Properties window before you converted the original file to an add-in. Notice
that the selected add-in’s filename and comments appear at the bottom of the Add-Ins dialog box,
informing the user what the add-in does. In any case, now that you’ve listed the add-in file, click the
OK button to exit the Add-Ins dialog box as indicated in Figure 22-12.

Figure 22-11 Figure 22-12

www.it-ebooks.info

   288 ❘ lesson 22  Add-Ins

Where Did Those Other Add-Ins Come From?

Even before you created your first add-in, you saw there were already some add-ins
listed in the Add-Ins dialog box. Excel ships with four available add-ins; they are
not open until you select them in the Add-Ins dialog box. The four add-ins are:

➤➤ The Analysis ToolPak add-in, which provides an expanded set of analysis tools
not available in standard worksheet functions and features

➤➤ The Analysis ToolPak VBA add-in, which provides an expanded set of func-
tions for your VBA programming code

➤➤ The Euro Currency Tools add-in is a tool for converting and formatting the
euro currency

➤➤ The Solver add-in is a what-if analysis tool that attempts to find an optimal
value for a formula in one cell while considering constraints placed on the
values in other cells

Creating a User Interface for Your Add-In

Now that the add-in has been created and installed, you need to provide your users with the abil-
ity to access the functionality. As it stands right now, all that’s happened is the add-in is available
behind the scenes. However, because the SheetManager add-in’s functionality is tied to a UserForm,
you’ll need to establish a way for users to click a link of some kind that calls the UserForm.

Before the Ribbon came along, a custom worksheet menu item was created using the CommandBar
object. For this example, I named the menu item SheetManager, and it appears on the Tools menu.
The good news is, Excel versions 2007 and 2010
still support CommandBars, and you can use the
same code to achieve a user-friendly custom menu
interface that is compatible with every version of
Excel starting with Excel 97.

For versions of Excel prior to 2007, a menu Figure 22-13
item named Sheet Manager will appear in the
Tools menu, as shown in Figure 22-13. For ver-
sions 2007 and 2010, the menu item named
Sheet Manager will be displayed in the Menu
Commands section of a new tab on the Ribbon
named Add-Ins. The Add-Ins tab appears when
you apply custom add-in code. In any case,
clicking the Sheet Manager menu item executes
the macro that calls the UserForm, as shown in
Figure 22-14.

www.it-ebooks.info

   Creating a User Interface for Your Add-In ❘ 289

Figure 22-14

The following event code, found in the ThisWorkbook module of the add-in file, establishes the cus-
tom user interface:

Private Sub Workbook_Open()
‘Declare a CBC variable for the custom menu item.
Dim objCmdControl As CommandBarControl
‘The custom menu item will be named “Sheet Manager”
‘and it will go onto the Tools menu for versions before 2007.
Set objCmdControl = _
Application.CommandBars(“Worksheet Menu Bar”) _
.Controls(“Tools”).Controls.Add
‘For the new menu item, give it a meaningful caption,
‘help it to clearly stand out by starting a BeginGroup.
‘The OnAction method will call the UserForm.
‘The Face ID is a small icon next to the menu item
‘that is optional, but adds a feeling of customization.
With objCmdControl
.Caption = “Sheet Manager”
.BeginGroup = True
.OnAction = “SheetManager”
.FaceId = 144
End With
End Sub

www.it-ebooks.info

   290 ❘ lesson 22  Add-Ins

Private Sub Workbook_BeforeClose(Cancel As Boolean)
‘Delete the custom menu item from the Tools menu.
‘The error bypass is for cases when the “Sheet Manager”
‘item is not listed on the Tools menu.
On Error Resume Next
Application.CommandBars(“Worksheet Menu Bar”) _
.Controls(“Tools”).Controls(“Sheet Manager”).Delete
Err.Clear
End Sub

Changing the Add-In’s Code

You’ll find that some of your add-ins are a work in progress. Users will enjoy the ease of performing
add-in tasks, and you’ll be requested to make enhancements to the add-in for more functionality. As
you pick up more VBA programming skills, you’ll want to improve your original code by making
edits for speed and efficiency.
Any changes you make to your add-in file will be done in the Visual Basic Editor. Open your add-in
file and all you will see is an empty-looking Excel file because all the sheets in an add-in are hidden
and cannot be viewed. Press Alt+F11 to go to the VBE, and just as if it were any Excel workbook,
make whatever changes to the code you need to make. When you are done, save your changes in the
VBE and close the add-in file.

For add-ins that you distribute to other users, you’ll want to protect the code
from being inadvertently changed or viewed by others. The process for protect-
ing your add-in code is the same as with any Excel workbook, and that is to lock
and protect the project in the Visual Basic Editor. The steps to do this are dis-
cussed in Lesson 4, in the section “Locking and Protecting the VBE.”

Closing Add-Ins

As you saw in the section “Changing the Add-in’s Code,” you can open an add-in file, but you might
like to know how to close an add-in file, because it cannot be closed the same way you close a work-
book. You have three ways to close an add-in file:

➤➤ Deselect (uncheck) the add-in’s name in the Add-Ins dialog box.
➤➤ Go into the VBE and press Ctrl+G to ensure that the Immediate window is open. In the

Immediate window, enter a line of code that closes the add-in file and press Enter. An exam-
ple of such code for the SheetManager add-in is as follows:

Workbooks(“SheetManager.xlam”).Close

➤➤ Close Excel, which closes all files, including add-ins.

www.it-ebooks.info

Try It  ❘  291

Removing an Add-In from the Add-Ins List

At some point in the future, you might want to remove the add-in from the list of available add-ins
in the Add-Ins dialog box, if the add-in is outdated or you just don’t need it anymore. To accomplish
this is an example of how science meets art, because Excel does not have a built-in way to remove an
add-in’s name from the list. Here are the steps to make this happen:

1. Close Excel.

2. Open Windows Explorer and navigate to the folder

that holds your add-in file.

3. Select the add-in filename, and without opening the
file, either change its name, or drag the file to a
different folder, or, if you really no longer need the
add-in, delete the file altogether.

4. Open Excel, and when you do, you’ll receive a mes- Figure 22-15
sage telling you that the add-in file cannot be found.
Click the OK button as indicated in Figure 22-15.

5. Open the Add-Ins dialog box and uncheck the name of the
add-in you want to remove. Excel reminds you that the file
cannot be found, and asks for confirmation that you want to Figure 22-16
delete the file from the list of available add-ins. Click the Yes
button as indicated in Figure 22-16.

Try It

In this lesson, you create and install an add-in that contains a User Defined Function to return the
text of another cell’s comment.

Lesson Requirements

For this lesson, you create an add-in to return the text of comments in other cells, and you test the
add-in by installing it onto a workbook that has comments in worksheet cells. To get the sample
database files you can download Lesson 22 from the book’s website at www.wrox.com.

Step-by-Step

1. Open a new workbook.
2. Go to the Properties window. In the Title field enter Comment Text and in the Comments

field enter Return text of comments in other cells.

3. Exit the Properties window and press the Alt+F11 keys to go into the Visual Basic Editor.

www.it-ebooks.info

   292 ❘ lesson 22  Add-Ins

4. From the menu bar in the VBE, click Insert ➪ Module. Copy the following User Defined
Function into the module:

Function GetComment(rng As Range) As String
Dim strText As String
If rng.Comment Is Nothing Then
strText = “No comment”
Else
strText = rng.Comment.Text
End If
GetComment = strText
End Function

5. Press the Ctrl+S keys to display the Save As dialog box. Navigate to the folder into which
you want to save this file. Name the file CommentText and select Excel Add-In in the Save
6. As Type field, as indicated in Figure 22-17. Click the Save button, which will convert this
7. workbook as a new add-in file named CommentText.xlam.
8.
9. Close Excel.
10.
Restart Excel and open a new workbook.

Right-click cell B2 of the active worksheet, and select Insert Comment. Enter some text in
your comment.

Select cell G1.

Press Alt+TI to show the Add-Ins dialog box.

Figure 22-17

www.it-ebooks.info

Try It  ❘  293

11. Click the Browse button and navigate to the folder where you saved the CommentText
add-in file. Select the CommentText file, and click OK. Your Add-Ins dialog box will look
like Figure 22-18, with the CommentText add-in loaded. Recall that the file is named
CommentText but the add-in dialog box shows it as Comment Text, and also shows the
description of the add-in, because that is the information you entered in Step 2 about the
add-in file in its Properties dialog box. Click the OK button to exit the Add-Ins dialog box.

Figure 22-18

12. In cell G1, enter the User Defined Function =GetComment(B1) and press the Enter key. Copy
the formula down to cell G2. You will see that the UDF returned “No comment” in cell G1
because no comment exists in cell B1. However, you did enter a comment into cell B2 in Step
8, so the UDF in cell G2 returns the text of the comment from cell B2. Your worksheet will
look similar to Figure 22-19.

Figure 22-19

13. Note that the workbook you are looking at does not contain the GetComment UDF code.
You can utilize that UDF because its code belongs to the CommentText add-in file that you
installed for the active workbook.

To view the video that accompanies this lesson, please select Lesson 22, available
at the following website: www.wrox.com/go/excelvba.

www.it-ebooks.info

www.it-ebooks.info

23

Managing External Data

One of the most versatile and useful benefits of Excel is its ability to import data from external
sources. In Lessons 26–30 you will see examples of sharing data back and forth with other
Microsoft Office applications from Excel.
Prior to Excel 97, the data that a person would be working with was entered into Excel manu-
ally. An Excel workbook was essentially a self-contained object that produced and stored its
own data, having almost no contact with the outside world except for the person working in
the project.
Starting with Office 97, Microsoft has been devoted to providing more and better tools for
importing and exporting data to the Internet, database programs, and text-related software
applications. Excel leads the way in this effort among all Office applications. In this lesson,
you learn how to use VBA to share data between Excel and other external sources, including
Access, the Internet, and text files.

Creating QueryTables from Web Queries

The Internet as we know it has only been around since the mid 1990s, not that long ago really,
but it’s hard to imagine what life would be like today without the World Wide Web. The pub-
lic’s desire is only increasing for access to the galaxy of information that is stored on the Web.
With each new release of its Office suite, Microsoft has improved the capacity of its applica-
tions to interact with web-based information.

When you connect Excel to an external source such as the Internet, you add a
QueryTable to your worksheet. Objects that can connect to external data sources
include a cell range, an Excel table, a pivot table, a text file, and a Web query. In
this case, you are adding a QueryTable to a worksheet because you are querying
the Web for information that will be displayed on your worksheet.

www.it-ebooks.info

   296 ❘ lesson 23  Managing External Data

Suppose you are interested in monitoring the stock prices of a half-dozen or so technology compa-
nies. If you want to avoid the monotony of going to a financial website and entering the same stock
symbols every time, you can automate the process with a Web query, and refresh the data anytime
you like.

When you build a Web query, you need to tell Excel what website to extract the information from,
and the cell address on the destination sheet where you want the QueryTable to be located. Some
background information about URLs and their parameters might be helpful for you to understand
what is going on.

If you open your Web browser and enter the URL http://money.cnn.com/quote/quote
.html?symb=YHOO,GOOG, you will reach a site that provides a table of stock quotes for Yahoo
and Google. With this URL, you are essentially passing URL parameters that allow you to pass
information such as search criteria to a website. In this case, the URL parameters being used are
the symbols for Yahoo (YHOO) and Google (GOOG).

The following macro places the QueryTable on cell A1, and points to one of the bevy of websites out
there that provide current stock quotes. For demonstration purposes, I chose a few companies that
are all headquartered in Silicon Valley where I live. The stock symbols of those companies are the
criteria that will apply URL parameters through the code to gather the stock quote information that
will populate the QueryTable. Figure 23-1 shows what the result looked like when I ran this macro
in January 2011.

Sub ImportStocks()

‘Declare variables for destination worksheet,
‘and two halves of the connection string:
‘one half for the URL, and the other half for
‘the quotes, to make it easier for you to edit.
Dim wsDestination As Worksheet
Dim strURL As String, strStocks As String

‘Set the destination worksheet; here it is Sheet2.
Set wsDestination = Worksheets(“Sheet2”)

‘Define the URL for getting your stock quotes.
‘There are many websites where you can do this.
strURL = “http://money.cnn.com/quote/quote.html?symb=”

‘Define your stocks of interest. I only selected these
‘as an example because they are silicon valley businesses
‘near where I live and run my Excel development company.
strStocks = “AAPL,CSCO,EBAY,GOOG,INTC,ORCL,YHOO”

‘My preference is to activate the destination worksheet
‘and select cell A1.
Application.Goto wsDestination.Range(“A1”), True

‘Clear the cells in the worksheet so you know the data
‘being imported will not be confused with other data
‘you may have imported previously and not yet deleted.
Cells.Clear

www.it-ebooks.info

   Creating QueryTables from Web Queries ❘ 297

‘Add your QueryTable with the connection string
‘and other useful methods you see in the With structure.
With wsDestination.QueryTables.Add _
(Connection:=”URL;” & strURL & strStocks, _
Destination:=Range(“$A$1”))
.BackgroundQuery = True
.SaveData = True
.AdjustColumnWidth = True
.WebSelectionType = xlSpecifiedTables
.WebFormatting = xlWebFormattingNone
.WebTables = “”“wsod_multiquoteTable”“”
.Refresh BackgroundQuery:=False
End With
‘Release object variable memory.
Set wsDestination = Nothing
End Sub

Figure 23-1

With the worksheet active, you can refresh the data by right-clicking cell A1 and selecting Refresh, as
shown in Figure 23-2. Alternatively, you can execute the VBA expression Range(“A1”).QueryTable
.Refresh in the Immediate window or in a macro. Each time you refresh the data, you see the most
recent version of the information in the data source, including any changes that were made to the data.

Figure 23-2

www.it-ebooks.info

   298 ❘ lesson 23  Managing External Data

Does your Web query take too long to refresh? You can cancel the Refresh
method if it’s running longer than you want to wait with this block of code:

If Application.Wait(Now + TimeValue(“0:00:10”)) Then
With Worksheets(1).QueryTables(1)
If .Refreshing Then .CancelRefresh
End With
End If

While on the subject of corporate performance, the following macro opens a .csv file for you,
depending on which stock symbol you are searching for, and copies several years of historical stock
price activity to Sheet3 of your workbook:

Sub ImportHistory()
Dim strStockSymbol As String
Dim strURL1 As String, strURL2 As String

‘Download the past years’ stock price activity.
strURL1 = “http://ichart.finance.yahoo.com/table.csv?s=”
strURL2 = “&d=2&e=18&f=2010&g=d&a=2&b=13&c=1986&ignore=.csv”
strStockSymbol = “EBAY”
Workbooks.Open Filename:=strURL1 & strStockSymbol & strURL2

‘Copy data from the csv file to your worksheet.
Range(“A1”).CurrentRegion.Copy _
ThisWorkbook.Worksheets(“Sheet3”).Range(“A1”)

‘Close the csv file without saving it.
ActiveWorkbook.Close False

‘Autofit the columns.
Columns.AutoFit
End Sub

There may be times when you are composing Web queries for other people to use. Before they try
running your macros, seeing as an Internet connection is required for the code to perform, it might
be a good idea to programmatically verify that the user has an Internet connection. You can place
the following procedures into a new standard module, and if no Internet connection exists, it would
be wise to use this code to halt any web-related activity your project may involve.

The strange-looking Public Declaration Function is not VBA code. It is
Applications Programming Interface, or API, which is the programming language
of the Microsoft Windows operating system. If you are wondering why API is being
used in this example, the reason is that the task at hand is a query about Internet
connectivity, which is a computer-wide issue that is not related specifically to any
one application, including Excel. In your programming travels, you will see API
being used with VBA for controlling objects that are related to Windows, such as
manipulating the task bar or returning the name of the computer.

www.it-ebooks.info

Creating a QueryTable for Access  ❘  299

Private Declare Function IsNetworkAlive Lib “Sensapi” _
(lpdwFlags As Long) As Long

Sub IsConnection()
If IsNetworkAlive(lngAlive) = 1 Then
MsgBox “You are connected to the internet.”
Else
MsgBox “Connection to the internet not found.”
End If
End Sub

There is another example in the Try It section that leads you in a step-by-step
process of creating a Web query.

Creating a QueryTable for Access

In upcoming lessons you learn about importing and exporting data between Excel and Access, using
VBA and a technology called Structured Query Language, or SQL. Because this lesson deals with
external data, you might be interested to know how to quickly, albeit manually, import an Access
table directly to your worksheet.
Click the Data tab on the Ribbon, and find the Get External Data section at the far left. Click the left-
most icon that is labeled From Access as shown in Figure 23-3.
You will see the Select Data Source dialog box. Navigate to the folder holding your Access database,
select the folder, and also select the name of the database file. Click the Open button as shown in
Figure 23-4.

Figure 23-3 Figure 23-4

www.it-ebooks.info

   300 ❘ lesson 23  Managing External Data

The Select Table dialog box will appear, so all you need to do is click to select the name of the table,
and then click the OK button as shown in Figure 23-5. After that, the Import dialog box will
appear. I chose to keep the imported table as a Table format, placed onto my worksheet, starting in
cell A1 as shown in Figure 23-6. Your Access table will load onto your worksheet as shown in
Figure 23-7, with the top row having AutoFilter buttons to help you with your future searches.

Figure 23-5 Figure 23-6

Figure 23-7

The Select Table dialog box may contain tables and queries, and you can import
data from either of them. You might want to be aware that Parameter queries
will not appear in this dialog box.

www.it-ebooks.info

   Using Text Files to Store External Data ❘ 301

Using Text Files to Store External Data

Hail the text file, the true foot soldier interface for transferring information between two or more
otherwise disparate platforms. In the modern age of computing, it’s always been the text file that
could be relied on for one application downloading its information in a comma-delimited or fixed-
length file, and another application like Excel being able to accept the data.

Text files are not pretty, they are almost never formatted, and they are not easy to read. But when all
else fails, they come through and are fairly easy to program. The following examples show how text
files can help you in your everyday work.

Suppose you want Excel to add a new record to a text file that records the date and time a particular
Excel workbook was saved. In the folder YourFilePath is a text file named LogFile.txt. The fol-
lowing VBA code goes into the ThisWorkbook module of the Excel file you are monitoring:

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Dim intCounter As Integer, myFileName As String
myFileName = “C:\YourFilePath\LogFile.txt”
intCounter = FreeFile
Open myFileName For Append As #intCounter
Write #intCounter, ThisWorkbook.FullName, Now, Application.UserName
Close #intCounter
End Sub

This macro will create four new text files, naming each with the prefix MyFile, followed by a num-
ber suffix in order from 1 to 4. For example, the first file will be named MyFile001.txt, the second
file will be named MyFile002.txt, and so on. The starting number of 1 is derived by the code line
For intCounter = 1 to 4. If you wanted to create four new text files starting with the name
MyFile038.txt, you’d establish the starting number of 38 by specifying it with the line of code For
intCounter = 38 to 41.

Sub CreateTextFiles()
Dim intCounter As Integer, strFile As String
For intCounter = 1 To 4
strFile = “MyFile” & Format(intCounter, “000”)
strFile = “C:\YourFilePath\” & strFile & “.txt”
Open strFile For Output As #1
Close
Next intCounter
End Sub

The following macro will copy the text of your comments in your worksheet’s used range into a text
file, where they will be listed along with the cell values in that range. This is a very fast macro.

Sub Comment2Text()
Dim cmt As Comment, rng As Range
Dim iRow As Long, iCol As Long
Dim strText As String

www.it-ebooks.info

   302 ❘ lesson 23  Managing External Data

Set rng = Range(“A1”).CurrentRegion
Open “C:\YourFilePath\YourFileName.txt” For Output As #1
For iRow = 1 To rng.Rows.Count
For iCol = 1 To rng.Columns.Count
If Not Cells(iRow, iCol).Comment Is Nothing Then
strText = strText & Cells(iRow, iCol).Text & _

“(“ & Cells(iRow, iCol).Comment.Text & “)” & “;”

Else

strText = strText & Cells(iRow, iCol).Text & “;”
End If
Next iCol
strText = Left(strText, Len(strText) - 1)
Print #1, strText
strText = “”
Next iRow
Close
End Sub

If you want to know how many lines a particular text file has, this macro will tell you:

Sub Test1()
Dim MyObject As Object, LineCount As Variant
Set MyObject = _
CreateObject(“Scripting.FileSystemObject”)
With MyObject.OpenTextFile(“C:\YourFilePath\YourFileName.txt”, 1)
LineCount = Split(.ReadAll, vbNewLine)
End With
MsgBox UBound(LineCount) - LBound(LineCount) + 1
End Sub

Export each sheet in this workbook as a text file, with each file named as the sheet tab name. Text
file macros compile very quickly.

Sub TextExport()
Dim rng As Range
Dim iWks As Integer, LRow As Long, iCol As Long
Dim sTxt As String, sPath As String
sPath = “C:\YourFilePath\”

For iWks = 1 To Worksheets.Count
Open sPath & Worksheets(iWks).Name & “.txt” For Output As #1
Set rng = Worksheets(iWks).Range(“A1”).CurrentRegion
For LRow = 1 To rng.Rows.Count
For iCol = 1 To rng.Columns.Count
sTxt = sTxt & Worksheets(iWks).Cells(LRow, iCol).Value & vbTab
Next iCol
Print #1, Left(sTxt, Len(sTxt) - 1)
sTxt = “”

www.it-ebooks.info

   Using Text Files to Store External Data ❘ 303

Next LRow
Close #1
Next iWks
MsgBox “The text files can be found in “ & Left(sPath, Len(sPath) - 1)
End Sub

If you would like to see a text file’s contents in a Message Box, you can use the following code.

Sub GetTextMessage()
Dim sTxt As String, sText As String, sPath As String
sPath = “C:\YourFilePath\YourFileName.txt”

If Dir(sPath) = “” Then
MsgBox “File was not found.”
Exit Sub
End If

Close
Open sPath For Input As #1
Do Until EOF(1)
Line Input #1, sTxt
sText = sText & sTxt & vbLf
Loop
Close
sText = Left(sText, Len(sText) - 1)
MsgBox sText
End Sub

Suppose you want to save the contents of cell A1 on Sheet1 as a text file. The following example
shows how that can be done:

Sub SaveCellValue()
Open “C:\YourFilePath\YourFileName.txt” For Append As #1
Print #1, Sheets(“Sheet1”).Range(“A1”).Value
Close #1
End Sub

Finally, this macro demonstrates how to delete a text file if it exists, and replace it with a new text
file of the same name. If the text file does not exist, the macro will create a new text file.

Sub DeleteAndCreate()
Dim strFile As String, intFactor As Integer
On Error Resume Next
strFile = “C:\YourFilePath\YourFileName.txt”
Kill strFile
Err.Clear
intFactor = FreeFile
Open strFile For Output Access Write As #intFactor
Close #intFactor
End Sub

www.it-ebooks.info

   304 ❘ lesson 23  Managing External Data

Try It

What is today’s date, and what is the current time of day? In this lesson you create a Web query to
import a display of the current day and time for several North American time zones.

Lesson Requirements

For this lesson, you access the website to the United States Naval Observatory, where the day and
time are recorded on the Master Clock of the United States Navy. To get the sample database files
you can download Lesson 23 from the book’s website at www.wrox.com.

Step-by-Step

1. Open a new workbook.
2.
3. From your worksheet, press Alt+F11 to go to the Visual Basic Editor.
4.
From the menu bar in the VBE, click Insert ➪ Module.

In your new module, type Sub TimeAfterTime and press the Enter key. VBA will produce the
following two lines of code, separated by an empty line:

Sub TimeAfterTime()

End Sub

5. Open a With structure for the destination worksheet:

With Worksheets(“Sheet1”)

6. Declare a String type variable for the website address:

Dim strURL As String

7. Define the website address from which the information will be imported to your worksheet:

strURL = _
“http://tycho.usno.navy.mil/cgi-bin/timer.pl”

8. For consistency, I prefer to activate the worksheet that will receive the web data. Cell A1 is a
convenient cell to start with:

Application.Goto .Range(“A1”), True

9. Clear the cells in the worksheet so you know the data being imported will not be confused
with other data you may have imported previously and not yet deleted:

Cells.Clear

www.it-ebooks.info

Try It  ❘  305

10. Open a With structure for the Add method of your new QueryTable. The connection, URL,
destination sheet, and other information that follows must be specified.

With .QueryTables.Add _
(Connection:=”URL;” &strURL, Destination:=.Range(“A1”))
.BackgroundQuery = True
.TablesOnlyFromHTML = False
.Refresh BackgroundQuery:=False
.SaveData = True

11. Close the With structure of the QueryTable’s Add method:

End With

12. Close the With structure for the destination worksheet:

End With

13. Your entire macro will look as follows:

Sub TimeAfterTime()

‘Open a With structure for the destination worksheet.
With Worksheets(“Sheet1”)

‘Declare a String type variable for the website address.
Dim strURL As String
‘Define the website address, from which the information
‘will be imported to your worksheet.
strURL = _
“http://tycho.usno.navy.mil/cgi-bin/timer.pl”

‘For consistency, I prefer to activate the worksheet
‘that will receive the web data.
‘Cell A1 is a convenient cell to situate yourself.
Application.Goto .Range(“A1”), True

‘Clear the cells in the worksheet so you know the data
‘being imported will not be confused with other data
‘you may have imported previously and not yet deleted.
Cells.Clear

‘Open a With structure for the Add method of your new
‘QueryTable. The connection, URL, and destination sheet,
‘and other information that follows, must be specified.
With .QueryTables.Add _
(Connection:=”URL;” &strURL, Destination:=.Range(“A1”))
.BackgroundQuery = True
.TablesOnlyFromHTML = False
.Refresh BackgroundQuery:=False
.SaveData = True

www.it-ebooks.info

   306 ❘ lesson 23  Managing External Data

‘Close the With structure of the QueryTable’s Add method.
End With

‘Close the With structure for the destination worksheet.
End With

End Sub

14. Press Alt+Q to return to the worksheet.
15.
You can test the macro by pressing Alt+F8 to display the Macro dialog box as shown in
Figure 23-8. Run the macro named TimeAfterTime. The result will resemble Figure 23-9.

Figure 23-8 Figure 23-9

To view the video that accompanies this lesson, please select Lesson 23, available
at the following website: www.wrox.com/go/excelvba.

www.it-ebooks.info

24

Data Access with
ActiveX Data Objects

The topic of data access has become one of the most intensive forces in driving the recent
development of commercial software applications. Data storage and search engine companies
have become the face of the worldwide voracious demand for accessing information.
Excel is without peer in its powerful features for calculating and analyzing data, and in its abil-
ity to produce customized reports in an instant with VBA. For users who deal with extremely
large volumes of source data, Excel can still fall short as a data storage application. Microsoft
has built Excel with some robust methods for importing external data into your workbooks,
making Excel a terrific front-end application that analyzes data it does not need to store.

Introducing ADO

ADO is an acronym for ActiveX Data Objects, which is the technology Microsoft recom-
mends for accessing data in external databases. Excel’s spreadsheets, being tabular row and
column objects, share common features with database tables, providing a natural environment
for data to be transferred between Excel and relational databases.
From Excel, using ADO you can

➤➤ Connect to most any external database in the Windows operating system, as long as
that database has, as many do, an ODBC (Open Database Connectivity) or OLE DB
(Object Linking and Embedding Database) driver.

➤➤ Add, delete, and edit records from a database to your workbook, or from your work-
book to a database.

➤➤ Query data to return a recordset, allowing you to import some or all records from a
database table directly to your worksheet, for whatever analysis you want to perform,
just as if the data was already in Excel.

www.it-ebooks.info

   308 ❘ lesson 24  Data Access with ActiveX Data Objects

Definitions of Database Terms

Because this lesson introduces concepts for external data access, there is more
descriptive theory about databases than actual code examples. In Lesson 29, you’ll
see several working examples of how Excel utilizes ADO and SQL in conjunction
with Access databases. If you are unfamiliar with database terminology, the follow-
ing definitions for common database terms might help you throughout this lesson.
A database is an organized collection of related information.
DAO (Data Access Objects) is a library of objects and their associated methods
and properties that can be used to represent objects in databases, enabling Excel to
interact directly with databases through VBA.
DBMS is an abbreviation for database management system. Popular examples of
database management systems include dBASE, Paradox, and Microsoft Access.
A field is a column in a list such as in an Excel worksheet or Access database that
describes a characteristic about records, such as first name or city.
ODBC (Open Database Connectivity) is a database standard that enables a pro-
gram to connect to and manipulate a data source, allowing a single user to access
many different databases.
A primary key is one or more fields that determine the uniqueness of each record in
a database.
A query is a series of statements written in Structured Query Language to specify
the tables and fields you want to work with that add, modify, remove, or return
data from a database.
A record is a row of data in a table.
A recordset is one or more records (rows) of data derived from a table.
A relational database is a collection of data items organized as a set of formally
described tables from which data can be accessed or reassembled in many ways.

Prior to ADO, Microsoft’s primary recommended tool for accessing external
data was an interface called DAO, or Data Access Objects. The DAO interface
has become all but obsolete due to its limitations as compared to ADO, though
DAO is still supported by ADO. The two technologies share many of the same
code syntaxes but they are not the same in terms of flexibility and performance.
You still do have a choice between the two, but you’ll be much better served by
ADO, which is why it is covered in this book.

www.it-ebooks.info

Introducing ADO  ❘  309

With entire books devoted to database integration with ADO, there is much more complexity to the
topic than this lesson is meant to cover. The best way to start becoming familiar with ADO is to
examine the three primary tools in its object model: the Connection object, the Recordset object,
and the Command object.

The Connection Object

The Connection object establishes a path that connects Excel and the database. With ADO from
Excel, you normally issue commands that pass information back and forth through the Connection
object. Among the key methods belonging to the Connection object are Open, which establishes
the database connection, and Close, which closes the connection. The Connection object’s
ConnectionString property defines how to connect to the database.
Connecting to the database is accomplished with the Provider keyword. The following line of code
is a common syntax for Excel versions 2007 and 2010:

Provider = “Microsoft.ACE.OLEDB.12.0;Data Source= _
C:\YourFilePath\Database1.accdb”;Persist Security Info=False;”

In versions of Excel prior to 2007, the Provider would have been specified as the Microsoft Jet data-
base engine of Access:

Provider = “Microsoft.Jet.OLEDB.4.0;” & _
“Data Source=C:\YourFilePath\Database1.accdb; Extended Properties=Excel 8.0;”

Or, depending on the circumstance, more simply:
Provider = “Microsoft.Jet.OLEDB.4.0”

When working with databases, you almost always connect to them, meaning you
do not open them in a way you’d open a Word document if you were working
with Word from Excel. The Connection object is like a conduit between Excel
and your database.

The Recordset Object

The Recordset object is probably the most commonly used object in ADO. When you instruct
ADO to retrieve a single record or the entire count of records from a database table, you use the
Recordset object to do that.
Among the key members of the Recordset object are the following:

➤➤ The ActiveConnection property, which is a connection string or a Connection object
that identifies the connection being used to access the database. As with this property for
the Command object, where objRecordset and objConnection are object variables, the
ActiveConnection syntax is
Set objRecordset.ActiveConnection = objConnection

www.it-ebooks.info

   310 ❘ lesson 24  Data Access with ActiveX Data Objects

➤➤ The Open method opens the Recordset object so you can access the data. Its syntax is

recordset.Open Source, ActiveConnection, CursorType, LockType, Options

Note that the Source argument is often a string that names the table from which the record-
set should be retrieved.
➤➤ The Close method closes an open Recordset object. With the Recordset object declared as
dbRecordset, the syntax for Close would be
dbRecordset.Close

The Command Object

The Command object holds information about the kind of task being run, which is usually related to
action queries in Access, or procedures in SQL, which are described in the next section. A Command
object can also return a list of data records, and is most often run with a combination of param-
eters, of which there are more than this lesson can possibly cover.
The Command object has three important properties:

➤➤ The ActiveConnection property, which, like the ActiveConnection property for the
Recordset object, is a connection string or a Connection object that identifies the connec-
tion being used to access the database. For example, this syntax assigns a Connection object
to the ActiveConnection property, where objRecordset and objConnection are object
variables:
Set objRecordset.ActiveConnection = objConnection

➤➤ The CommandText property, which sets the command that will be executed by the database,
and will usually be an SQL string.

➤➤ The CommandType property, which tells the database how to interpret and execute the
CommandText’s instructions.

An Introduction to Structured Query Language (SQL)

Structured Query Language (SQL) is a database language used in querying, updating, and managing
relational databases. SQL is used to communicate with the vast majority of databases that are com-
monly in use today.
Structured Query Language is a complex language in response to the rigid nature of table design in
relational database construction. This lesson covers SQL’s four basic operations of SELECT, INSERT,
UPDATE, and DELETE. As a reminder of what I mentioned at the beginning of this lesson, you’ll find
several examples of these operations in Lesson 29 that show how to work with Access from Excel.

www.it-ebooks.info

   An Introduction to Structured Query Language (SQL) ❘ 311

You’ll notice that SQL statements such as SELECT and INSERT are shown in
upper case. This is a standard SQL programming practice and a good habit
to get into from the start. The SQL code examples you’ll see in this book are
relatively small, but SQL code can be very large and complex. SQL is easier to
read when its statements are shown in upper case, distinguishing them from the
clauses of code with which they are associated.

The SELECT Statement

The SELECT statement retrieves data in the form of one or more rows (records) from one or more
tables. The SELECT statement is probably SQL’s most commonly used operation, because it tells the
data source what field(s) you want to return from what table(s).
If you want to retrieve all columns and all rows from the Vendors table, the expression in SQL
would be as follows:

SELECT *
FROM Vendors

Sometimes you might not want to retrieve all columns. The following example will retrieve the State
column from the Vendors table, if you want to know the count of your vendors per state.

SELECT State
FROM Vendors

If you want to see a list of vendors and the names of their contact people, but only for vendors
in California, the following example would accomplish that. Note that the literal string criterion
California is in single quotes, which is SQL’s required syntax.

SELECT VendorName, ContactName
FROM Vendors
WHERE State ‘California’

If you want to retrieve the previous recordset by having it already sorted by the VendorName field,
you could add the ORDER BY statement and specify the field name as follows:

SELECT VendorName, ContactName
FROM Vendors
WHERE State ‘California’
ORDER BY VendorName

www.it-ebooks.info

   312 ❘ lesson 24  Data Access with ActiveX Data Objects

The INSERT Statement

The INSERT statement adds a new row (record) to a table. You need to specify the name of the table
where the row will be added. You may optionally omit the field names from the INSERT statement
but it is advisable that you name them anyway because it will help you to see that the values you are
entering are in the same order as the field names.
An example of using INSERT is this fictional pair of statements that respectively place the values
5432, Doe, John, Male into a table named Employees, for fields named EmployeeID, LastName,
FirstName, and Gender.

INSERT INTO EmployeeID (EmployeeID, LastName, FirstName, Gender)
VALUES (‘5432’, ‘Doe’, ‘John’, ‘Male’)

It’s standard SQL programming practice to enter the statements in upper case.
It is mandatory SQL programming practice to place the string literal VALUES
within single quotes, just as you see it here.

If you had opted to enter the preceding SQL code without naming each field, the syntax example for
that same procedure would have been as follows:

INSERT INTO EmployeeID
VALUES (‘5432’, ‘Doe’, ‘John’, ‘Male’)

The UPDATE Statement

The UPDATE statement allows you to change the values in one or more columns (fields) in a table.
UPDATE is most commonly used to modify the value of a specific record that you identify with the
WHERE clause. You also need to specify each column you want to change, and what each column’s
new value should be.
The following example shows how you could update the contact name of one of your company’s
vendors in the ContactName column of the Vendors table. You need to be careful to specify the
WHERE clause so that only one record is changed, and that it is the correct record.
In the Vendors table, you have a field named VendorID that lists unique vendor identification num-
bers. The vendor name itself is Widgets, Inc. but that is not as important as its vendor identification
number. Suppose that the vendor identification number for Widgets, Inc. is 1234. The new contact
name is John Doe, executed with these three statements in SQL:

UPDATE Vendors
SET ContactName = ‘John Doe’
WHERE VendorID = ‘1234’

www.it-ebooks.info

Try It  ❘  313

If the ContactName field had many empty (referred to as Null) values, and you wanted to fill those
empty spaces with the word Unknown, the following example would accomplish that:

UPDATE Vendors
SET ContactName = ‘Unknown’
WHERE ContactName IS NULL

The DELETE Statement

The DELETE statement deletes one or more rows from a table. If you want to delete the vendor
named Widgets, Inc., you would use the WHERE statement to specify which value in which column
should identify the record for Widgets, Inc. The VendorID column is the perfect column for this task
because a large company might have two vendors with the same name.
The following SQL statements would delete the record from the Vendors table that has the value
1234 in the VendorID column:

DELETE FROM Vendors
WHERE VendorID = ‘1234’

Make absolutely certain you specify the WHERE clause, because if you do not,
every row from the Vendors table would be deleted. If an empty table is what
you want, this fictional sequence would accomplish that:
DELETE FROM Vendors
Odds are, you don’t want an empty table with all rows deleted from it. The
kicker is, after the rows are deleted, you cannot undo that action as you can in
Excel. Unless you are good friends with an experienced database programmer
who might (or might not) be able to recover your unintentionally deleted rows,
take heed and always specify the WHERE clause in your SQL DELETE actions.

Try It

This lesson introduced the fundamentals of ADO and SQL. You will see several examples in
Lesson 29 of VBA macros that show how to program ADO with SQL to interact with Access
databases from Excel.
Here is a way to get a head start on the instruction in Lesson 29 — b​ ecome familiar with database
tables. Open Access and create a new database. Create a new table and enter some fictional data such
as a mailing list with fields for FirstName, LastName, StreetAddress, City, State, Country, and Postal
Code. Make a dozen or so entries and get a feel for navigating and editing a database table. For exam-
ple, Figure 24-1 shows a table in Access being populated with hypothetical employee information,
such as you might see in a company’s personnel database.

www.it-ebooks.info

   314 ❘ lesson 24  Data Access with ActiveX Data Objects

Figure 24-1

You’ll notice an important distinction between an Access table and an Excel worksheet. Database
tables do not have row headers as numbers, or columns designated by letters. Columns (called fields in
a database environment) rely on being identified by their field headers such as FirstName, LastName,
and so on. Rows (called records) rely on being identified by one or more key fields, or certain proper-
ties of other fields such as being empty (Null) or having date entries between a start date and end date.
You might also want to surf the Web for sites that list SQL objects and their associated properties
and methods. Keep in mind that SQL’s capacity for database interaction goes far beyond what you’ll
need it to do for your Excel projects, so stick with the basics for now when perusing SQL instruc-
tional material.

www.it-ebooks.info


Click to View FlipBook Version