0% found this document useful (0 votes)
33 views

Excel VBA Macros

This document provides an overview of using VBA and macros in Excel. It discusses recording macros to generate VBA code, editing that code to make it more efficient. Key aspects of writing VBA macros are explained, including using variables and constants, selecting specific cells, and using logical statements like IF. Examples are provided of various VBA concepts like declaring variable types, setting variable values, and performing special cell selection.

Uploaded by

sanu sayed
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
33 views

Excel VBA Macros

This document provides an overview of using VBA and macros in Excel. It discusses recording macros to generate VBA code, editing that code to make it more efficient. Key aspects of writing VBA macros are explained, including using variables and constants, selecting specific cells, and using logical statements like IF. Examples are provided of various VBA concepts like declaring variable types, setting variable values, and performing special cell selection.

Uploaded by

sanu sayed
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 63

Excellence with Excel 3.

0
Excel – VBA and Macros

Excel – VBA and Macros

This quick reference guide summarizes the lessons on VBA and macros in this course.

You don’t need to know these features for interviews, but you can save a lot of time on the job if you
know even a bit about them.

VBA is powerful because it lets you automate repetitive tasks without having to put much time and
effort into learning a general-purpose programming language.

If you already know Excel, VBA is simply an extension of its normal features.

Table of Contents

EXCEL – VBA AND MACROS 1

Getting Started with VBA: The Macro Recorder 2


Editing and Refining the VBA Code 4

The Key Components of Any VBA Macro 5


Variable and Constant Declarations 6
Special Cell Selection with Union, Intersect, and On Error 7
IF, ELSE, and ELSEIF Statements 11
“For Each” Loops 14
Arrays for Storing Sets of Values 18

More Advanced VBA Features 21


The Dictionary Object (“Hash Table”) 21
String Functions 26
Jumping To and Filling Ranges 30
ConvertFormula 36
The Table of Contents Macro: Hyperlinks, Offset, Sheets, and Msgbox 41
Charts and ChartObjects in VBA 45
User-Defined Functions (UDFs) 50

VBA Finishing Touches 53


Cleaning Up Code with Helper Functions 55
Assigning Keyboard Shortcuts to Macros 58
Exporting Macros for Use in Other Files 60

1 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

Getting Started with VBA: The Macro Recorder

If you’re completely new to VBA and macros, you should get started by recording a few macros and
then examining the automatically generated code.

To do this, make sure the “Developer” toolbar in the ribbon menu is enabled (go to Options or
Preferences and then “Customize Ribbon”), and then click “Record Macro”:

You’ll get some options to name your macro and assign keyboard shortcuts to it – Ctrl + Shift + Letter
Key is usually best – and then it will begin recording.

When you’re done recording, press “Stop Recording” in the same Developer toolbar area.

If you now open “Visual Basic” in this same area, click on the “Modules” folder, and then click on
“Module1”, you’ll see the code that was automatically generated by your actions.

In this simple example, we formatted a cell as an input box, which means that we changed the fill color
to yellow, the borders to light grey, the font color to blue, and the horizontal alignment to “center”:

Here’s the code:

2 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

This code may look intimidating, but it’s simple if you break down each part:

• Selection refers to the range of cells that you selected before you began recording the macro.

• With Selection.[Something] followed by an End With tells VBA, “Please look at a property of
this cell or range of cells and change something about it.”

For example, in the first With.Selection.Interior, VBA changes the pattern, the color of the pattern, the
fill color of the background, and a few other attributes.

The numbers used for the colors here are VBA’s internal codes.

3 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

You can expand on this example and record macros for plenty of other things: copying formulas or
constants across or down, editing formulas, or converting absolute references to relative references.

This approach works well for formatting, but it does not work well for everything.

For example, the macro recorder will not “understand” your actions when you edit a formula – it saves
the formula you type in, and it applies that same formula to every cell when you activate the macro.

Recording macros is still the best starting point for learning VBA, but to write more complex macros,
you’ll have to get comfortable Googling terms and looking up the appropriate commands.

Return to Top.

Editing and Refining the VBA Code

The automatically generated code above is quite repetitive, so it is not ideal for a real macro.

For example, we don’t need four separate “With Selection.Borders” statements; we can use just one
and apply the same style to all borders in the range.

Also, there’s no need to use separate “With Selection” statements when we could combine all these
changes into one and delete everything else.

Here’s a cleaned-up version of this code:

4 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

It does the same thing, but it’s much easier to read and interpret this way.

But this macro still has plenty of problems:

• It will format everything in the selected range of cells, which is inefficient because it should skip
empty cells.

• If the input cell has a formula rather than a hard-coded constant, it should apply a black font
color rather than blue.

• What if the user has selected an empty range of cells or some other invalid range?

• What if the code generates an error?

To fix these problems and make the macro robust, we’ll move into the next section and cover variables
and constants, special cell selection, and “IF” statements to perform logical checks.

Return to Top.

The Key Components of Any VBA Macro

To use VBA to its full potential and create macros that do more than simple formatting, you need to
know:

• How to Save/Store Data – You’ll declare constants, variables, and arrays to do this.

• How to Select Certain Types of Cells within a Wide Range – You’ll use the Union, Intersect,
and .SpecialCells commands to do this.

• How to Perform Logical Checks – As in Excel, “IF” statements also work in VBA, but the syntax
is a bit different.

• How to Loop Through Cells or Items in a Set – You will use “For Each” loops to do this.

In each section below, we’ll explain these topics and show you how to refine this “Input Box” macro
and create other, more complex macros.

Return to Top.

5 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

Variable and Constant Declarations

Variables in VBA are similar to named cells and ranges in Excel; they let you “store data” and then
reference it in code you write.

You can declare a variable with the following syntax:

Dim Variable_Name As Variable_Type

There are dozens of “variable types,” but a few of the most common ones include:

• Range – Used for both individual cells and ranges with multiple cells.
• String – Used for text or non-numerical/non-date data.
• Integer – The same as an integer in math.
• Double – Used for longer numbers with decimal places.
• Boolean – Used for True or False values.
• Date – Used for dates.
• Variant – This one can store any data, so you use it when you’re not sure of the type.

You don’t have to declare a variable as a specific type, but it’s good practice to do so because it makes
your code easier to understand and modify.

Here are examples of variable declarations:

Dim FormulaCells As Range


Dim CompanyName As String
Dim NextYear As Integer
Dim PrevRevenue As Double

Dim AvgBalance As Boolean


Dim CurrentDate As Date

Once you’ve declared these variables, you can then set most of them to different values with the
assignment operator (“=”):

CompanyName = “Walmart Inc.”


NextYear = 2030
PrevRevenue = 1031.231

6 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

AvgBalance = True
CurrentDate = “12/31/2025”

But with a Range variable, and anything else that is an Object rather than a simple number or text,
you must use the “Set” command in front of any assignment:

Dim randomCells As Range


Set randomCells = Range(“A1:A10”)

If you want to declare a constant – a number, date, string, or range of cells that can never change – you
should use the “Const” command and include the assignment in the declaration:

Const errorText As String = “N/A”

Constants are useful when you need a condition, number, or piece of text that will never change, such
as the name of a new spreadsheet the macro will insert, or the maximum numerical input.

Once you’ve declared a constant and assigned a value to it, you cannot change it anywhere in your
VBA code.

To save space, you can also declare multiple variables or constants in the same line:

Dim firstAnchorPos As Integer, secondAnchorPos As Integer, textBetweenAnchors As String

Finally, note that there are naming restrictions on both variables and constants, similar to the
restrictions on named cells and ranges in Excel:

• The first character must be a letter.


• You can’t use a space, period, exclamation mark, @, &, $, or # in the name.
• The name must be less than 255 characters.
• And you cannot use VBA “reserved keywords” in the name.

Return to Top.

Special Cell Selection with Union, Intersect, and On Error

Once you know about variables and constants, one immediately useful application is selecting certain
types of cells within ranges.

7 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

For example, maybe you’ve selected an entire schedule on your spreadsheet, but you only want to
format the cells with formulas.

To do this, you can use the .SpecialCells method of the Range object:

Dim FormulaCells As Range


Set FormulaCells = Selection.SpecialCells(xlCellTypeFormulas)

And to select only the cells with constants, you can use:

Dim ConstantCells As Range


Set ConstantCells = Selection.SpecialCells(xlCellTypeConstants)

Selection always represents the range of cells the user has selected before activating this macro, and
Selection.SpecialCells selects only certain types of cells within that range.

You can pass in two function inputs as follows:

Set FormulaCells = Selection.SpecialCells(xlCellTypeFormulas, xlNumbers)

This command will find all cells with formulas that produce numerical output in the selected range.

There are many possible inputs for the first parameter, but the most useful ones are:

• xlCellTypeBlanks – Only empty cells.


• xlCellTypeComments – Only cells with comments.
• xlCellTypeConstants – Only cells with constants.
• xlCellTypeFormulas – Only cells with formulas.
• xlCellTypeLastCell – The last cell in the range.

Possible inputs for the second parameter include:

• xlErrors – Cells with errors in them.


• xlLogical – Cells with “logical values.”
• xlNumbers – Cells with numeric values (dates or actual numbers).
• xlTextValues – Cells with text.

You can combine these inputs for the second parameter, but you cannot do so for the first one.

8 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

So, you could now write code that selects only cells with formulas that produce numeric values, and
code that selects only cells with numeric constants:

Dim numFormulaCells As Range, numConstantCells As Range


Set numFormulaCells = Selection.SpecialCells(xlCellTypeFormulas, xlNumbers)
Set numConstantCells = Selection.SpecialCells(xlCellTypeConstants, xlNumbers)

But if you try these statements in real VBA code, you’ll see that they don’t quite work as expected.

There are a few problems:

1) If you select just a single cell, the Selection.SpecialCells method will not work correctly.

2) What happens if the range of cells in Selection has no formula cells with numeric output AND
no numeric constant cells? You get an error!

3) What if the user has selected a nonsensical range, such as A1:Z10000, even though your
spreadsheet only goes from A1 to Z95?

You can fix these problems with the On Error command and the Intersect command for finding the
“intersection” of two ranges.

To fix problems #1 and #3, you could change the code above to the following:

Set FormulaCells = Intersect(Selection, Selection.SpecialCells(xlCellTypeFormulas),


ActiveSheet.UsedRange)

“Intersecting” the formula cells in the Selection with the Selection itself handles the case where you’ve
selected only a single cell.

And then intersecting both of those with the “Used Range,” or ActiveSheet.UsedRange, ensures that a
nonsensical range, such as A1:Z10000, will be ignored.

If your spreadsheet is using only A1:Z95, then that’s the maximum range for these formula cells.

To handle problem #2 – a Selection that has no formula cells and no constant cells – you can use these
commands before and after the Intersect commands:

On Error Resume Next


On Error GoTo 0

9 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

These commands tell VBA to keep executing the code even if it encounters an error.

Putting together all these pieces, here’s our Input_Box macro so far:

We declare the Range variables for FormulaCells and ConstantCells in the beginning.

Then, we set all the formatting for borders, fill colors, and alignment in the With Selection part.

Then, to use black font color for the FormulaCells and blue font color for the ConstantCells, we use
Intersect to retrieve both of them and then change their .Font.Color properties.

These “RGB” codes refer to Excel’s notation for storing colors; 0, 0, 0 indicates no colors at all, AKA
black, while 0, 0, 255 means no red, no green, and 100% blue.

A related command is Union, which “joins” two separate ranges or collections of cells together:

Dim formConstCells As Range

10 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

Set formConstCells = Union(FormulaCells, ConstantCells)

To use the Union command, we must do some error-checking first: if one of these ranges is empty or
generates an error, Union won’t work properly.

This macro is looking better, but there are still a few problems:

1. We’ve told the code to “keep going” if it encounters an error, but it still doesn’t handle the
error. We need to check for it and take different actions if one or both ranges are empty.

2. Even though we use different font colors for formula and constant cells, we’re still applying the
fill color, border, and alignment formatting to everything in the range – even blank cells.

3. And we’re not handling the case where there are no formula or constant cells in the range.

We can fix these problems with IF, ELSE, and ELSEIF statements in VBA.

Return to Top.

IF, ELSE, and ELSEIF Statements

There are IF statements in Excel, and there are very similar IF statements in VBA.

The IF statements in Excel mostly test the results of formulas and logical evaluations, and they take
different actions depending on whether the results are TRUE or FALSE.

VBA gives you more options than this: you can use a single IF structure to check for many different
conditions and give different instructions depending on which conditions, if any, are true.

The syntax is also different, and you must include a “Then” after each conditional check.

Here’s what a full IF / ELSEIF / ELSE setup looks like, using the same Input_Box macro:

11 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

The first few lines here declare the variables and then find all cells with formulas and all cells with
constants in the Selection, as explained in the previous section. The only difference is that we ignore
non-numeric constant cells now (i.e., anything with hard-coded text in it).

This line:

If (Not FormulaCells Is Nothing) And (Not ConstantCells Is Nothing) Then

Does what it says: if both these ranges have *something* in them, i.e., at least one cell in each range,
then the code will execute the set of actions right below the “Then.”

“Not Is Nothing” is a bit awkward, but that’s the only way to check for this in VBA (there is no “Is
Something” command).

The next few lines are straightforward:

Set NonEmptyCells = Union(FormulaCells, ConstantCells)


FormulaCells.Font.Color = RGB(0, 0, 0)
ConstantCells.Font.Color = RGB(0, 0, 255)

We use the Union command to join together the formula cells and constant cells into one big range of
cells, which we call NonEmptyCells.

Then, we set the font color to black for the formula cells and blue for the numeric constant cells.

12 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

If this first “If” statement evaluates to true, VBA executes the three lines of code right below it, stops,
and exits the entire structure, jumping to the “End If” at the bottom.

But if it’s not true, then VBA keeps going down and checking the other conditions here. The next one is:

ElseIf Not FormulaCells Is Nothing Then


Set NonEmptyCells = FormulaCells
FormulaCells.Font.Color = RGB(0, 0, 0)

This one handles the case where there are formula cells, but no constant cells. And then the next ElseIf
handles the case where there are constant cells, but no formula cells.

There’s a final “catch-all” Else at the end:

Else
Set NonEmptyCells = Nothing

If VBA reaches this final condition, then it means that there are no formula cells and no constant cells
in the range the user has selected.

After VBA reaches the “End If” shown above, NonEmptyCells could be nothing, only formula cells, only
constant cells, or both formula and constant cells.

Now, it’s easy to fix some of the problems discussed in the last section, such as incorrectly
formatting blank cells:

Instead of using “With Selection,” we first check whether or not NonEmptyCells has cells in it, and if it
does, we use “With NonEmptyCells” to apply the formatting only to those cells.

But if NonEmptyCells has no cells at all, then we do nothing.

13 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

With these changes, we’ve now fixed the remaining problems:

1. If something in the Intersect or Selection.SpecialCells commands generates an error, we do


nothing (the code keeps running, and NonEmptyCells is set to Nothing).

2. We skip all blank cells and apply the formatting only to cells in the Selection with formulas or
numeric constants.

3. And we’ve handled the case where there are no formula cells AND no constant cells.

You will use IF, ELSEIF, and ELSE in virtually every macro, so you must understand them if you want to
do anything substantial in VBA.

Return to Top.

“For Each” Loops

While it’s useful to select certain types of cells in the Selection, sometimes you need to go beyond that.

Sometimes, you need to loop through each cell in an area, check its formatting or contents, and then
perform different actions based on its format or contents.

We use this technique in the macros for color-coding spreadsheets and formatting spreadsheets for
printing.

In both cases, we need to loop through cells, check the types of formulas they contain, and check if the
macro has already been applied to those cells.

To do this, we use the “For Each” command to loop through each cell in a range (or each item in some
other object) and the “Next” command to move to the next cell.

Here’s how the Color_Code macro starts:

14 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

The first few lines declare all the variables (ranges of cells and one for the cell formula).

Then, we use Intersect and Selection.SpecialCells to create ranges for numeric constant cells, text
constant cells, numeric formula cells, and text formula cells.

The “On Error Resume Next” tells VBA to keep going even if one of these commands generates an
error.

To apply the proper formatting, such as blue font color for numeric constant cells, black font color for
numeric formula cells, and black for text formula cells, we loop through each range.

The example below is for the numeric constant cells:

We use the same “If Not Is Nothing” check in the beginning, followed by “For Each”.

This code will then go through each cell in the region and check its “interior color” (i.e., fill color).

15 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

If the fill color is yellow (255, 255, 153) or white (255, 255, 255), then we change the font color to blue.
Otherwise, we do nothing.

That’s because we always use the yellow fill color for input cells and the white fill color for historical
data and projections – but other fill colors, such as grey and blue, are typically used for headers:

We perform similar checks in the “For Each” loops for text constant cells and text formula cells, but the
colors are slightly different.

Numeric formula cells are more complicated. There, we also need to check for formulas that are links
to other files or links to other spreadsheets and apply the red or green font colors. Here’s the code:

16 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

As always, we check that the range contains at least one cell first (“If Not numFormulaCells Is Nothing
Then”).

Then, we loop through each cell in this range (“For Each cell In numFormulaCells”) and start by
checking the interior color.

If it’s white, we proceed with the code and retrieve the formula in the cell.

If it’s yellow, meaning it’s an input cell, then we change the font color to black.

Continuing with the “white fill color” case, next we use an If/ElseIf/Else structure to check the formula
for links to other spreadsheets and other files.

Links to other files should always have “.xls” in the formula, but the exact file extension could
be .xls, .xlsx, or .xlsm, and there might be single or double quotes involved as well.

So, we use the Like operator to check if the formula contains “.xls”, with anything before or after it,
followed by a “]”, then anything, and then a “!”:

If cellFormula Like "*.xls*]*!*" Then

The * and * characters mean “anything could be here” – we care about the .xls part in the middle.

If the formula contains a link to another file, we change the font color to red, or RGB(255, 0, 0).

If not, then we check for direct links to other spreadsheets. Excel always uses the “!” character to
indicate these links, but we only want formulas that are direct links with nothing else. For example:

=ABC!A1

But NOT:

=ABC!A1 + ABC!B2

Therefore, this formula should contain “!” but no other operators, such as \, +, -, /, %, ^, >, >=, <, <=,
<>, or &.

We use the following ElseIf structure to check for this:

17 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

ElseIf cellFormula Like "*!*" And Not cellFormula Like "*\**" And Not cellFormula Like "*+*" And Not
cellFormula Like "*-*" And Not cellFormula Like "*/*" And Not cellFormula Like "*%*" And Not
cellFormula Like "*^*" And Not cellFormula Like "*>*" And Not cellFormula Like "*<*" And Not
cellFormula Like "*>=*" And Not cellFormula Like "*<=*" And Not cellFormula Like "*<>*" And Not
cellFormula Like "*&*" Then

Once again, the * character means “anything could be here”; we only care about the one specific
character, not everything else around it.

If this condition is true, meaning the formula is a direct link, we change the font color to green, or
RGB(0, 176, 80).

The final Else statement at the end changes the font color to black if we found no evidence of links to
other spreadsheets or files.

We use nearly the same macro to format spreadsheets for printing (see the lesson), with a few tweaks
to allow the user to “toggle” print formatting off and on.

This “Color Code” macro above is not efficient because it checks for many different characters within
each formula.

We could make it more efficient by removing some of those checks, but then the macro would not
handle as many cases.

Return to Top.

Arrays for Storing Sets of Values

For formatting purposes, it’s also helpful to store sets of values in VBA.

We call these “sets of values” arrays, and each item in the array has a specific index number, such as 1,
2, or 3.

Each item in the array must have the same variable type as well. For example, you can create an array
that has 5 integers, but you cannot create an array that has 2 integers and 3 strings.

Technically, you do not have to specify the size of the array when you declare it; VBA will resize it as
you add new elements.

18 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

But the best practice is to specify the number of items in the array so that the code is easier to
understand and modify.

In the “Cycle Number Format” macro in the course, we start by declaring a numberFormats array:

In this array declaration:

Dim numberFormats(1 To 6) As Variant

“1 to 6” means that the array will start with item #1 and go up to item #6, and “Variant” means that
the variable type of each item can be anything.

Each item in numberFormats(1) through numberFormats(6) represents the “next” custom number
format that we want to switch to when the user activates the macro with Ctrl + Shift + A.

So, if the user is currently in a cell with the percentage format (item #4), then we will change the cell’s
format to numberFormats(5) next, which represents standard numbers without decimal places.

The UBound function retrieves the size of the array (6 in this case).

Next, we use the Intersect and Selection.SpecialCells commands to retrieve all the non-empty cells:

19 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

And then the final part of the macro uses two “For Each” loops to go through all the non-empty cells,
and for each non-empty cell, it loops through all the formats in this numberFormats array:

We use StrComp rather than a simple “=” sign because StrComp works more reliably when the strings
we’re comparing have unusual or special characters.

The first “Exit For” statement is important because as soon as we get a matching number format, we
want to exit the numberFormats loop and go back to the outer loop to move to the next cell.

Arrays can get significantly more complicated because we can also create multidimensional arrays,
such as:

Dim multiDimArrray(1 to 5, 1 to 3, 1 to 4) As Integer

20 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

And there are ways to change an array’s size if we’ve declared it and specified the size, but now we
need to change it for some reason.

However, for most formatting and “spreadsheet automation” tasks, you will be using simple 1-
dimensional arrays that contain the formatting or contents of cells in the range.

Return to Top.

More Advanced VBA Features

Using just the features covered in the previous sections, you can accomplish quite a lot in VBA.

However, if you want to go beyond formatting and create macros that create or change formulas or
that modify the spreadsheet’s contents, you’ll need to learn some more advanced features.

Return to Top.

The Dictionary Object (“Hash Table”)

It’s useful to store items sequentially in an array, but sometimes you want to store them according to
other criteria.

For example, maybe you have a list of employees, and you want to store each employee’s name and
phone number such that each name is associated with a phone number.

One solution, in this case, is to use a Dictionary object (also known as a hash table, hash, map, or
associative array in other programming languages).

The Dictionary lets you store items according to Key:Value pairs rather than numeric indices. For
example, you could enter these Key:Value pairs for the employee and phone number data:

Key: “John Smith” Value: 555-555-5555


Key: “Jane Scott” Value: 123-456-7890

And then, you could look up each employee’s phone number by referencing this Dictionary object and
entering the employee’s name for the Key.

21 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

Before you can use Dictionary objects in VBA, you must install the Microsoft Scripting Runtime in the
PC version of Excel. To do this, go to Tools → References within the VBA Editor and check “Microsoft
Scripting Runtime”:

In Mac Excel, there is no built-in version of this Dictionary object, so you’ll have to find one online and
install it. As of the time of this course, there was a good Mac implementation in this Github repository.

Once you’ve followed the steps above, you can declare a Dictionary object like this:

Dim formatLookUp As Dictionary


Set formatLookUp = CreateObject("scripting.Dictionary")

One real-life use case is to use the Dictionary to store different custom number formats, and then to
associate each custom number format with a range of cells in the Selection.

The Key:Value pair would be:

Key: Custom Number Format Code Value: Range of Cells

22 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

This structure is useful because you can then select cells according to their number formats and
perform different operations on ranges of cells with different number formats.

In the course, we use this feature to create the “Change Decimal Places” macro.

Yes, there is a built-in way to change the decimal places in Excel (Home → Number)…

…but it has a big downside: if you select a range of cells with many different number formats, this
built-in method will change all the numbers to the same format:

So, if you want to increase the decimal places for percentages, valuation multiples, and dollar amounts
all at the same time, you need to select each cell type, execute the command, select the next cell type,
execute the command again, and so on:

23 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

Our macro automates this process so that we can select an entire range of cells in many different
formats, and VBA changes the decimals without changing all the cells to the same format.

The first part of this macro uses the standard Intersect and Union commands to create the
nonEmptyCells range:

The only difference is the Dictionary declaration, which we explained above.

24 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

Next, we loop through each cell in this nonEmptyCells range and check whether or not the number
format in that cell already exists in the Dictionary (“formatLookUp”).

If it does not, we add a Key:Value pair with the number format as the key and the cell as the value.

If it does already exist, we use Union to join this current cell with the other cells that have that same
format, we remove that format, and then we re-insert it with the current cell joined to it:

This “For Each” loop creates a Dictionary where each Key represents a different number format in the
range, and each Value represents the range of cells that use that number format.

We then use another “For Each” loop to go through each Key in the Dictionary, select the entire range
of cells for that Key, and execute the “Increase Decimals” command:

25 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

There is no way to know that this specific command increases decimals:

Application.CommandBars.FindControl(ID:=398).Execute

You would have to Google it or record a macro and check the code to get this line of code.

Dictionaries have their uses in VBA, but they’re less important than “For Each” loops, Intersect/Union
to select ranges, Array, and so on.

For example, we could have skipped the Dictionary here and looped through all the non-blank cells
manually, selected each one, and executed the same command – less efficient, but easier to write.

Return to Top.

String Functions

String functions are useful for “toggles” in VBA, where the macro performs one action when you press
the shortcut key, and then performs the opposite action when you press the shortcut key again.

For example:

• Flipping the signs of numbers from negative to positive or positive to negative.


• Adding =IFERROR() around formulas and then removing it.
• Scaling up all the numbers in a range by 1,000, and then dividing them by 1,000.

In the course, we use String functions to create the “Flip Signs” macro and the “Error Wrap” macro.

26 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

The start of the “Flip Signs” one, with variable declarations and numeric constant cells, is standard:

Flipping the signs of cells with numeric constants is easy because we can just set the cell’s value to the
negative of its current value (the same as multiplying by -1).

It’s more complicated for formulas because a formula might already have a negative sign in front of it.

If it does, then we must remove that negative sign and the parentheses. For example:

=–(L49*(1+M56)) → =L49*(1+M56)

But if the formula does not have the negative sign and parentheses, then we need to add them:

=M72*AVERAGE(L71,M71) → =–(M72*AVERAGE(L71,M71))

To accomplish both of these, we use the Left, Right, Mid, and Len functions, which all exist in VBA and
work the same way they do in Excel.

Left retrieves the N leftmost characters of a string, Right gets the N rightmost characters, Mid starts at
position X and retrieves Y characters, and Len retrieves the length of a string.

And we use StrComp, discussed earlier, to check the first 3 characters and see if they match “=-(“:

27 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

We do something very similar for the “Error Wrap” macro because the basic idea is the same: check for
certain characters in the beginning, remove them if they exist, and add them if they don’t.

The difference is that it only makes sense to retrieve and loop through formula cells for this one
because constant cells cannot generate errors.

Also, it’s trickier to remove text from the ends of formulas here because there’s more than just a single
parenthesis at the end.

Here are examples of the changes we want:

Toggle On: =I22/H22–1 → =IFERROR(I22/H22–1, "N/A")

Toggle Off: =IFERROR(I22/H22–1, "N/A") → =I22/H22–1

The macro begins with standard variable declarations, a retrieval of the formula cells in the Selection,
and a loop through all the formula cells:

28 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

The next part of the macro requires more explanation:

Before checking characters or modifying any formulas, we must check the length of the formula in the
current cell first.

If it’s shorter than “=IFERROR(” then it cannot possibly contain =IFERROR, so we take the formula and
add =IFERROR( in the beginning and , “N/A”) at the end.

On the other hand, if it’s longer than “=IFERROR(“ then the formula may already have IFERROR in it.

29 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

In that case, we check the leftmost characters of the formula text and see if they match =IFERROR(

If they do, we use InStrRev to find the position of the last comma in the formula, and then we use the
Mid function to retrieve all the text between the =IFERROR( and the last comma.

We then create a new formula with a “=” in front and just that inner formula term (the
innerFormulaTerm variable above).

If the leftmost characters of the formula text do NOT match =IFERROR( then we add it at the beginning
and the N/A part at the end.

The best thing about string functions in VBA is that they work nearly the same as they do in Excel. You
might have to look up the occasional new function, such as InStrRev here, but nothing is a giant leap
over normal Excel functions.

Return to Top.

Jumping To and Filling Ranges

Just as the string functions in Excel have their equivalents in VBA, so too do the keyboard shortcuts for
jumping to boundaries (Ctrl + Arrow Keys) and “filling right” (Ctrl + R) and “filling down” (Ctrl + D).

Here are the equivalents when Selection represents the range of cells the user has selected:

• Ctrl + Left Arrow Key: Selection.End(xlToLeft)


• Ctrl + Right Arrow Key: Selection.End(xlToRight)
• Ctrl + Up Arrow Key: Selection.End(xlUp)
• Ctrl + Down Arrow Key: Selection.End(xlDown)

• Ctrl + R: Selection.FillRight
• Ctrl + D: Selection.FillDown

In the course, we use these methods to build macros that “Flash Fill Right” and “Flash Fill Down.”

In other words, instead of selecting the exact area over which you want to Fill Right or Fill Down, the
macro looks at the boundaries and calculates the area automatically:

30 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

This macro does not work perfectly in all situations, but we can come up with a reasonably good
version without too much effort.

In the screenshots below, we’ll use the finished versions of these macros from the final lesson in the
VBA module because we make a few fixes and tweaks to the macros by then.

Here’s the start of the Flash Fill Right macro:

31 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

The new part here is that we’re using Selection.SpecialCells to find the last cell in the range.
The .Column property then gives us its column number.

The Application.ScreenUpdating = False in the beginning tells VBA not to update the screen until the
macro is done, which makes the macro more efficient.

We are not looking for just formula cells or just constant cells, so we Intersect the Selection and the
UsedRange to ensure a reasonable range, which is stored in the selRange variable.

Next, we check to see whether or not selRange has at least one cell in it, and that it’s not in the top row
of the spreadsheet.

If those are both true, then we use the .End(xlUp).End(xlToRight) commands to do the equivalent of
pressing Ctrl + Up and then Ctrl + Right in Excel to move to the right boundary of the first row above
the area the user has selected:

We need the selRange.Row > 1 check because if the Selection includes the first row of the spreadsheet,
there’s no way to “go above it” and figure out how far the fill should extend to the right.

The topRightCell here would be the “FY24” cell in the range shown below:

32 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

We finish the macro with this code, which requires some explanation:

The IF statement ensures that we do not fill past the rightmost column in the UsedRange of this
spreadsheet.

Then, we set the “fill range” by using the Range method, which creates a range based on the cells we
pass in as input parameters.

To create the cells required to form this range, we use the ActiveSheet.Cells command, which creates a
single cell based on a row number and a column number.

The .Row and .Column properties of a range, such as in selRange.Row and selRange.Column, always
produce the row number and column number of the top-left cell in that range.

So, this part creates the top-left cell:

ActiveSheet.Cells(selRange.Row, selRange.Column)

To create the bottom-right cell, we start in selRange.Row, move down the number of rows in the range
(selRange.Rows.Count – 1), and then use the column number of the topRightCell:

ActiveSheet.Cells(selRange.Row + selRange.Rows.Count – 1, topRightCell.Column)

Here’s the range formed by these two newly created cells:

33 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

Once we’ve set this fillRange, we use the fillRange.Select and fillRange.FillRight methods to fill to the
right through this range:

The “Flash Fill Down” macro is similar, but the logic is trickier. The issue is that we can’t just use the
VBA equivalents of Ctrl + Left and Ctrl + Down because the cell immediately to the left might be blank,
even if its column has contents further down.

Here’s an example that illustrates the problem, if we start in cell L47 (in the middle below):

We start the macro in a similar way, but we find the row number of the last row in the range instead:

34 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

In the next part, there are a few different cases to deal with:

Case #1: The cell immediately to the left is empty, and there’s nothing below it, so the entire column
below it is empty.

In this case, we can press Ctrl + Left and Ctrl + Down, or selRange.End(xlToLeft).End(xlDown), to move
to the bottom row of the fill range.

Case #2: The cell immediately to the left is blank, but the cells below are not blank, so there is
something in this column.

In this case, we can start in this cell immediately to the left and use .End(xlDown).End(xlDown) (press
Ctrl + Down twice) to navigate to the bottom row of the fill range.

Case #3: The cell immediately to the left is not blank, and the cells below it are also not blank.

In this case, we can start in this cell immediately to the left and use .End(xlDown) (press Ctrl + Down) to
move to the bottom row of the fill range.

Once we do that, we then set the fillRange based on the top-left cell in the selected range, the number
of the bottom row from one of the cases above, and the column number of the right-most cell.

Here’s the code:

35 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

You can find cases where this logic doesn’t work as intended, so you could keep tweaking it, but this
version is “good enough” for most purposes.

Return to Top.

ConvertFormula

While it’s useful to add and remove =IFERROR() around formulas and flip the signs of formulas or
constants, sometimes you need to go beyond that.

For example, sometimes you want to modify every single term in a formula a certain way, and it’s not
viable to use string functions because the formula could have dozens of terms.

One useful VBA method for doing that is ConvertFormula, which changes all cell references in a
formula to absolute, relative, row absolute column relative, or row relative column absolute.

36 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

In the course, we use this ConvertFormula to create the Anchor Toggle macro, which changes all cell
references in a formula to one of the four options above (absolute, relative, row absolute column
relative, or row relative column absolute). Each time you use it, it cycles to the next option.

This is a surprisingly tricky macro to write because of the toggle: we need to detect which reference
type the formula is currently using, and then “cycle it” to the next reference type. For example:

=H25*(1+I28) → =$H$25*(1+$I$28)

=$H$25*(1+$I$28) → =H$25*(1+I$28)

=H$25*(1+I$28) → =$H25*(1+$I28)

=$H25*(1+$I28) → =H25*(1+I28)

Without this macro, you would have to go into each formula manually and press F4 or ⌘ + T several
times to cycle through all the reference options.

If you wanted to do that for a range of cells, you would have to enter each cell manually and press F4
or ⌘ + T several times, which is time-consuming unless you automate it with this macro.

Here’s how we break down this problem:

First, we set up a normal macro to select all formula cells in the Selection and loop through them, and
we declare a few variables at the top:

Next, we tackle the simplest case first: the one where the formula uses all relative references (i.e., no
“$” characters).

37 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

To do this, we search for the “$” character using the InStr method; if it doesn’t exist anywhere, the
formula must have all relative references.

If that’s the case, then we call the ConvertFormula method, using Application.ConvertFormula, to
change everything to absolute references:

If you want more details on ConvertFormula, please see Microsoft’s documentation on the different
reference types.

After that, we handle the case where there is at least one “$” character in the formula.

Assuming there was a “$” somewhere, we need to find the position of the next “$”. We use the InStr
function to do that, which starts at a position in a string and searches for a specific character:

secondAnchorPos = InStr(firstAnchorPos + 1, cell.Formula, "$")

If it cannot find another “$”, it returns 0. In that case, there are two possibilities:

1) This cell reference is Row Absolute Colum Relative (e.g., A$1 or AB$1 or Sheet1!C$3).
2) This cell reference is Row Relative Column Absolute (e.g., $A1 or $AB1 or Sheet1!$C3).

To tell them apart, we check the character just before the “$”.

If it is an alphabetic character, such as A, B, C, or D, then it must be a Row Absolute Column Relative


reference (A$1 or AB$1 or Sheet1!C$3).

If it’s not an alphabetic character, then it must be a Row Relative Column Absolute reference ($A1 or
$AB1 or Sheet1!$C3).

To check this character, we use the Mid function and the Like operator, which you saw before in the
“Color Code” macro:

If Mid(cell.Formula, firstAnchorPos – 1, 1) Like "[a-zA-Z]" Then

38 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

firstAnchorPos – 1 gives us the character right before the first “$”.

Then, if this cell reference is Row Absolute Column Relative, we change it to Row Relative Column
Absolute. If it’s already Row Relative Column Absolute, we change it to all Relative.

Here’s the code for this case:

We’ve written another subroutine here called Toggle_Formula because we’ll need the same logic in
the next step.

Creating another subroutine like this lets you separate code and organize it more logically.

Unlike a function, a subroutine does not return anything – and you must use “Call” in front of its name
to activate it.

Finally, in the last case here, we need to handle formulas with multiple “$” characters in them.

This is harder than it sounds because that could be a sign of a fully Absolute reference or a sign of
multiple mixed references:

$A$1 or $A1 + $B2

$AB$1 or $AB1 + $BC2

39 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

To decide, we look at the text between the two “$” characters and see if it’s 100% alphabetic.

If it is, then the reference is Absolute.

If not, it’s a mixed Relative/Absolute reference.

If it is an Absolute reference, then we change the entire formula to use Row Absolute Column Relative
references.

If it’s a mixed reference, then we call the Toggle_Formula subroutine.

Here’s the code:

We use the Rept function (WorksheetFunction.Rept) to repeat the possible alphabetic characters (a, b,
c, A, B, C, etc.) and compare the “text between anchors” to those characters.

If there are 5 characters in between the “$” and “$”, this If statement is true if all 5 characters are in
the lowercase or uppercase alphabet.

This macro is more difficult to write than some of the others covered in this course because it’s easy to
mix up the logic for the different cases here.

It’s moderately useful and will save you some time, but it’s not as useful as some of the simpler macros
for color-coding and cycling number formats.

Return to Top.

40 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

The Table of Contents Macro: Hyperlinks, Offset, Sheets, and MsgBox

When you have a complicated workbook with 10+ spreadsheets, it’s useful to create a Table of
Contents or Summary page in the beginning:

The problem is that if you create this Table of Contents manually, you’ll also have to update it manually
whenever you insert a new spreadsheet or change the order of the sheets.

You can automate the insertion of a Table of Contents sheet with VBA, and the logic is fairly simple.

The hard part is that you’ll need to use a lot of formatting commands, and you’ll have to Google certain
tasks extensively to figure out how to accomplish them within VBA.

This topic is less important than the other ones in this guide, so we’re not going to cover it in extreme
detail.

Here are the steps, starting with the main subroutine in this macro:

41 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

The ISREF function in Excel tells us whether or not a specific cell reference exists, and we often use it to
detect whether an entire spreadsheet exists as well. “Evaluate” lets us use the same function in VBA.

The MsgBox command is useful for displaying alerts and messages and asking the user for Yes/No
decisions.

And the Sheets.Add command does what it sounds like and adds a new spreadsheet based on an index
we specify.

The next part of this macro, in the Create_Numbers_Links subroutine, sets up the formatting, such as
the sheet title, names, borders, and fill colors.

We use the “With” and “End With” notations to save space, and we use the .Offset method to move
over columns or move down rows.

The .Resize method is useful for “expanding the area” that we want to format based on a single
starting cell:

42 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

The code to display each sheet’s name and a direct link to it is as follows:

The first few lines loop through the worksheets in this file (they’re stored in the “Worksheets” object)
and check to make sure that the current sheet is not the “ToC” sheet and is also visible.

43 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

If those are both true, then we proceed to the next segment of code and start by retrieving the title of
the current sheet and then putting it in our Table of Contents area.

We assume the spreadsheet title is always in cell B2, so ws.Range(“B2”).Value retrieves that title.

The Hyperlinks object exists for the entire sheet, and Hyperlinks.Add lets us add direct links to other
sheets in the file.

There’s no way to know the syntax – you have to look it up online and follow Microsoft’s instructions.

We use single quotes for the sheet’s name in the SubAddress part to handle special characters, such as
blanks or dashes, in the sheet name:

tocSheet.Hyperlinks.Add Anchor:=.Offset(i, 2), Address:="", SubAddress:="'" & ws.Name & "'!A1",


TextToDisplay:=ws.Name

The .Offset(i, 2) part moves us down by the row number we’re in, and then moves us across 2 columns.

The final line here is very tricky, and, unfortunately, it is not easy to explain:

.Offset(i).Formula = "=SHEET(INDIRECT(""'""" & "&" & .Offset(i, 2).Address & "&" & """'!A1""))"

We’re using the same =SHEET(INDIRECT formula that’s in the normal Cover Page, but we’re putting
single quotes around the spreadsheet name in case it has a special character.

But we also need double quotes around the single quotes because we want the double quotes to
appear within this formula!

And we use the & operator to join together each element. If this is too confusing, you can make the
number (the "i" iterator") show up here instead:

.Offset(i).Value = i

The final result is a macro that produces a “ToC” spreadsheet that looks like this:

44 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

If the order of the sheets ever changes, the # column updates automatically due to the
=SHEET(INDIRECT formulas there.

And if we ever delete or add new sheets, we can delete and recreate the Table of Contents sheet
automatically by activating the macro.

Return to Top.

Charts and ChartObjects in VBA

Just as it’s possible to automate formatting and formula changes using VBA, it’s also possible to
automate the creation of graphs and charts.

Unfortunately, the syntax is confusing and difficult to explain, so if you want to do something like this,
your best bet is to use the macro recorder and then edit the code.

Otherwise, you’ll spend hours Googling the proper VBA methods to modify axis titles or the font sizes
for data labels, and there isn’t much consistency to anything.

We’ll cover the highlights of how to write a macro to build a Price-Volume Graph, but they will be very
high-level because there’s no point in memorizing these commands.

First, we need to pull in the source data – a public company’s share price and volume of shares traded
over the past year, 2 years, 3 years, etc.

45 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

As of the time of this course, there’s no easy way to do this automatically in Excel/VBA without using
external add-ins such as the ones from Capital IQ or FactSet.

If you don’t have those, you can look up the data on sites like Yahoo or Google Finance and then copy
and paste it into Excel:

Once you have this, you should select all the data, activate the macro recorder, and then complete the
steps required to build a Price-Volume Graph, covered in the written guide to Charts & Graphs.

We did this and then cleaned up and simplified the code. Here are the main steps in the macro:

46 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

This part above sets up the graph, the source data for the graph, and its height and width.

There’s no point memorizing the Shapes.AddChart2 syntax; the macro recorder generates it. Next is
this segment:

Again, these are commands that you could only know from the macro recorder’s code. We fix the “Gap
Width” issue in the beginning to avoid the need to backtrack and do so later.

In some cases, we modify the pvGraph Chart object directly, while in other cases, we set the formatting
based on objects within the chart, such as pvGraph.ChartGroups(1).

There is no logic to which formatting option corresponds to which object.

Next, we format the Horizontal Category Axis (for the dates) and the Secondary Vertical Axis (for the
volume of shares traded):

47 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

Setting the Tick Label Spacing and Tick Mark Spacing to 25 removes the blank spaces in between the
Volume bars; the rest is standard color/size formatting.

We finish with the Primary Vertical Axis, the Graph Title, and the Legend:

48 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

The main point here is that we consolidated and simplified the auto-generated code from the macro
recorder by using “With” and “End With” statements to group formatting commands.

With this macro completed, we can now select ranges of Date, Price, and Volume data and
automatically create Price-Volume Graphs:

49 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

Is this macro useful?

The answer is: “Sometimes, but not really, because you could always just copy and paste another Price-
Volume Graph and change the Source Data.”

That’s the problem with graphs and charts in VBA: writing macros to create them doesn’t necessarily
save you much time over a simple copy-and-paste-and-data-swap for an existing template.

Return to Top.

User-Defined Functions (UDFs)

Macros can modify formulas, formatting, or graphs on a spreadsheet, but they do not return values.

That’s why all macros start with “Sub” for “Subroutine” – a Subroutine performs a set of actions and
changes the spreadsheet, but it doesn’t produce one single “answer.”

By contrast, a Function in VBA performs a set of actions and then returns a specific answer.

You use the same VBA syntax and commands to write both Functions and Subroutines, but they are
used for different purposes.

Functions are useful for making specific calculations you need in a spreadsheet, in cases where Excel
does not already have built-in functions to do the same.

50 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

For example:

• You could write a function to calculate WACC, the Weighted Average Cost of Capital, based on
several inputs.

• You could write a function to calculate a company’s Annual Churn Rate (cancellation rate)
based on a range of Monthly Subscription Data.

• Or, you could write a function to calculate CAGR, the Compound Annual Growth Rate, based on
a set of numbers and dates.

We cover the last example in this course, with the goal of writing a user-defined function (UDF) that
does the following:

Since CAGR = (Ending Number / Starting Number) ^ (1 / # Years) – 1, the calculation here is: ($595,986
/ $510,329) ^ (1 / 5) – 1 = 3.2%.

Our function must generalize this formula so that it calculates the # Years based on the range of dates,
and so that it calculates Ending Number / Starting Number based on the range of numbers.

In this case, we cannot use the macro recorder because it’s not possible to perform a “set of actions”
in Excel that results in this exact output.

So, we start by writing a “CAGR” function that accepts a range of dates and a range of numbers as
inputs, does some error-checking, and then calls a helper function named “calculateCAGR” that
performs the calculation.

Here is the CAGR function:

51 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

In each case, we set CAGR to something: 0 if there’s an error or incorrect input, or the output of the
calculateCAGR function if the inputs are valid.

The calculateCAGR helper function requires more explanation, so here’s the first part of it:

52 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

And then the last part of this helper function is as follows:

We use YEARFRAC here because the user could have entered anything for the dates – they could be 3
months apart, 9 months apart, 5.3 years apart, or 10.625 years apart.

In each error case, we set calculateCAGR to 0, and when there are no errors, we make the actual
calculation. VBA “knows” to return this value since the calculateCAGR variable has the same name as
the calculateCAGR function.

Similarly, in the CAGR function above, CAGR always equals 0 or the value produced by calculateCAGR,
so the function always returns something.

The vast majority of this user-defined function consists of error-checking, which is quite common in
all types of programming.

The math is simple, but there are many ways in which the user could enter invalid cell ranges for this
function, so we need to handle all those cases.

Return to Top.

VBA Finishing Touches

If you’ve made it this far, you should have a good understanding of the fundamentals of VBA.

53 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

However, even if your macros and VBA code work, you may not necessarily be following “best
practices.”

If your code is not well-structured, or it has too much redundancy, or it doesn’t handle certain errors,
then it’s not ideal.

There are a few minor points to cover here, as well as three major ones: cleaning up code with helper
functions, assigning keyboard shortcuts to macros, and exporting macros for use in other files.

One minor point is that it helps to add this line of code at the start of each function or subroutine:

Application.ScreenUpdating = False

And this one at the end of each function or subroutine:

Application.ScreenUpdating = True

These ensure that the Excel screen will not update until the macro is completely finished – not a big
deal for a simple macro on a small sheet, but a huge deal for a complex macro on a large sheet.

Another minor point is that you should add comments to your code to explain what you’re doing,
especially in cases where the logic is tricky. You can type the single quote character to do this:

You don’t need to add comments for every single line, but they make your code more understandable
for anyone else reviewing it – whether that’s you in the future, or someone else.

Finally, each “Module” in VBA should have its own descriptive name rather than the default names of
Module1, Module2, etc.

All function, subroutine, and module names must be unique, so you cannot call a macro
“Color_Code” and then call its module “Color_Code” as well.

We tend to use slight variations of the function/subroutine names for the module names:

54 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

Return to Top.

Cleaning Up Code with Helper Functions

If you find yourself repeating the same code, or very similar code, in different macros, you should
move this similar code into helper functions.

That way, you can write the function or subroutine once and then re-use it everywhere.

And if something ever changes, you can go back to that one function or subroutine and make your
edits there.

We created a separate “Helpers” module for these functions, and they include helpers such as
“getNonEmptyNumericCells”:

55 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

We use this function in many macros because plenty of tasks in VBA require non-empty cells with
formulas or constants in them.

We can use this helper function by typing Helpers.getNonEmptyNumericCells and passing in the
UsedRange and Selection (“Set” is still required since nonEmptyCells is a Range variable):

56 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

We can even create helper functions/subroutines within the same module because many “toggle”
macros use nearly the same code in both cases:

Decimal_Helper here is a subroutine because it does not return any values. That’s also why we have to
type “Call” in front of its name to use it (e.g., Call Decimal_Helper(True)).

Further down within this subroutine, we check this increaseDec input variable and then execute the
appropriate command based on that:

57 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

Similar to proper spreadsheet setup and formatting, helper functions are not required for VBA code to
work correctly, but they will make your life easier.

Return to Top.

Assigning Keyboard Shortcuts to Macros

If you’re using only a few macros, and the built-in macro recorder lets you assign the exact keyboard
shortcuts you want, you don’t need to create any shortcuts manually.

The built-in recorder works well for shortcuts that use the Ctrl key and one other key, such as:

• Ctrl + Shift + T
• Ctrl + .

But sometimes you may want to use a more complex shortcut, such as:

• Ctrl + Shift + Alt + T


• Ctrl + Shift + Alt + .

To assign custom keyboard shortcuts to your macros, you start by creating helper subroutines called
“CreateShortcuts()” and “DeleteShortcuts()” that bind each key combination to a specific macro:

58 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

The syntax for the shortcut codes in Application.OnKey method is as follows:

• Ctrl: ^
• Shift: +
• Alt: %
• Enter: ~
• Other Keys: {Enclose the key in curly braces}

So, for example, the “^+1” binding above corresponds to Ctrl + Shift + 1.

The “^+%{T}” binding corresponds to Ctrl + Shift + Alt + T.

You can get the full list in Microsoft’s documentation here.

Typing Application.OnKey, entering the shortcut code, and then entering the macro name in double
quotes will create the binding.

Doing the same thing but leaving out the macro name will remove the binding.

Once you’ve done this, go to “ThisWorkbook” in the Microsoft Excel Objects list in the VBA Editor,
select BeforeClose and Open on the right-hand side, and enter the following subroutine calls:

59 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

If you can’t see it in the screenshot above, we’ve created two private subroutines (“private” meaning
that other modules cannot use them):

Private Sub Workbook_BeforeClose(Cancel As Boolean)


Call Helpers.DeleteShortcuts
End Sub

Private Sub Workbook_Open()


Call Helpers.CreateShortcuts
End Sub

Now, save the file, close it, and open it again, and your new keyboard shortcuts should work.

Return to Top.

Exporting Macros for Use in Other Files

One disadvantage of VBA/macros in Excel is that if you write complex code in one file, it does not
automatically transfer to other files (workbooks).

You have to export the code and then import it into new files to transfer your macros.

To do this, go to “Save File As” and select “Excel Add-in (*.xlam)” for the type:

60 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

Then, open a new, blank file, go to Options or Preferences (Alt, T, O or ⌘ + ,), Add-ins, and Manage:
Excel Add-ins:

61 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

And then select the .xlam file you saved and load it into Excel:

62 of 63 https://breakingintowallstreet.com
Excellence with Excel 3.0
Excel – VBA and Macros

Now, all your macros will be available in this new file. To get the custom keyboard shortcuts to work,
you will have to save, close, and re-open the file.

As an optional step, you could also save the original file, delete all the “VBA Worksheet” objects in the
VBA Editor and make your file consist of just the VBA modules you’re using for your macros.

That way, when you export this file and load it elsewhere, VBA Worksheet objects with the names of
the spreadsheets in the original file won’t clutter up your new file.

Return to Top.

63 of 63 https://breakingintowallstreet.com

You might also like