Excel Vba Book
Excel Vba Book
in
Microsoft Excel VBA
An
Introduction
Programming In Excel VBA by J.Latham
An Introduction Microsoft Excel MVP 2006-??
The most current version of the book may be downloaded, free of charge, from:
http://www.jlathamsite.com/LearningPage.htm
HTU UT
Look for the link to the .pdf document just below the heading "Introduction to VBA Programming". I
recommend right-clicking the link and choosing "Save Target As" to get a copy of it onto your system.
In October 2012, a new publication was placed on the website. While not designed specifically
to be a companion to this introduction, I believe that many of you that are serious about
programming in Excel VBA will find it useful. It is also available through the above link,
through this direct link to it:
Bullet-Proofing Your Excel VBA Code
It also has a companion workbook demonstrating the effects of scope in Excel VBA.
SlicesOfPi.xls
And keep your eyes out for an introduction to Debugging that is now a work in progress.
Table of Contents
OVERVIEW ...................................................................................................................................... V
T T
Why ............................................................................................................................................ v
T T
What ........................................................................................................................................... v
T T
Who ............................................................................................................................................ v
T T
How ............................................................................................................................................ v
T T
Copyright Acknowledgments.................................................................................................. vi
T T
Workbook Events.................................................................................................................... 7
T T
Functions.................................................................................................................................. 11
T T
Subs .......................................................................................................................................... 12
T T
Public Scope.......................................................................................................................... 20
T T
If...Then .................................................................................................................................... 29
T T
If...Then...Else.......................................................................................................................... 30
T T
If...Then...ElseIf...Else............................................................................................................. 30
T T
www.Contextures.Com ........................................................................................................... 70
T T
http://www.contextures.com/tiptech.html ............................................................................ 70
T T
F (cont'd) .................................................................................................................................. 70
T T
General ............................................................................................................................. 85
T T
Formatting ....................................................................................................................... 85
T T
Formulas .......................................................................................................................... 86
T T
Printing ............................................................................................................................ 88
T T
UserForms ....................................................................................................................... 88
T T
TU Figure 2 Open the VBE from the Excel Tools Menu ..................................................................... 3 UT
Overview
0B
WHY
16B
Why does this book exist? I wrote this book to hopefully provide a basic introduction to learning to
program using Visual Basic for Applications (VBA) as implemented in Microsoft™ Excel©. I have
attempted to provide a balance of basic programming concepts and good programming practices. Along
the way concepts are presented that often fall into the “advanced” category in other books. I don’t believe
these concepts are “advanced” in that it takes more basic teaching to understand and use them, rather if
they are taught as part of that basic teaching they are no more difficult to learn than anything else in the
language.
The goal is not to make you all-knowing of all things VBA in Excel, but rather to try to give you a basis
for understanding what VBA for Excel is capable of, helping you put code samples you obtain from a
variety of sources to work for you, to learn how to modify and adapt recorded macros to make them more
generic and useful to you, and to encourage you to learn more about the language so that you can take full
advantage of the worlds #1 spreadsheet application.
WHAT
17B
What is taught in this book? The basic elements of VBA coding are covered and hopefully taught in it.
The First Edition will pretty much just cover what I decide to cover. If anyone has specific things that
they feel would be beneficial to the budding VBA programmer, I will certainly entertain the idea of
including them in later revisions to it. You can send such suggestions via email to:
[email protected]
HTU UTH
The difficulty in presenting this type of material is that teaching VBA coding requires knowledge of many
things that have inter-dependence on one another. This inter-dependence can be an actual physical
dependence, but more often it is a dependence based on the knowledge of many different elements of the
programming environment: the syntax or command structure for instructions; a knowledge of the
“objects” in the application and their attributes (properties) and the things you can do to or with them
(methods), along with many other things. By necessity some things must be taught before others in order
to build from a basic understanding to more complex understanding as the studies continue. In discussing
some of the basics, more advanced concepts may be used in the process and the reader must accept those
as-yet-unexplained concepts and pieces simply on faith or with an “it is what it is” attitude for a while.
Since this is an Introduction to VBA for Excel, many details of many subjects and areas are left to be
discovered by the student on their own through experience, further study and examples from other sources
in the future.
WHO
18B
This book is for anyone desiring to learn how to extend the functionality and usefulness of Excel through
added capabilities often only available through VBA.
HOW
19B
You will learn to begin programming in Excel VBA by reading through this book and you will use your
copy of Excel to ‘follow along’ and create procedures and observe them at work.
ANTICIPATED USER SKILL REQUIREMENTS
20B
This book is designed to be used by those with the Excel® knowledge typical of the ‘average’ office user.
This means that the user is expected to be familiar with general Excel® features and functions such as the
use of menu and icon toolbars, selecting worksheets and cells, creating simple formulas in cells,
‘navigating’ within Excel®, and opening, saving and closing the Excel® application and Excel® created
workbooks (.xls files).
This document was created using Microsoft Word and Excel 2003, along with the Microsoft Office 2007 provided
‘publish as .pdf’ feature to generate the final document.
Graphic screen capturing was performed using SnagIt from TechSmith.
COPYRIGHT NOTICE: This document in all forms is Copyright © by Jerry L. Latham, 2008, 2009,
2011. All rights are reserved. Readers are granted permission to make copies for their personal or
educational use and even corporate/commercial use, but in no instance may the document or portion or
portions thereof be used as part of or as the totality of any package that is distributed or provided for
profit or other gain. This book is FREE and if someone charged you money for it, or charged you
money for a package that it is any part of, they stole from you and they stole from me. Those people are
thieves.
The most current version of the book may be downloaded, free of charge, from:
http://www.jlathamsite.com/LearningPage.htm
TUH UT
Look for the link to the .pdf document just below the heading "Introduction to VBA Programming". I
recommend right-clicking the link and choosing "Save Target As" to get a copy of it onto your system.
In October 2012, a new publication was placed on the website. While not designed specifically
to be a companion to this introduction, I believe that many of you that are serious about
programming in Excel VBA will find it useful. It is also available through the above link,
through this direct link to it:
Bullet-Proofing Your Excel VBA Code
It also has a companion workbook demonstrating the effects of scope in Excel VBA.
SlicesOfPi.xls
What is VBA?
1B
Visual Basic for Applications (VBA) is an extensible programming language that is made up of a
core set of commands and extended on a per-application basis to be able to work directly with
objects in that application. This means that VBA for Excel knows about things like workbooks,
worksheets, cells and charts and more; while VBA for Access knows about tables, queries,
reports and data entry forms, among other things. The core can even be licensed for use by 3rd P P
party companies to permit it to be used with their application(s). This was the case with Visio
before Microsoft bought the product for use under their banner.
VBA can probably be best described as an object-based (but not a true object oriented) language
that is event driven. Let’s look at the event driven side of it first.
23B VBA: AN EVENT DRIVEN LANGUAGE
Event driven means that nothing happens until something happens. Rather Zen-like isn’t it? Ok,
once again, but with a better grasp of reality. In VBA, no code executes except in response to
some event taking place (or at the command of the code once it is started by some event). An
event can be any one of many things. Opening an Excel workbook creates, or triggers, the Open
event, closing it triggers the BeforeClose event. Selecting a worksheet in the workbook will
cause a Deactivate event to occur on the page that had been selected and an Activate event to
happen to the new sheet you select. Many events occur that don’t have code associated with
them, and that’s to be expected; something doesn’t have to happen every time something else
happens. A shape (square, button, text box) actually triggers a Click event when it is clicked on
– you may or may not have code associated with one of those shapes to respond when it is
clicked on.
Event driven also means that you never know exactly when code for an event will be called upon
to run. For example, you may have a process that runs when a particular sheet is selected that
takes a long time to complete – perhaps checking for and hiding unused rows, or refreshing the
data on the sheet from another data source. While that is going on, you may click a button on the
sheet to try to do something else, such as sort the data on the sheet. Excel will, for the most part,
deal with the timing of when these processes are performed. You do need to be aware that it is
possible to request an operation to begin before another has completed. Most of the time this
does not cause any problem at all, but sometimes it can.
VBA: AN OBJECT-BASED LANGUAGE
24B
Object based means that when referring to the components of the application, things like
workbooks, worksheets, cells, charts, etc. are ‘objects’. An object has certain attributes. Just a a
person has attributes like height, weight, eye and hair color, the objects in Excel have attributes
(Properties) such as value, height, width, color and more. Additionally, objects can do things or
have things done to them – these actions are known as Methods. For example, a workbook can
be opened or closed; a cell can have its shading altered, a worksheet can be deleted.
While you may use constants and variables in your code that seemingly don’t have any direct
relationship to an object, in the end the results of processing or calculations will probably be
used to alter some property of an object in the workbook: the value in a cell, the range of
information used as a data series on a chart, whether or not a particular sheet is visible or not at
any given moment. With all of this under our belt, we can now look at how to access this power.
The Excel VBA IDE (Integrated Development Environment) has not changed in quite some
time. This is a good thing – the interface in Excel 2007 is the same as it was in Excel 2003, 2002
(XP), and even back to Excel 97 , and that means that no time is wasted for programmers in
learning a new interface just to be able to continue to use a language they are already familiar
with. There are 5 major areas of the IDE and I like to work with all of them visible.
Your first question may be “How the heck did you get there!?” The quickest way to open the
VBA IDE (which I’ll simply call the VBE for Visual Basic Editor for the rest of this document),
is to press [Alt]+[F11] while in the main/normal Excel window. You can also get there from the
normal Excel menu via Tools | Macro | Visual Basic Editor:
This is the VBE [View] menu option expanded. As you can see,
it permits you to display any of the 5 major areas of the IDE and
even more that are useful in special circumstances such as the
Object Browser and the Locals and Watch windows.
Note: To close any of these windows once you’ve opened them,
simply click the classic “close window” [X] in the upper right
corner of the window.
I’ll bet you thought that all code modules were created equal. Not true – code modules don’t
have any Constitutional Rights, although they do have to follow the rules of design requirements
imposed by Microsoft and the compiler.
27B GENERAL PURPOSE CODE MODULES
These are code modules you’ll bring into existence and can contain code to do almost anything
of a ‘general purpose’ nature. Examples of code that might appear in them would be code that
responds to shapes or command buttons you might put on a worksheet; code to respond to
custom menus you might develop, user defined functions (UDF) that you develop to perform
actions and calculations by way of using the name of the UDF in a worksheet formula just like a
built-in Excel worksheet function.
Oh, By the Way Macros you record are placed into general purpose modules. Recording
macros during different sessions with the workbook results in numerous modules that may
contain as few as a single procedure (macro) in it. This results in being quite wasteful of
resources. All macros recorded during a single session are typically placed into a single module.
To create a new general purpose module you can use the [Insert] | Module
option from the VBE menu toolbar:
Just what are the workbook events? You can get a complete list of them from the code window
while the Workbook Code module content is displayed: You can display that content by double-
clicking the ThisWorkbook object in the VBAProject window. You’ll get a display similar to
this
There is one and only one code module per worksheet that is associated with Worksheet Event
handling. However, each sheet has its very own code module that is separate and distinct from
all of the others even though they may all have event handlers for a given event for those
worksheets. At the technical level, this module, just like the event handling module for the
workbook are Class Modules. Remember that if you want to do any coding that deals with
events that occur at the worksheet level, you do it in these modules.
Worksheet Events
86B
Just what are the worksheet events? You can get a complete list of them from the code window
while any Worksheet Code module content is displayed: You can display that content by
double-clicking any worksheet object in the VBAProject window. The code module for that
sheet will be displayed. You’ll get a display similar to this
Often in worksheet event stubs provided by the VBE you will see reference to two special
objects (sometimes more or others also): Cancel and/or Target.
Target represents the Range [which is an object that represents a single cell, a group of cells, one
or more rows and/or one or more columns] that is active at the time the event took place. Think
of Target as the actual object itself. Anything you do to Target is done to the actual Range that
it represents. Changes made to Target will appear on the sheet itself.
The Cancel object is a Boolean type object. A Boolean object can only have one of two
conditions assigned to it: TRUE or FALSE. By default a Boolean object is FALSE (and has a
numeric value of zero). If your code sets Cancel = TRUE then the underlying event action is
cancelled: the DoubleClick never takes place or the RightClick never gets completed. These are
handy events to use to take very special actions with – you can have someone double-click in a
cell (and set Cancel = True) to begin a series of events unique to that cell. A real world example
of this type of thing in one application I developed is that in a data area matrix that has dates in
Quite frankly we’re not going to cover Class Modules. That is an “advanced” topic in my
considered opinion, and 99.9% of all coding needs can be met without using them. Creating a
class takes much more preparation and thought than we have the time or space for in this book.
UserForms and their Modules
89B
We will cover both UserForms and their underlying code modules separately later. Think of
them much as worksheets and worksheet modules. Each UserForm has its own code module that
contains the code associated with all objects on the UserForm.
The difference between a Sub and a Function is simply that a function can return a value to the
procedure that called it. That procedure can be another Function, a Sub or even to a worksheet
cell. When it is done using a worksheet formula, the Function is known as a User Defined
Function, or UDF. Potentially all Functions are UDFs.
One other distinction between Functions and Subs is that (generally) Functions can only affect a
single cell in a workbook, while Subs can do their work and affect almost any aspect of a
workbook or worksheet. When it is used as a UDF, it can only affect the cell that it is called
from; it cannot alter the contents of other cells.
A Function starts with its declaration:
Function functionName (argument1 As Type, argument2 As Type) As fType
Where Function is a reserved word declaring the start of the definition of the function.
functionName is the name you assign to the function.
Within the parenthesis you define the list of arguments and their types that are to be passed to the
function for it to use to get its job done. You do not have to pass any arguments, but you do have
to use the parenthesis, as:
Function noArgumentFunction() As Boolean
Finally, you declare the type of value that the function will return (fType). The type can be any
valid type such as String, Boolean, Integer, Float, Double, Long, Variant, etc.
A Function ends with the End Function statement. Everything in between the function’s
declaration and the End Function statement is part of the function itself.
Here is an example of a function that calculates and returns the square of a value passed to it:
Function SquareOfNumber(anyInteger as Integer) As Long
SquareOfNumber = anyInteger ^ 2
End Function
Here is how it might be called from another procedure:
Dim aNumber as Integer
Dim numberSquared as Long
aNumber = 15
numberSquared = SquareOfNumber(aNumber)
After all of that numberSquared will contain 225 (15 * 15, or 15^2)
The function could also be called from a worksheet in a cell like this:
=SquareOfNumber(15)
And 225 would appear in the cell. Actually, Excel would display the formula as:
Procedures: Sub and Function Page 11
Copyright © 2008 by J.L.Latham, All Rights Reserved.
Programming In Excel VBA by J.Latham
An Introduction Microsoft Excel MVP 2006-??
=squareofnumber(15)
Excel makes UDF names all lowercase to distinguish them from built-in worksheet functions.
32B SUBS
Sub procedures are just like Functions, except that they do not return a value in the same way
that a Function does. They can accept arguments, or not, just like a Function does.
A Sub starts with its declaration:
Sub subName (argument1 As Type, argument2 As Type)
Where Sub is a reserved word declaring the start of the definition of the procedure.
subName is the name you assign to the procedure.
Within the parenthesis you define the list of arguments and their types that are to be passed to the
Sub for it to use to get its job done. You do not have to pass any arguments, but you do have to
use the parenthesis, as:
Sub noArgumentProcess()
There is no declaration of the type of value that the sub will return because if there were, then it
would be a Function and not a Sub.
A Sub ends with the End Sub statement. Everything in between the sub’s declaration and the
End Sub statement is part of the sub itself.
PROCEDURES: PUBLIC OR PRIVATE
3B
By default all procedures are “Public”. That is to say that they can pretty much be used from
anywhere in the project. For Sub procedures, it also means that they show up in the Tools |
Macro | Macros list as available to be run through that interface and for Functions, public
functions can be used as UDFs. You can explicitly declare a procedure to be Public by
preceding its declaration with the word “Public” like:
Public Sub aPublicSub()
or
Public Function aPublicFunction(arg1 As Variant) As Variant
But sometimes we don’t want the user to have access to a procedure, or don’t want other
modules to be able to use a procedure in another module. For those times, you can make a
procedure only accessible from within the code module that it exists in by preceding its
declaration with the word Private. You’ll notice that all of the Workbook and Worksheet built-in
event procedures are declared as Private. Subs that are declared as Private do not show up in the
Tools | Macro | Macros list, and private functions are not available for use as UDFs. Examples
of private declarations are:
Private Sub aPrivateSub()
or
Private Function aPrivateFunction(arg1 As Variant) As Variant
Private procedures are normally only usable by other procedures in the same module with them.
There is an exception to the rule; you can get around it by using Run “privateProcedureName”.
You can also use the Call command in a similar fashion. See the Excel VBA Help topic on
CALL for limitations in using it. When you use Run or Call the procedure is executed and
control returns to the line of code following the Run or Call statement.
Procedures: Sub and Function Page 12
Copyright © 2008 by J.L.Latham, All Rights Reserved.
Programming In Excel VBA by J.Latham
An Introduction Microsoft Excel MVP 2006-??
Decimal – this is a special type that almost doesn’t exist. The quote from Excel Help tells this
tale: “…signed integers scaled by a variable power of 10. The power of 10 scaling factor
specifies the number of digits to the right of the decimal point, and ranges from 0 to 28. With a
scale of 0 (no decimal places), the largest possible value is +/-
79,228,162,514,264,337,593,543,950,335. With a 28 decimal places, the largest value is +/-
7.9228162514264337593543950335 and the smallest, non-zero value is +/-
0.0000000000000000000000000001.
Note At this time the Decimal data type can only be used within a Variant, that is, you cannot
declare a variable to be of type Decimal. You can, however, create a Variant whose subtype is
Decimal using the CDec function.”
You cannot use words unique to the VBA language as the names for your own constants and
variables. The list is pretty long, you’ll learn what you can use and what you cannot during your
coding efforts. Words like For, Next, Do, Loop, Until, Dim, Const, InStr are reserved for the
language and you can’t use them except as the instructions that they are. It is even considered
bad form to use a reserved word as part of a constant or variable name because it can confuse
anyone reading the code later, so while intNext is a valid name, it is an unwise one to use; but a
name like intNextNameInList would probably be a good one to use.
COMMENTS AND REMARKS
37B
It is always a good idea to add comments to your code. How many to add is a judgment call on
your part. But a comment should add understanding and not just repeat what the code is doing:
X = X + 1 ‘ add one to X
There isn’t too much that will make your users think of you often and most unfavorably than for
them to have entered a lot of important information and suddenly have the program blow up in
their face with an unhandled error (also called an exception in some languages).
If you try running MyFirstProcess
and supply a word or other non-
numeric entry to be processed you
will get a Type mismatch error
because we defined variable
theResult as an Integer type, and
words are not integers. Clicking
[End] will stop the process; clicking
[Debug] will take you to the line in
the code where the error took place.
Now if you run the procedure again and enter a word or something other than a number, you are
gently requested to correct the error of your ways and allowed to try again without the entire
application crashing to the ground.
Now we will continue our interrupted discussion of declaring variables and constants.
A variable declared inside of a procedure has procedure level scope. The variables and constants
we declared in MyFirstProcedure had procedure level scope.
Procedure level variables are created when the procedure begins to execute, they are only
available to be used within the procedure and they cease to exist when the procedure ends at the
procedure’s Exit Sub or Exit Function statement.
As with any good rule, this one has an exception. If you declare the variable using the Static
declaration instead of Const or Dim statements, then the variable will retain the last value
assigned to it when the procedure ended as its initial value the next time the procedure executes.
A trivial example: try placing this code in a module and just press [F5] several times to watch the
value of myStaticCounter go up each time.
Sub StaticsAtWork()
Static myStaticCounter As Integer
'each time this procedure is called, myStaticCounter value will increase by one
myStaticCounter = myStaticCounter + 1
MsgBox myStaticCounter
End Sub
Even though myStaticCounter retains its last value, it still cannot be accessed to determine its
value outside of the procedure – it retains its procedure level scope.
You cannot use the Public or the Private declarations within a procedure. For all practical
purposes all declarations within a procedure are private to that procedure.
Module Level Scope
91B
The next step up the scope food chain is module level scope. These are constants and variables
that can be used/evaluated/modified (for variables) by any procedure in the module. Module
scope variables and constants are declared in the General Declarations Section of a module.
The General Declarations Section of a module is the area ahead of any declaration of a
procedure. The Option Explicit statement that we’ve already seen is in this section of the
modules. Declare your module scope variables and constants after the Option Explicit statement
and before any procedure declaration.
You can use the Dim and Const statements to make declarations in this area but it is clearer to
the reader if you use the Private declaration statement so that readers will know later that these
variables and constants are private/local to the module:
Private anyModuleLevelScopeVariable As Variant
Private Const anyModuleLevelScopeConstant = “The whole module can see me!”
Public is a term that was previously Global. A variable or constant declared as Public in the
General Declarations section of any standard module has visibility/accessibility in any procedure
in any module in the entire project.
Why not just declare everything Public and be done with it? Because in more than the simplest
application you will invariably change the value of a public variable at the wrong time/place
causing yourself mega-headaches in debugging it all. Overall it is best to keep the scope of your
declared values at the lowest level possible. You will have fewer problems and easier debugging
all around by doing that.
I personally like to put all of my Public constants and variables into a single module with
comments provided to explain where they are used and what they are used for. This provides a
single central point of management for the Public values.
What are candidates for Public values? Look for things that you find yourself using repeatedly
for the same purpose in several areas of your project – perhaps using the same worksheet name
to perform operations with the sheet; definitions of the layout of those worksheets, constants that
your logic depends on heavily and are used in multiple areas.
When to Use Constants and/or Variables
93B
One question that comes up from time to time is “why use constants at all – why not just use
their value(s)?”. I’ll answer your question with a question: which is more informative to you
here?
If ActiveCell.Row < 4 Then
Or
If ActiveCell.Row < firstRowWithData Then
Not only is the second form more understandable, it keeps you from having to track down every
place you’ve used 4 as a value and trying to figure out if you mean the first row with data on a
sheet, or are comparing ages of pre-school children, or seeing if the word Mississippi has the
correct number of 'i's in it.
Finally, using named variables/constants helps prevent typographic errors. [Debug] | Compile
VBAProject will find errors in variable/constant name spellings rapidly, but it cannot do
anything at all to determine that you typed a 4 when you really meant to type a 5 and just had
your finger on the wrong key when you typed it. A common error, known as FFS (fat finger
syndrome).
Be consistent. If you don’t follow any published standards for conventions such as commenting,
constant/variable naming, source code listing formats or others, then at least be consistent within
your own code in the way you do these things. This will make your code more readable and
understandable to you, and will tend to making extending the code to include new features,
modify old ones and simply fix bugs than if you do things one way today and some other way
the next. That is not intended to keep you from changing the way you do things as you discover
better ways to do them.
MORE GOOD PROGRAMMING PRACTICES
42B
As we encounter situations in our coding examples where a Good Programming Practice can be
demonstrated, they will be pointed out and labeled as GPP #n That may be more effective in
showing them to you ‘in context’ than just describing them in a list here.
7B Looping Structures
One thing that computer code is good at doing is something dull and tedious for us human types:
repetitive actions. A macro in itself is a way of doing something repetitive, with varying levels
of complexity, over and over with ease and without boring ourselves to death doing it. Each
time we run a Macro or cause a procedure to be called, we are performing some repeated
process.
Within procedures we may also need to perform a particular task many times. The use of
looping structures such as:
For … Next
For Each … Next
Do … Loop
Do … Until
and
Do … While
All give us slightly different ways to perform actions, calculations and other processing many
times in a relatively small section of code.
43B GPP #3:
Keep the amount of work inside of a loop to a minimum. If there is something that can be done
outside of the loop before starting it, do it outside of the loop.
For example let us assume you want to take a list of numbers you have in a range and increase
those values by some percentage that you have stored. You could code it like this:
For Each anyValue In listOfValues
anyValue = anyValue * (1 + percentIncrement)
Next
The problem with this is that each time through the loop, the value of 1 + percentIncrement must
be recalculated. You can increase the efficiency of that loop by calculating that value before
entering the loop, as:
tempValue = 1 + percentIncrement
For Each anyValue In listOfValues
anyValue = anyValue * tempValue
Next
FOR … NEXT LOOPS
4B
The simplest and oldest loop structure in Basic is the For…Next loop. The general form, or
syntax, of the command is
For counter = startCount To endCount Step stepValue
Executable statements and comments to be performed
Next
For is a reserved word that marks the beginning of the loop.
This is a special loop that works very much like the For…Next loop, but it loops with ‘objects’
within larger group of the same type of objects. The Excel engine is smart enough to figure out
that part of it. That is, if your larger group is Worksheets, it knows to work with each individual
worksheet in the group; or if your range is a group of cells, it knows to work with each individual
cell within the group.
Typical setups for using For Each might be similar to these:
Dim groupOfCells As Range ‘ remember, a range can refer to 1 or more cells
Dim anySingleCell As Range ‘ remember, a range can refer to 1 or more cells
Set groupOfCells = ThisWorkbook.Worksheets(“SomeSheetName”).Range(“A1:A500”)
For Each anySingleCell In groupOfCells
… do some work within the loop
Next
Here is an example that would protect all sheets in the active workbook without a password.
Dim anySingleSheet As Worksheet
For Each anySingleSheet In ActiveWorkbook.Worksheets
anySingleSheet.Protect
Next
For x = 0 To 0
MsgBox "inside of the loop"
Next
End Sub
You will see the message once, proving that the code inside of the loop did run.
If a For...Next loop runs to completion, the value of the counter value will be one more than the
endCount. Example:
Sub test()
Dim x As Integer
Dim y As Integer
For x = 1 To 10
y=y+1
Next
MsgBox "Counter x is: " & x & vbCrLf & "Value y is: " & y
End Sub
The message displayed should be:
Note: in the MsgBox statement, vbCrLf is a built-in VBA constant that provides a newline; that
is, it provides a Carriage Return and a Line Feed, thus they called it vbCrLf.
Use [Ctrl]+[End] to break into that code if you actually try running it.
There is nothing in that code to stop the loop from processing, so it pretty much runs forever.
While there are times when you may actually choose to implement such a loop, you usually want
a way to halt one either manually or automatically. We will rewrite the code a little to get it to
halt automatically after having annoyed you just a little.
Sub LoopForever()
Dim loopCount As Integer
Dim y As Integer
Do Until loopCount = 3
MsgBox "Looped " & y & " times."
loopCount = loopCount + 1
y=y+1
Loop
End Sub
the value of loopCount is used to exit the loop once it reaches a value of 3. How many times will
the message appear? No, not a trick question - the message will appear 3 times.
But what happens if we change it just a little bit?
Sub LoopForever()
Dim loopCount As Integer
Dim y As Integer
Do While loopCount < 4
MsgBox "Looped " & y & " times."
loopCount = loopCount + 1
y=y+1
Loop
End Sub
So I'll ask the question again: How many times will the message appear? In this case it becomes
a trick question. You'll see the message 4 times. And yet logic tells us that 3 is less than 4, but
the test must be done at the Do While statement and that means that we get an extra, sometimes
unexpected pass through the loop.
Again the message will be displayed 4 times because even though we've moved the test to the
bottom of the loop, we still have to get some value into loopCount that equals or exceeds 4 in
order to exit the loop. So be sure you know how many times your loop will execute if you are
depending on it to exit after a specific number of iterations. If we rewrite the last section like
this:
Sub LoopForever()
Dim loopCount As Integer
Dim y As Integer
Do
MsgBox "Looped " & y & " times."
loopCount = loopCount + 1
y=y+1
Loop While loopCount < 3
End Sub
Then the message will be displayed 3 times, presumably as you expected it to. You could also
change that last statement to:
Loop Until loopCount = 3
and get the message displayed 3 times.
We had to do a little more work but we got a lot of added functionality. Try changing the value
of constant testPhrase and see how it works. Just make sure you have at least one non-alphabetic
character in the phrase since we haven't tested to see if positionInString ends up becoming
greater than the number of characters in testPhrase.
Generally there's no accepted standard for which of the Do Loop types (While or Until) to use
other than your own personal preference. Typically you can write either type to accomplish the
same task and get the same result.
8B Decision Makers
There are two primary decision making tools in VBA: If...Then and Select Case. We can look
at the loop structures as decision makers also, but they are kind of indirect decision makers. The
If...Then, and its brothers If...Then...Else and If...Then...ElseIf...Else along with Select Case
are very definitely there to assist you in changing the path of the program or the logic of a
process; i.e., they help you make decisions about what to do next based on the result of
calculations or actions at a specific point in your process.
IF...THEN
48B
This is the most basic of the decision makers. Using it assumes there is pretty much only one
test to perform and only one action to take if the result of the test is true. It can be written as a
one-line statement such as:
If X = 2 Then Y = 5
Very straight forward statement: if at this point in the process X equals 2, then set Y to 5. If X
does not equal 2 at this point, Y will retain whatever value it has at the moment.
A personal preference of mine is to make even this simple statement a "block" because I think it
makes the code more readable and understandable. This is exactly the same statement, but in
"block" form:
If X = 2 Then
Y=5
End If
This form also allows us to easily and clearly perform more than a single action based on the
result of the decision, like this:
If X = 2 Then
Y=5
Z=9
aStringVariable = "X was 2"
End If
So in this example, we perform three actions when we find that X has a value of 2. The End If
statement also gives us a clear view of what will be done when X = 2 by defining the end of the
If Then code block.
But what if we need to do one thing when X = 2 and do something else when it doesn't? Enter
the If...Then...Else statement.
Using this combination we can test for different values of a particular item. For this example, we
need to set Y, Z and aStringVariable to specific values when X is either 2 or 3, and another set of
values when it is not 2 or 3.
If X = 2 Then
Y=5
Z=9
aStringVariable = "X was 2"
ElseIf X = 3 Then
Y=0
Z = 99
aStringVariable = "X was 3"
Else
Y=1
Z=3
aStringVariable = "X was neither 2 nor 3"
End If
You may actually have many ElseIf ... Then statements before the final Else statement, making
this a multi-conditional decision maker. But for the times when you have many decisions to
make based on the value of one (or more) variable value(s), the Select Case statement is more
efficient.
9B Data Sources
There are lots of sources for data to work with inside of Excel:
Cells on worksheets
Files external to the Excel workbook (and I include things like queries to obtain data
from a variety of sources such as database files or from a networked location or internet
site)
The user!
There are a couple of things you need to keep in mind when getting data from any source:
You have to know where to find it, and what actions to take to get it into your VBA code
to work with, and
Remember that what you expect to get is not always what you actually do get. We'll
cover this aspect some more in a short discussion of data validation later on.
DATA FROM WORKSHEETS: INTRO
52B
Within VBA you can get data from any cell or group of cells on any worksheet in any open
workbook. Later on I'll show you how to do this without ever leaving the cell that is currently
active on your screen.
You will need to know where to look for the information or how to find it, and unless you are
working in a fairly structured situation, you may need to perform some data validation on it
before trying to use it in your code.
DATA FROM EXTERNAL SOURCES
53B
The possible external sources and their types is so varied that we can't really cover them all here.
You'll need to know how to either open any external data file such as a .txt, .dat or .csv file and
read from it and you'll need to know the format of the data in the file. Usually you have an idea
about these things before you begin writing the code to access the external files, so don't worry
about it at this time. Sometimes finding out what's in a file and how it's all laid out requires
some 'legwork'; that is, you may have to open the file and bring in the data without using Excel
and simply examine it to see what's what within it.
When querying databases you will probably have some guidance from those who created the
database and maintain it as to what tables and fields within those tables you are going to need to
reference to get what you want from it. This takes us into the realm of SQL (Structured Query
Language) and that's definitely beyond the scope of this book!
54B USER PROVIDED DATA
Working with data provided "on the fly" or in "real time" from the end user is almost an art. You
cannot EVER be certain that they'll provide the information you've requested in the form that
you need it or that it will even be the same kind/type that you asked for! User input data is
almost always in dire and desperate need of data validation before using it.
In VBA code the InputBox$() function is coded as shown below. For this example we are going
to ask the user to enter what we plan on using as a starting balance for a worksheet that is set up
to act as a checking account program of some type. So we are expecting a numeric input that we
will want to use as money (Currency).
Sub GetACurrencyEntry()
Dim dataAccepted As Boolean ' a flag to tell us when we think the input is good
Dim userInput As Variant ' use variant to accept any type of entry the user may provide
Dim acceptedInput As Currency ' we will store the validated/accepted amount in this variable
dataAccepted = False ' initialize to remain in the loop until a good entry is made
Do Until dataAccepted ' implied test of dataAccepted = True
userInput = InputBox$("Enter the Starting Balance for the account:", "Starting Balance", 0)
If IsNumeric(userInput) Then
'looks ok, at least it starts with numbers
dataAccepted = True ' so that we will exit this loop
Else
'oops, not looking very good
MsgBox "Please enter a dollar amount to continue..."
End If
Loop
acceptedInput = Val(userInput) ' get the numeric value of the validated/accepted entry
'... continue on to use acceptedInput in your code
End Sub
As you can see, we've set up a loop to keep asking the user for some numeric entry until we get
one from them. We use the Boolean flag, dataAccepted, to tell us when we think it is alright to
use what they entered later on in our processing.
dataAccepted = False ' initialize to remain in the loop until a good entry is made
Do Until dataAccepted ' implied test of dataAccepted = True
userInput = InputBox$("Enter the Starting Balance for the account:", "Starting Balance", 0)
If IsNumeric(userInput) Then
'looks ok, at least it starts with numbers
dataAccepted = True ' so that we will exit this loop
Else
'oops, not looking very good
MsgBox "Please enter a dollar amount to continue..."
End If
Loop
acceptedInput = Val(userInput) ' get the numeric value of the validated/accepted entry
'... continue on to use acceptedInput in your code
End Sub
You're probably going to ask "Well, teach, what do we do if userInput = ""?" My answer is "that
depends". It depends on how you want to handle it. You could toss up a prompt asking if they
wish to continue and put up the dialog again or you could put the default value of 0 into variable
userInput just as if they'd clicked [OK] or you might even ask them if they want to quit futzing
around with their checkbook for now and if so, shut down so they can restart everything later on.
ThisWorkbook.Worksheets("SysSheet").Range("A2") = "Client:"
ThisWorkbook.Worksheets("SysSheet").Range("B2") = Me!txt_ClientCompany
End Sub
Although I did not have to be as specific as I have been in this code, it definitely tells exactly
what to do with what:
ThisWorkbook. is optional usually. However since the person may be working on several
quotations in several workbooks, I use ThisWorkbook to tell VBA that I mean the worksheet
named SysSheet that exists in the same workbook that this code is being executed in.
Similarly, the Me! associated with the names of the two text boxes used in the example tells
VBA not to be confused by any other forms that may be open or any text boxes that it may see
laying around that have those same names.
Some of you may ask to please explain a little about how controls like the ComboBox,
checkboxes and option buttons in the first userform are referenced or tested in code. So I'll hit
them each quickly and then we'll move on.
Checkboxes and Option Buttons usually have one of two possible conditions: TRUE (has an x or
check in it or the button has a dot in the middle) or FALSE (checkbox is empty and same for the
circle of the option button). So you can write code like this:
If checkboxIncludeLadder = True Then
or
If optionButtonChoose1HPEngine = True Then
and take appropriate action based on the results of those kinds of tests.
As for the ComboBox, it has a couple of properties that can be used. You can use its .Text
property to get whatever selection was made in it verbatim. Or you can use its .ListIndex
Data Sources Page 39
Copyright © 2008 by J.L.Latham, All Rights Reserved.
Programming In Excel VBA by J.Latham
An Introduction Microsoft Excel MVP 2006-??
property to find out which item in the list was selected. The ListIndex values start at zero, so if
ListIndex = 0 it means that they chose the first item in the list. If they did not choose an item in
the list, the ListIndex value is a negative 1 (-1).
So How Do I Display or Remove a UserForm from the Screen?
To present a userform on the screen, you .Show it. Somewhere in your code you'll need a line
that uses the name of the form that you give it during design along with the .Show method, as:
UserForm1.Show
or
GetCustomerInformationForm.Show
You can simply write a macro to do it if you need to:
Sub ShowCustomerInfoForm()
GetCustomerInformationForm.Show
End Sub
There are two ways to remove a form from display. The code I presented earlier uses
Unload Me
which completely removes the form from memory. This has the side effect of also removing all
information that was entered into it at that time. I could write that line as Unload Me because it
was executed from within the form's code module. If I had needed to do that from some other
section of code I could have written it as:
Unload GetCustomerInformationForm
But you can simply hide the form from view which keeps it in memory and retains the
information that was last placed on it. Two ways of doing that:
First, from within the form's own code segment:
Me.Hide
Second, in some other code segment
GetCustomerInformationForm.Hide
And that's how you deal with UserForms. That is not to say that it is all that can be done with
forms and controls on them. Remember that this is an Introduction to things, not a definitive
bible covering every aspect of every possible command, object, function and feature in VBA or
Excel. I actually used different code in my project to move the data from the form onto the
worksheet, but what I wrote above will work and hopefully was easy for you to understand at
this point in the tutorial.
Ok, this one is more my project than yours – there’s no work for you to do except examine the
code and observe the results. The project consists of two workbooks:
Project01_WB01.xls and Project01_WB02.xls
They are available by clicking the appropriate link (right-click and choose Save Target As) on
this page:
http://www.jlathamsite.com/LearningPage.htm
TUH UTH
The code is all in Project01_WB01.xls (WB01) while the other workbook, WB02, contains data
that we want to move into WB01. There are three text boxes on the first sheet of WB01 that are
associated with VBA code. The first one activates a macro that was recorded while individually
copying each of the data items from WB02 into the 3rd worksheet in WB01.
P P
To observe the difference in performance between the recorded macro and the custom code in
WB01, first try clicking the “Step 2” button. The object at this time is to simply see how long it
takes to copy a total of 167 entries from the WB02 into WB01. Obviously, both workbooks
must be open for this to take place.
The Step 2a and Step 2b ‘buttons’ each run a version of custom written VBA code to achieve the
same results. The only difference between the two procedures is that one of them has a slight,
but probably not humanly noticeable speed advantage over the other. But they definitely have a
visible speed advantage over the recorded macro.
Other things to notice when examining the code in WB01 is that the recorded macro is absolutely
not robust or versatile: add another item of information in WB02 and it won’t get copied over
into WB01; delete an item that’s already in WB02 and you end up with a ‘hole’ in the
information transferred over into WB01.
So now we see that not only is the custom code faster and more compact than the recorded
macro, but it is also more robust. It needs no further attention or maintenance no matter what
changes you make to the information in WB02.
The custom written VBA code demonstrates how to use objects in VBA to reference information
in an entirely separate workbook, and can easily be adapted to work for you with the same
workbook or across more than just two workbooks.
Often you don’t have the luxury of working with another Excel file. But many applications have
the ability to either be saved as, or to export their information to what is known as an ASCII text
file. You’re probably used to seeing them as .TXT files and they can be opened and read easily
with a program such as Microsoft’s Notepad. Sometimes they are rather specially formatted
ASCII files that you see as .CSV files. CSV stands for Comma Separated Values. Actually
several different characters may be used besides a comma to separate groups of values, but the
name from the original use of the comma has stuck with them. Excel has built-in features to
import data from .CSV files, but other text files may not conform to those standards and you may
want to import those into Excel and nothing but custom code will do the trick for you.
Ok, this one is more my project than yours – there’s no work for you to do except examine the
code and observe the results. The project consists of one Excel workbook and a text file with
sample data in it:
Project02.xls and Project02DataFile.txt
They are available by clicking the appropriate link (right-click and choose Save Target As) on
this page:
http://www.jlathamsite.com/LearningPage.htm
TUH UT
There are some useful snippets of code to take note of and possibly save for reuse. The module
named GetFilenameCode contains a routine that opens up the file browser window and will
return the full path and name of a file you select to the calling routine. This is definitely handy,
reusable code. I blatantly plagiarized that code from
http://www.cpearson.com/excel/GetFileName.aspx
No sense in reinventing the wheel unless you figure a way to make it turn faster and easier.
Chip's website, and others, provide fantastic resources like this at no cost to the user. But I do
believe that credit is always due to the benefactor, so Chip gets the plug from me along with my
gratitude for providing the code.
Within the ReadTextFileCode module, in the ReadATextFile process, there is definitely one line
that deserves some detailed discussion:
ActiveSheet.Range("A" & Rows.Count).End(xlUp).Offset(1, 0) = oneTextLine
The ActiveSheet is the one sheet that is currently selected in Excel. There can only be one
ActiveSheet at any given time.
The .Range(“A” & Rows.Count).End(xlUp) portion of the command says look in column A
beginning at the last possible row and go up the column until you find the end of cells that match
the general character of that cell. The ‘general character’ being either empty or not empty. The
assumption here is that the last cell in the column is empty, so the command is going to find the
last cell in the column that is not empty. If the entire column is empty, it will return 1 for “the
first row is the end of this section”.
The .Offset(1, 0) portion says that once you’ve found the end of the list, move down 1 row in the
same column. So this points at the next empty cell in the column, or if the column is entirely
empty, it points to row 2 of the column.
I've already mentioned a big one: speed. Performance improves dramatically when you
reference these 'in-memory' objects than if you use more direct methods of coding to work with
them.
By working with the objects in memory, you often prevent having to select different sheets and
cells on them and display the updated data - this alone is a big time saver because updating the
displayed workbook/worksheets/cells is a big time user.
You don't have to actually physically "select" an object to work with it! You may even make
reference to worksheets that are hidden and to the data on them without having to unhide it and
select it and then start selecting cells one by one or in groups on that sheet. Consider the
following code:
The following is actually an example of the way I once worked through columns of data on
worksheets in my earlier days of programming Excel. Before I learned of the wonders of using
Objects. This code simply looks in column A of a sheet until it finds an "X" (or "x") in that
column, or until it encounters an empty cell. It presumes that there are no empty cells in column
A until the end of the list.
Sub Find_X_InColumnA_OnSheet1()
Const SeekValue = "X"
Dim startTime As Date
Dim endTime As Date
Application.ScreenUpdating = False
Set myTestSheet = ThisWorkbook.Worksheets("Sheet1")
myTestSheet.Cells.Clear ' delete any info on the sheet
Set baseCell = myTestSheet.Range("A1")
For LC = 65 To 90 ' values for A to Z
For IL = 1 To 1000 ' 1000 rows worth of each letter
baseCell.Offset(rowOffset, 0) = Chr$(LC)
rowOffset = rowOffset + 1
Next
Next
Set baseCell = Nothing
Set myTestSheet = Nothing
End Sub
GPP #2: Use Application.ScreenUpdating = False to improve performance. This command tells
Excel to hold off on actually sending updated data/changes to the screen. I've seen the use of this
command improve performance as much as 10 times without any other changes to the code at
all. Think about it: work done in 1 second instead of 10, or even 1 minute instead of 10 minutes.
Application.ScreenUpdating = False is almost a 'set it and forget it' command: When the end of
your Sub is encountered, Excel will automatically turn screen updating back on without any
action or code from you at all. Within a Sub it will remain in effect until you either exit the Sub
or you give a Application.ScreenUpdating = True command.
There's one catch to that automatic reset of screen updating - if your Sub calls other Subs, then it
will be turned back on when one of the other Subs exits unless you remember to set it back to
False after making the call(s).
'this Set will assign the range from A1 down to the last row in column A
'that has any entry in it. We don't have to worry about empty cells in
'the middle of the list any more!
Set seekInRange = myTestSheet.Range("A1:" & _
myTestSheet.Range("A" & Rows.Count).End(xlUp).Address)
'now we work through the individual cells in memory
For Each anyCellInSeekInRange In seekInRange
If Trim(UCase(anyCellInSeekInRange)) = SeekValue Then
'remember the address of the cell with the X in it
foundAtCell = anyCellInSeekInRange.Address
Exit For ' we found first "X" or "x"
End If
Next
endTime = Now()
'because we didn't update the screen, the current active
'cell is not 'visible', so we need to pull it up into view
Application.Goto Range(foundAtCell), True
MsgBox "It took " & Format(endTime - startTime, "ss") & " seconds to find X at " & foundAtCell
End Sub
I hope that all of this convinces you of the advantages of working with Object references to
objects in Excel. If it doesn't, then you probably might as well stop reading right here, because
you are going to see a lot more of them as we continue onward.
Programming With Excel Objects Page 48
Copyright © 2008 by J.L.Latham, All Rights Reserved.
Programming In Excel VBA by J.Latham
An Introduction Microsoft Excel MVP 2006-??
Keep in mind that any object that you can work with directly in VBA can be referenced by one
of these "in memory object references". This includes things like various shapes, controls,
queries, charts, chart elements, etc. But the end result of it all is that modifications you make to
those in-memory object representations are applied to the actual "see it on the screen" object they
represent, or to the unseen object (as hyperlinks or queries) in the workbook.
THE EXCEL OBJECT MODEL AS A REFERENCE
62B
So how do you learn to reference these objects or what their 'family' (technically a 'Collection' in
Excel) is? There are a couple or three of ways to do that. One of the more direct methods is to
use the Excel Object Model as a reference. So, where the heck is it at?
Excel gives you the ability to assign a 'meaningful name' to a cell or group of cells (each of
which is known as a range in VBA). Assigning a name is easy to do:
Step 1: choose the cell or group of cells to be named,
Step 2: enter the name for the range in the 'Name Box' and press [Enter]
Next simply click inside of the Name Box to get ready to assign a
name to cell B2.
Finally, type in the name 'TaxRate' and press the [Enter] key.
NOTE: you must terminate the name entry with the [Enter] key. If
you don't, then the name is not accepted by Excel as a name.
After this is done, you can now refer to the contents of cell B2 on this sheet using its TaxRate
name. For example, you could refer to it in a formula in the workbook like this:
=1.99 * TaxRate
and the cell would show the result. Assuming there is a value of 0.875 in B2/TaxRate, then the
formula would return $0.17 (also assuming the cell with the formula in it formatted to display
currency).
You can also assign a name to a range of cells to make referencing the group easier and
'maintenance free' in your formulas and other worksheet functions.
Normally when you use a list of entries in a group of cells as the source for Data Validation
controlled cell entry, the list must be on the same worksheet with the cell using it as its list. But
if you have given a name to a list of cells, that list can be on another sheet in the workbook. This
gives you the ability to put several lists on a worksheet that you can even keep hidden.
See the VB Help topic for SORT for all the details.
In setting up for a sort you need to keep in mind that you will be sorting a range of cells, and that
the various sort keys must also be ranges or references to ranges.
The setup – the variables we will need (or just want) get declared first:
Setup for single field (column) sort, which will sort an area that includes A1 to F1000 on Sheet1.
Row 1 contains labels (headers) and we will sort in ascending order based on column C.
Dim myWorksheet As Worksheet
Dim theSortRange As Range
Dim theSortKey as Range
Set myWorksheet = ThisWorkbook.Worksheets(“Sheet1”)
Set theSortRange = myWorksheet.Range(“A1:F1000”)
Set theSortKey = myWorksheet.Range(“C1”)
theSortRange.Sort Key1:=theSortKey, Order1:=xlAscending, Header:=xlYes, _
OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _
DataOption1:=xlSortNormal
Note: the ‘DataOption#” parameter is only valid in Excel 2003 and later versions. Leave it
off of the command if the sort will be used in an earlier version [it will still work in 2003
and later without it]
Setup for three field (column) sort, which will sort an area that includes A1 to F1000 on Sheet1
where row 1 contains labels (headers) and we will sort in ascending order based first on column
C, then on column A and finally in descending order of column F.
Dim myWorksheet As Worksheet
Dim theSortRange As Range
Dim theSortKey1 as Range
Dim theSortKey2 as Range
Dim theSortKey3 as Range
Set myWorksheet = ThisWorkbook.Worksheets(“Sheet1”)
Set theSortRange = myWorksheet.Range(“A1:F1000”)
Set theSortKey1 = myWorksheet.Range(“C1”)
Set theSortKey2 = myWorksheet.Range(“A1”)
Set theSortKey3 = myWorksheet.Range(“F1”)
theSortRange.Sort Key1:=theSortKey, Order1:=xlAscending, Order2:=xlAscending, _
Order3:=xlDescending, Header:=xlYes, OrderCustom:=1, OrderCustom2:=1, _
OrderCustom3:=1, MatchCase:=False, Orientation:=xlTopToBottom, _
DataOption1:=xlSortNormal, DataOption2:=xlSortNormal, DataOption3:=xlSortNormal
There are a couple of ways to modify what we just did to find the first empty cell in the column
of data.
Method #1: Take the value of lastRow and add 1 to it. That would be the row number of the next
available empty cell in the column.
Method #2: make the addition part of the statement itself.
lastRow = ThisWorkbook.Worksheets(“SheetName”).Range(“A” & Rows.Count).End(xlUp).Row + 1
You can even modify the statement with the .Offset() option to do it:
lastRow = ThisWorkbook.Worksheets(“SheetName”).Range(“A” & Rows.Count).End(xlUp).Offset(1, 0).Row
In this case you may have a column of data that has empty cells in it and you want to find the
first row with an empty cell in it. Hopefully it is obvious that if there are no empty cells in the
data list that the first empty cell would be the one just below the last entry in the list. The
command looks much like our previous command except that it looks down from row 1 in the
column:
Dim firstEmptyCell As Long
firstEmptyCell = Worksheets(“SheetName”).Range(“A1”).End(xlDown).Row
Enough about finding those particular unique entries in a column. Now we’ll look at doing
much the same thing for rows.
me to pretty much stop providing code examples, scratching my head trying to think up code that
you might find useful. Instead, the remainder of this document consists of links to various
absolutely excellent examples of VBA for Excel coding. In some cases, such as Chip Pearson’s
site, I’ve copied the table of contents with links to various Excel solutions on the sites. You can
follow those links to those code solutions.
CONSOLIDATING DATA IN A WORKBOOK
69B
One of the best sources of code that may be used to combine data from several worksheets and
even workbooks can be found at Ron De Bruin’s site:
HTUhttp://www.rondebruin.nl/copy2.htm UT
While you can use Data Auto-Filter to remove rows from view, sometimes it's easier to just hide
the rows with code. You need to know what condition you want to use to choose rows to be
hidden and what column values meeting the condition can be found.
Let us say that you want to hide all rows that do not have a value entered into column R.
Perhaps a row's data represents values for quantities of a product produced on certain dates and
you want to see all products that were produced on the date contained at the start of column R.
Hiding rows with no entry in column R would clean up the list for you.
Here is the code that would do the trick for you.
Start by UNHIDING all rows! This will make sure that only the rows you mean to hide will be
hidden at the end of the process, with no left over hidden rows from other similar actions taken
on other columns:
ActiveSheet.Columns("R:R").EntireRow.Hidden = False
Actually you can pick any column! I just chose to use R since R is the column we are about to
examine for empty cells to determine whether to hide a row or not.
Sub HideColumnRRows()
Dim testRange As Range
Dim anyCell As Range
ActiveSheet.Columns("R:R").EntireRow.Hidden = False
Set testRange = ActiveSheet.Range("R1:R" & _
ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row)
For Each anyCell in testRange
If IsEmpty(anyCell) Then
anyCell.EntireRow.Hidden = True ' Hide this row!!
End If
Next ' end of anyCell loop
Set testRange = Nothing ' release resource back to the system
End Sub
Unhiding Rows
102B
I've already given away this secret because we started off our Hide Rows routine by unhiding all
rows. But we will put it in a sub by itself anyhow. Just remember that this will NOT unhide
rows that are hidden because of data filtering - they are hidden in a different manner and will not
be unhidden with this code.
You can pick any column on the sheet, since any column includes all rows. For convenience
sake, it's probably easiest to simply use column A.
Sub UnhideAllRows()
ActiveSheet.Columns("A:A").EntireRow.Hidden = False
End Sub
We have a simple looking routine but it isn't working for us. Unfortunately the programmer
wasn't very generous with comments, and now we need to try to figure out just why it isn't
working for us.
Option Explicit
Public Const intRaiseToPower = 2 ' squared
Sub SquareANumber()
Const getRow = 2
Const getCol = 1
Const putRow = 2
Const putCol = 2
This tells us that we are trying to perform some operation that requires some specific 'Type' of
constant or variable, but what we are trying to use is not one of them and Excel could not trick
What you want to do at this point is to click the [Debug] button. Excel will then automatically
open the VB Editor (VBE) and even show you the line of code that it thinks is causing the
problem. NOTE: For some problems, Excel can get confused and point to the wrong line of
code. But that's something to cover on another day.
When we click the [Debug] button, we get this display:
Excel has pointed out the line of code that it feels there is a problem with, now it is up to us to
figure out the details.
We probably need to answer 2 or 3 questions on the way to determining the exact problem:
#1 - what sheet is the "ActiveSheet". For experienced users, this is an easy question to answer,
but if it was some object set to represent a sheet that might be hidden from view or not currently
selected, we need to know which sheet we should be examining.
An important tool you'll need to help pin the problem down and come up with a fix is the
Immediate window of the VBE.
You can do a lot in the Immediate window: examine values, determine addresses, set values and
even issue some commands to Excel itself. For now we want to find out what sheet we are
getting a value from, so we type the following into the Immediate window and press the [Enter]
key at the end of it:
? ActiveSheet.Name
The ? is a shortcut entry for "Print" or "Show me..." and is a holdover from the very early days of
the original BASIC interpreters.
The name of the ActiveSheet is revealed to us as: Sheet1. So at least now we know what sheet
to look at, but where on that sheet do we need to be looking? We know that we should be
looking at Cells(getRow, getCol). But where the heck is that? Once again, it is the Immediate
window to the rescue. We can get it to show us the address of that cell by typing:
? Cells(getRow, getCol).Address
and pressing the [Enter] key.
By the way, you can copy from the code window into the Immediate window, which can help
prevent typos from interfering with your debugging efforts.
And there we see a problem: Cell A2 holds some text, and since we declared intMyNumber to be
type Integer, and so a text value cannot be assigned to a numerically typed variable - and there
lies the answer to why we got "Error 13: Type Mismatch" when trying to use the Sub.
Now it is up to you to determine why someone typed text into a cell you were expecting to find a
number into (or realize that you should not type text into a cell that is going to be used for some
math processing). The Debugger has done about all it can for you, what you do to prevent the
problem in the future is a decision you have to make yourself.
OTHER DEBUGGING TIPS:
73B
Tip #1: You can quickly determine certain values right in the code window by simply moving
the mouse pointer/cursor over a constant or variable name and its value will be displayed as a
popup tip:
Or you can simply hit the [F5] key which will bring up the error message again and you
can click the [End] button on it.
You do that by clicking in the area to the left of the beginning of a line of code. The dark red dot
and highlighting will indicate that a breakpoint has been set. You can remove it later by clicking
the dark red dot again, or use the [Debug] option in the menu to clear them all:
Another way to achieve much the same thing is to insert the Stop statement into the code where
you want it to break into debug mode. Simply type the word Stop on a line by itself in the code -
just don't forget to delete it after your debugging is completed.
Once you have halted the code where you want to, you can press the [F8] button to then single
step through your code and examine values and processes along the way to the problem line of
code. When you are ready to let the code run normally again during your debug session, press
the [F5] key - or you can terminate the execution using the [Reset] button and start all over
again.
You'll notice in the last screen shot that there are several ways of controlling what pieces of code
are executed associated with the [F8] and [F9] keys. They can all help in your effort to
determine the source of a problem, or just to go through code to see how it works.
You can find a more complete list of many Excel MVP websites here:
http://www.mvps.org/links.html#Excel
HTU UT
And if you go to the top of that page, you can look through the list for websites belonging to
MVPs in many areas:
http://www.mvps.org/links.html
HTU UT
http://www.rondebruin.nl/tips.htm
HTU UT
Excel 2007
T T
Filtering by the Active Cell's Value, Font Color or Fill Color in Excel 2007
HTU U T TH
VBA code examples for Tables in Excel 2007 or a List in Excel 2003
HTU UTH
Add buttons to the QAT and customize the images of the buttons
HTU UTH
Merge cells from all or some worksheets into one Master worksheet
HTU UTH
Copy every TXT or CSV file in a new worksheet of a newly created workbook
HTU UTH
Copy a range from closed workbook (Local, Network and on the internet)
HTU U T TH
Copy records with the same value in a column to a new sheet or workbook
HTU UTH
VBA code examples for Tables in Excel 2007 or a List in Excel 2003
HTU UTH
Delete/Hide/Disable examples
T T
Zip file or files with the default Windows zip program (VBA)
HTU U T TH
Unzip zip file or files with the default Windows zip program(VBA)
HTU UTH
Weeknumber/Dates
T T
Week numbers
HTU U T HT
Help information
T T
Help Context IDs for Excel 2000, 2002, 2003 and 2007
HTU UTH
Other pages
T T
WWW.CONTEXTURES.COM
T76BHU
T7BHU
HTU UTH
Jun-07
Advanced Filter - Different Sheet video
HTU UTH HTU UTH
Functions
HTU UTH
AutoFilter - Basics
HTU UTH
Functions -- Count cells
HTU UTH
AutoFilter - Programming
HTU UTH
Functions -- INDIRECT 11-Nov-06
HTU UTH
B
G-M
Bar over character
HTU UTH 31-Oct-06
GetPivotData
HTU UTH 23-Jan-09
Blog, Contextures
HTU UT
09 Video
HTU UTH
Books -- on my bookshelf
HTU UTH
INDEX Function
HTU UTH
Keyboard Shortcuts
HTU UTH
Charting Links
HTU UT
Combining Data
HTU UTH
22-Feb-09
Names -- Use Names in Formulas 17-Jun-05
HTU UTH
Comments - Basics
HTU UTH
Navigation Toolbar for Sheets 2003 21-Dec-05
HTU UTH
http://www.contextures.com/xlDataEntry0
UTH
video
http://www.contextures.com/xlcomments03.ht 4.html 18-May-08
HTU UTH
HTU
UTH UTH
28-Jan-06
Comments - Number and List 22-Jan-06
HTU UTH
Order Form
HTU UTH 30-Jul-05
Comments - Printing
HTU UTH
Comments - Programming
HTU UTH
P
Comments - Resize
HTU UTH
http://www.contextures.com/Pubn03.htmlPivot UTH
HTU UTH
Conditional Formatting - Shade Alt Rows 14-Feb-07 Pivot Tables - Add-in -- Pivot Power 29-Apr-05
HTU UTH
HTU UTH
Conditional Formatting - Filtered Bands 23-Feb-07 Pivot Tables - Clear Old Items video updated 27-Jun-08
HTU UTH
HTU UTH HTU UTH
Conditional Formatting - Coloured Shapes 22-Jun-07 Pivot Tables - Create in Excel 2007 video 19-Feb-09 HTU UTH HTU UTH
http://www.contextures.com/xlPivot06.html
HTU UTH
HTU UTH
Contextures Blog
HTU UT
http://www.contextures.com/xlPivot10.htmlPiv
HTU UTH
Count Cells
HTU UTH
Pivot Tables - Data Field Layout video
HTU UTH HTU UTH
video
HTU UTH H
Pivot Tables - Multiple Consolidation Ranges
HTU UTH
List 15-Jul-05
Q-R-S
UTH
05 Running Totals, Pivot Tables video 13-Sep-08 HTU UTH HTU UTH
Shortcuts, Keyboard
HTU UT
Sorting a List
E
HTU UTH
Excel Links
HTU UTH
Sum a Filtered List
HTU UTH
Excel Sites
HTU UTH
Excel Store
HTU UTH
Survey Form
HTU UTH 29-Oct-05 updated 11-Oct-06
Excel Table 21-Aug-08
HTU UTH
F
Table, Excel
HTU UTH 21-Aug-08
07
FAQs, Excel - Pivot Tables and Pivot Charts 09-Oct-
http://www.contextures.com/xlToolbar01.html
HTU UTH
06 HTU UT
http://www.contextures.com/xlfaqFun.htmlFA
HTU UTH
Filter, Advanced
HTU UTH
Filter, AutoFilter
HTU UT
Video Index
HTU UTH H
A M
Absolute And Relative Cell References
HU
VBA Code
Add-Ins, Automation, Creating
HU Macros, As Opposed To Functions
HU
Enabled, Technique 2
(Calculations With Errors)
Add-Ins, Installing And Loading
HU Macros, Running From Worksheet
HU
Cell
Add-Ins And Utilities, Third Party
HU Matrix To Vector Formulas
HU
Age, Calculating
HU Maximum Values, Persistent
HU
instance of a class
Analysis Tool Pack (ATP), Installing
HU Menu Items, Creating Manually
HU
Code
AnyXML, Allowing optional and arbitrary XML
HU Menu Items, Creating For The
HU
Application Events
HU Minimum And Maximum Values
HU
Persistent
Application-Level Names
HU Missing References In A VBA
HU
Project
Arguments, Passing ByVal And ByRef
HU Modified File, Returning The Most
HU
With Code
Array, Converting To Columns
HU Modules, Adding descriptions for
HU
Months
Array, Testing If Sorted
HU Most Or Least Common Entry In A
HU
List
Arrays, Determining Data Type Of
HU Moving A Form With The Window
HU
Arrays, Reversing
HU Named Ranges
HU
Arrays, Sorting
HU Named Range Box, Increase The
HU
Size Of
Arrays Of Objects, Sorting
HU Named Range Box, Shortcut
HU
Keystroke
Arrays, Utility Procedures For
HU Nested Function, Exceeding Limit
HU
Browser
Automatically Closing A Workbook After Idle Time
HU Newsgroups, Connecting To
HU
Posters
Averaging Values In A Range
HU Newsgroups, Problems Posting To
HU
B
Banding, Color Banding With Conditional Formatting
O
HU
Blinking Text
HU Objects, Connected And
HU
Disconnected
Bracket Pricing, Formulas For
HU OnTime Method In VBA
HU
Function
ByRef and ByVal Parameter Passing
HU Optional And Arbitrary XML
HU
setting
Case, Converting Text To Upper or Lower Case
HU
Function
ByVal
Cell Values And Displayed Text
HU Parameters, Optional Parameters
HU
To A Function
Cells, Referring To Cells In Another Range
HU Passing Parameters ByRef And
HU
ByVal
CellView Add-In
HU Parent Windows, With Userforms
HU
From Procedures
Characters, Counting In A String
HU Passwords, Forgotten
HU
Custom
Circular References, Example
HU Pivot Tables, An Introduction
HU
Class Modules
HU Positioning UserForms To Cells
HU
Shapes
Class Names, Window Class Name Of Office
HU Preventing Duplicate Entry
HU
Applications
Classes, Default Member Of
HU Previous And Next Worksheets
HU
Clipboard, Windows
HU Printing Cell Comments To Word
HU
Cloning A Folder
HU Pricing, Progressive And Bracket
HU
Code Modules
HU Procedure Attributes For The
HU
Object Browser
Code And Formula Usage, Legal Conderations
HU Procedure Name, Automatically
HU
Code Modules
HU Progress Bar, Displaying while
HU
running code
Collections And Dictionaries, Procedures for,
HU Proper Case, Converting Text To
HU
Colors, Sorting By
HU Quarter, Determining From Date
HU
Function
Column Or Row From Table Conversion
HU
VBA
COM Add-Ins, Installer
HU Randomize The Order Of
HU
Elements In An Array
COM Add-Ins And Automation Add-Ins, Installing
HU Ranges, Converting To Column
HU
Another Range
Concatenating Strings, a better method than
HU Ranking Data In List (and
HU
Techniques
Conditional Formatting,Using Cells On Other Sheets
HU Recursive Code, Illustrated With
HU
Folder
Converting A Table To A Column Or Row
HU References, Setting To VB
HU
Projects
CTRL, SHIFT and ALT, Testing State Of Key
HU References, Missing References
HU
In A VBA Project
Copyright And Trademark Usage of contents of this
HU Registry, Functions For Working
HU
Component
Counting Cells With A Specific Content Returning Every Nth Value In A
HU
References
Counting Characters In A String
HU Returning Arrays From User-
HU
Defined Functions
Counting Words In A Cell Or On A Worksheet
HU Reversing A Range Of Cells
HU
Records
Custom Document Properties, Reading And Writing
HU Rounding Errors And Precision
HU
single row
Dates, Adding And Subtracting
HU RSS Feed, Get What's New
HU
Dates, Julian
HU UH Scheduling Procedures With
HU
Procedures
Day Of Week, Returning Nth, Day Of Week In A
HU Screen Flicker When
HU
To Sequence
Days In Month, First And Last Days In Month
HU Selection, Removing Active Cell
HU
Or Active Area
DATEDIF Function
HU Series, Inserting Cells And Filling
HU
A Series
Debugging VBA Code
HU Series, Finding A Series Of Cells
HU
UserForms
Defined Names In Excel
HU Shading Cells
HU
State Of Key
Deleting Duplicate Rows With Advanced Filter
HU Shortcut Keys
HU
Array
Desktop, Getting Folder Name Of
HU Shutdown, Detecting And Acting
HU
Sorting
Directories, User Specific
HU Sorted, Testing If An Array Is
HU
Sorted
Directories, Creating A Tree List
HU Sorting By Cell Color
HU
DirTree Add-in
HU Sorting Arrays Of Objects
HU
Dictionaries
Distinct Items In Lists
HU Sorting Worksheets
HU
Of
Distinct Values VBA Functions, Returns Array Of
HU Standard Time And Daylight
HU
Downloads
HU Strings, Most Or Least Common In
HU
A Range
Document Properties, Reading Modifying In Both
HU Strings, Concatenating With
HU
Digits
Duplicate Entries, Preventing
HU Strings, Fixed Length
HU
Dynamic Ranges
HU Strings, Shortening With
HU
PathCompactPathEx
Strings, General Formulas
HU
Creating
Easter, Date Of
HU SUMIF, Multiple Criteria
HU
Interior Color
Element Common To Two Lists
HU Summing Every Nth Value
HU
Emptying A Folder
HU Support, Getting Support For
HU
Excel
Enum Data Type
HU Symbols, Using special symbols
HU
with Excel
Ensuring Macros Are Enabled, Technique 1
HU
Err.LastDllError property
HU Tables, Lookup Functions For
HU
Tables
Errors, Diagnosing Startup Errors
HU Table, Converting To Row Or
HU
Column
Error Handling
HU Table, Creating A Table From A
HU
Events
Events, Application
HU Text Files, Importing And
HU
Exporting
Events, Suppressing In UserForms
HU Text Files, Importing Files With
HU
only input
Extension, File extensions and the Hide Extensions
HU Thanksgiving, Calculation Of Date
HU
setting
"This" reference is "Me" in
HU
VB/VBA
TimeBombing A Workbook
F
HU
Standard
File Attachments In Newsgroups, Why Not
HU Times And Working Hours,
HU
Formulas
FindAll XLA Add-In
HU
setting
First And Last Names, Extracting From A String
HU Unique Entries, Counting
HU
Upper Case
Folder, Browse For
HU Usage And Distribution Of Code
HU
And Formulas
Folder, Deleting Contents
HU User Defined Functions (UDFs) In
HU
VBA
Folder, Creating An Exact Copy
HU User Defined Functions,
HU
Arrays
Folders, Creating A Tree List Of Subfolders And
HU Used Cells In A Range
HU
Files
Folders And Files In A TreeView Control
HU User-Specific Folders
HU
Windows
FormatMessage, Getting API Error Messages
HU UserForms, Positioning To Cells
HU
Determined At Run-time
Forms, Moving With Windows
HU UTC And Local Times, And
HU
time
Formula Bar, Shortcut To
HU
Fractional Arithmetic
V
HU
Called
Function Libraries As Automation Add Ins
HU Variables, Scope And Visibility
HU
In VBA
Functions, As Opposed To Macros
HU VBA Editor, Automating The VBA
HU
In A VBA Project
Vectors And Matrices
HU
Versions Of Excel
G
HU
Functions For
Games For Excel
HU Visual Basic For Applications
HU
(VBA), Optimizing
GetInfo UDF
HU VLOOKUP - A Better Way
HU
Modules
GetLastError Windows API Function
HU
GetSystemErrorMessageText Function
W
HU
Grades
HU Week, First Monday Of
HU
Dates
Weekday, First And Last Of Month
H
HU
Extensions setting
Hide Extensions setting and VBA in Excel
HU Windows API Functions, Getting
HU
Error Information
High And Low Values, Persistent
HU Window Class Names Of Office
HU
Applications
Highlighting ActiveCell
HU Words, Counting In A Cell Or On
HU
A Worksheet
HLOOKUP - A Better Way
HU Words, Extracting From A String
HU
VBA
Worksheets, Referencing From
HU
Formulas
IF Functions, Nested
HU Worksheets, Sorting
HU
Loading
Internet, Downloading a file from.
HU XML, Optional And Arbitrary XML
HU
Julian Dates
HU
Z
K
Zero Values, Ignoring In Functions
HU
Keyboard Shortcuts
HU Zip File, Saving A Workbook As A
HU
Zip File
L
Last And First Names, Extracting From A String
HU
Look for the two links to downloadable Formulas and the one for downloadable Code.
Jon Peltier has premium quality knowledge of Excel Charting and Graphing and you would be
hard pressed to get better starting help on Charting with Excel from someplace other than
http://peltiertech.com/Excel/Charts/index.html
TUH UT
Long overlooked and underappreciated, Charles Williams was finally awarded Microsoft Excel
MVP status. Long overdue. His site has some really informative information, good help and
great ‘inside’ information about the way that Excel works. For the really serious, his Fast Excel
analysis tool is definitely one to have around.
This page has many links at the top regarding how Excel’s (re)Calculation engine works, and
how to make it work for you:
HTU http://www.decisionmodels.com/calcsecrets.htm UT
This page has lots of tips and information on how to speed up the performance of your
workbooks:
http://www.decisionmodels.com/optspeedh.htm
HTU UT
Need to find out more detail about the memory requirements or usage in your version of Excel?
Then check out this page:
http://www.decisionmodels.com/memlimits.htm
HTU UT
Here you will find some really useful, and FREE tools for working with Excel.
http://jkp-ads.com/Download.asp
TUH UT
get excellent information from his site without leaving your keyboard or spending any extra $.
http://spreadsheetpage.com/ John Walkenbach site’s main page.
HTU UTH
Here is the Table of Contents for his Excel Tips at the site, with some having companion files
that can be downloaded.
General
CommandBar Calculator
TUH UTH
Formatting
Formulas
Calculating Easter
TUH UTH
Naming Techniques
TUH UTH
Creating A “Megaformula”
TUH UTH
Printing
CommandBar Calculator
TUH UTH
UserForms
Displaying Help
TUH UTH
Selecting A Directory
TUH UTH
VBA Functions
Multifunctional Functions
TUH UTH
o File Exists
o FileNameOnly
o RangeNameExists
o SheetExists
o WorkbookIsOpen