week 5 - City, University of London

Excel VBA - City University Continuing Education
VBA for Microsoft Excel - Part 5
Table of Contents
1
1.1
1.2
1.3
2
2.1
2.2
2.3
3
4
4.1
4.2
5
5.1
1
For Each Loops .................................................................................................. 1
For Each loops ............................................................................................... 1
Testing to see if a cell contains a number .................................................. 2
Testing to see if a cell is blank ..................................................................... 2
Using variables with loops .............................................................................. 3
‘Counter’ variables ....................................................................................... 3
Finding the highest / lowest value ............................................................ 3
The Locals window ...................................................................................... 3
Used Range ........................................................................................................ 4
Using For Each with Object Collections ......................................................... 4
A macro that runs on every open workbook ............................................ 4
A macro that runs on every worksheet ..................................................... 4
Shortcut selection keys ..................................................................................... 5
Code corresponding to keyboard shortcuts .............................................. 5
For Each Loops
Rather than repeat code to perform repeated tasks, you should create a loop
structure to repeat the task in hand. ‘Looping’ therefore means ‘repetition’.
Often you will need a statement for applying a task to a group of objects. If you
want to change the colour of a range of cells to blue, or give every cell the value
of "2", this can be done using Selection or Range e.g.,
Selection.Interior.Color = vbGreen
Range("B2:C6").Interior.Color = vbGreen
Commands that are applied to a group of cells present little problem - for
example, "change the fill colour to red" or "change the value of the cells to say
‘Closed on Sundays’ “. The previous state of the cells is irrelevant as they are
overwritten. After the macro has been run, they uniformly have the colour or value
set by the macro.
1.1 For Each loops
Sometimes, the existing values do matter as when you want to update a range of
numbers by multiplying the values by 1.5 – for example, if all employees get a 50%
pay increase. If the macro involves processing each cell individually, then the
selection property is not adequate.
Selection = Selection * 1.5 does not work because each cell in a selection
has its own individual Value property.
Rather than create repetitious code like:
Range("B2") = Range("B2") * 1.5
Range("B3") = Range("B3") * 1.5
Range("B4") = Range("B4") * 1.5
you can create a loop.
What you need is a construction that is equivalent to for each cell in the selection do
some action. This allows you to treat each cell individually but only need to write
one command for the action. For a selection of cells, do something for one cell and
when that is done repeat the commands for the next cell. This loop continues until
all cells are processed .
Here the calculation is different for each cell. If B2 contains 19, then the operation is
19 * 1.5; if cell B3 contains 26, the operation is 26 * 1.5, and so on.
This is where a For Each loop can be used. Here is the basic pattern:
For Each object in selection
-- do some action(s) on each object --
Next object
Page 1 of 5
Excel VBA - City University Continuing Education
Where object means an object variable of some kind – on this occasion a
Range variable representing a single cell within a selection. The code between
the For Each and Next is repeated until the end of the selection is reached.
Here is an example: we assume that cells are selected before running the
macro. The macro will fail if any cell contains non-numeric data
Sub LoopTest()
Dim myCell As Range
For Each myCell In Selection
myCell = myCell * 1.5
Next myCell
End Sub
A range variable called myCell is declared; the variable will be instantiated to
each cell in the selection by the code
Any lines between the For Each and Next are repeated, i.e. cells are multiplied
by 1.5 one by one within the selection.
You may find it helpful to compare the code with the flow diagram below.
The For Each … Next block contains the lines to be repeated, and can also contain
other blocks like If statements
1.2
Testing to see if a cell contains a number
Use the IsNumeric() function for this. Example:
If IsNumeric(ActiveCell) Then
Msgbox “Current cell contains a number”
End If
1.3 Testing to see if a cell is blank
You can use the IsEmpty() function to test whether or not a cell is blank
Example:
If Not IsEmpty(ActiveCell) Then
Msgbox “Current cell contains data”
End If
Alternatively, if a cell is empty it contains the empty string”” (literally one double
quote followed by another with nothing in between):
If ActiveCell <> “” Then
Msgbox “Current cell contains data”
End If
In the next code note also how the IsNumeric() function prevents a run-time
error should a cell contain non-numeric data
Sub Looptest2()
Dim mycell As Range
For Each myCell In Selection
If IsNumeric(myCell) And mycell >= 25 Then
myCell = myCell * 1.5
myCell.Interior.Color = vbCyan
ElseIf IsNumeric(myCell) And mycell < 25 Then
myCell = myCell * 1.2
myCell.Interior.Color = vbMagenta
End if
Next myCell
End Sub
Page 2 of 5
Excel VBA - City University Continuing Education
2
Using variables with loops
The loop examples up to now have been used to directly manipulate worksheet
data. However you may want to accomplish additional tasks, which typically
means creating one or more extra variables.
2.1 ‘Counter’ variables
For example if you carry out operations on a range of cells using a loop, you
might want to keep a count of how many cells were affected. You would have
to create an integer variable, and increment it by one each time the operation
happened. To increment a variable by one is very easy. If the variable is called i
then the way to increment it is i = i + 1
For example, if you select a range containing hourly pay rates, and you want
upgrade any to a minimum of £10 and message how many cells were affected
you could write:
Sub
Dim
Dim
For
PayCalc()
rng As Range
i As Integer
Each rng In Selection
If rng.Value < 10 Then
rng.Value = 10
i = i + 1
End If
Next rng
MsgBox i & " pay rates increased"
End Sub
Highest = Selection.Cells(1).Value
For Each rng In Selection
If rng.Value > Highest Then
Highest = rng.Value
End If
Next rng
MsgBox "Highest value is " & Highest
End Sub
For this code to work you must have a range of numeric cells selected. Note that
the statement Selection.Cells(1).Value (see sction 4 of these notes) is able to
reference the first cell of a selection
2.3 The Locals window
The Locals window can help you debug problems in your code because it shows the current
value of any variable while you step through a program. To display the Locals window, in
the VB Editor, click View menu, Locals window.
To use the Locals window step through your program (function key F8). Carefully observe
the value of variables as each line is executed.
2.2 Finding the highest / lowest value
Again use a variable in a loop to store the value of the highest so far. Assign the
first value in the selection to the variable, and as the loop runs it is compared
with each successive value. If the first value is superseded then the higher value
is assigned to variable, otherwise the highest remains as it is.
Sub FindMaxValue()
Dim Highest As Single
Dim rng As Range
'initial setting of a max value
Page 3 of 5
Excel VBA - City University Continuing Education
3
Used Range
The worksheet object has a UsedRange property, which returns the range from
the top left to the bottom right of cells that have been used on the worksheet.
You must remember to include a reference to a worksheet e.g.,
ActiveSheet.UsedRange.Select or
Worksheets(1).UsedRange.Select
Worksheets(“Rates”).UsedRange.Columns(1).Select
UsedRange (or any other range) has an Address property, which can be useful,
eg
Debug.Print ActiveSheet.UsedRange.Address
The program below loops through the UsedRange and formats cells containing
a value over 50.
4.1 A macro that runs on every open workbook
This code saves all open workbooks and closes Excel.
Sub SaveThemAll()
Dim w As Workbook
‘w is an object variable of type Workbook
For Each w In Workbooks
w.Save
Next w
Application.Quit
End Sub
Sub UsedDemo()
Dim mycell As Range
For Each mycell In ActiveSheet.UsedRange
If IsNumeric(mycell) And mycell > 50 Then
mycell.Interior.Color = vbYellow
End If
Next mycell
End Sub
4.2 A macro that runs on every worksheet
The next code writes some text to cell A1 on each worksheet by iterating through
the worksheets collection.
The limitation of Selection.CurrentRegion.Select is that you cannot use it to
reference data that includes blank rows. In these circumstances you may be able
to exploit UsedRange. The disadvantage of UsedRange is that includes blank
cells that were previously formatted, which might spoil your intentions, so
avoid UsedRange where the same sheet is continously recycled.
For Each w In Worksheets
w.Range("A1") = "City University"
Next w
End Sub
4
Using For Each with Object Collections
For Each is versatile, because it can be used to repeat statements for any
collection of objects. It is not limited to ranges of cells. The code always takes
the form
For Each objectvariable In collection
e.g.,
Dim w As Worksheet
For Each w In Worksheets
...
Next w
Sub LoopWorksheets()
Dim w As Worksheet
It’s essential to remember to use the object variable in the code within the loop
w.Range("A1") = "City University"
otherwise the text will be written to the active sheet multiple times.
Admittedly the above program is not very useful. The next code uses the same
technique to change the font name, font size and column width for every sheet in
the workbook.
Sub LoopWorksheets2()
Dim w As Worksheet
For Each w In Worksheets
With w.Cells.Font
.Name = "Verdana"
Page 4 of 5
Excel VBA - City University Continuing Education
.Size = 11
End With
w.Columns.ColumnWidth = 14
Next w
End Sub
5
Shortcut selection keys
A region is a range of cells, all containing text, numbers or formulas and bounded
by white space (empty cells). The current region is where the currently selected
cell is: it is the block of cells surrounding the current cell. We have already
encountered Ctrl+Shift+8 or Ctrl + * (from numeric keypad) to select the current
region.
Similarly, assuming the cell containing the value, “Current” is selected, CtrlShift-right arrow selects the following:
You can use Ctrl + (left/right/up/down) arrow to select the cell on the edge of
a region to the left of/right of/above/below the selected cell
5.1
Assuming the cell containing the value, “Current” is selected ,Ctrl + Up arrow
has the effect illustrated below
Code corresponding to keyboard shortcuts
Keystroke
Ctrl + Shift +8
Ctrl + left
Ctrl + right
Ctrl + up
Ctrl + down
Corresponding code
Ctrl + Shift + left
Ctrl+Shift+right
Ctrl + Shift + up
Ctrl+Shift+down
Range(Selection,Selection.End(xlToLeft)).Select
Range(Selection,Selection.End(xlToRight)).Select
Range(Selection,Selection.End(xlUp)).Select
Range(Selection,Selection.End(xlDown)).Select
Selection.CurrentRegion.Select
Selection.End(xlToLeft).Select
Selection.End(xlToRight).Select
Selection.End(xlUp).Select
Selection.End(xlDown).Select
These references can be valuable for tasks such as selecting data prior to a loop or
finding the first blank row of a worksheet.
You can use Ctrl + Shift + (left/right/up/down) arrow to select a range from
the currently active cell to the leftmost/rightmost/topmost/bottommost cell in
the current region
Page 5 of 5