Figure 1: A raw worksheet in need of formatting
Click to enlarge
The following code listing shows the code recorded by the macro to produce the worksheet shown in Figure 2.
Listing 1: Code produced by the Macro Recorder:
Sub Macro1()
'
' Macro1 Macro
'
Columns("B:N").Select
Selection.ColumnWidth = 9.86
Range("B3:N3").Select
With Selection
.HorizontalAlignment = xlRight
.VerticalAlignment = xlBottom
.WrapText = False
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = False
End With
Range("B4:N9").Select
Selection.Style = "Comma"
Selection.NumberFormat = "_(* #,##0.0_);_(* (#,##0.0);_(* ""-""??_);_(@_)"
Selection.NumberFormat = "_(* #,##0_);_(* (#,##0);_(* ""-""??_);_(@_)"
Range("A4:A8").Select
Selection.InsertIndent 1
Selection.Font.Bold = True
Range("A9:N9").Select
Selection.Font.Bold = True
Range("N3:N8").Select
Selection.Font.Bold = True
Range("B3:M3").Select
Selection.Font.Bold = True
Range("A2").Select
Selection.Font.Bold = True
Rows("3:3").Select
Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Range("A2").Select
End Sub
Figure 2: The worksheet after running a formatting macro
Click to enlarge
Looking at listing 1, the biggest thing that jumps out at me is the use of the Select method. The Macro Recorder has to record everything you do — it can’t make assumptions or educated guesses about what is really important or needed. One terribly inefficient yet common habit to avoid is using the Select method in conjunction with Selection. It is not necessary to select items in order to manipulate them programmatically. In Excel, the vast majority of the things you do as a user is manipulate ranges.
In the recorded code, any line that starts with Selection is actually manipulating a Range object. The main way you can make this code more efficient is to modify it to eliminate the use of Select and Selection as shown in Listing 2. In this listing, I commented out the unnecessary code (lines that start with an apostrophe) and followed each logical task with the statement that replaces the “commented out” code.
Generally after cleaning a macro in this manner and verifying it still works, I would delete all of the commented code. I left it in this listing so that you could easily compare the changes I made.
‘ A cleaner version of the recorded macro
Sub MoreEfficientMacro()
Dim ws As Worksheet
Set ws = ActiveSheet
'Columns("B:N").Select
'Selection.ColumnWidth = 9.86
ws.Range("B:N").ColumnWidth = 9.86
'Range("B3:N3").Select
'With Selection
' .HorizontalAlignment = xlRight
' .VerticalAlignment = xlBottom
' .WrapText = False
' .Orientation = 0
' .AddIndent = False
' .IndentLevel = 0
' .ShrinkToFit = False
' .ReadingOrder = xlContext
' .MergeCells = False
'End With
ws.Range("B3:N3").HorizontalAlignment = xlRight
'Range("B4:N9").Select
'Selection.Style = "Comma"
'Selection.NumberFormat = "_(* #,##0.0_);_(* (#,##0.0);_(* ""-""??_);_(@_)"
'Selection.NumberFormat = "_(* #,##0_);_(* (#,##0);_(* ""-""??_);_(@_)"
ws.Range("B4:N9").NumberFormat = _
"_(* #,##0_);_(* (#,##0);_(* ""-""??_);_(@_)"
'Range("A4:A8").Select
'Selection.InsertIndent 1
'Selection.Font.Bold = True
ws.Range("A4:A8").InsertIndent 1
ws.Range("A4:A8").Font.Bold = True
'Range("A9:N9").Select
'Selection.Font.Bold = True
'Range("N3:N8").Select
'Selection.Font.Bold = True
'Range("B3:M3").Select
'Selection.Font.Bold = True
'Range("A2").Select
'Selection.Font.Bold = True
ws.Range("A9:N9").Font.Bold = True
ws.Range("N3:N8").Font.Bold = True
ws.Range("B3:M3").Font.Bold = True
ws.Range("A2").Font.Bold = True
'Rows("3:3").Select
'Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
ws.Range("3:3").Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
'Range("A2").Select
Set ws = Nothing
End Sub
This listing could be improved in several more ways, but given the space of this column and without providing more background, I’ll need to save them for another day.
If you remove the comments, the cleaned version has 13 lines of statements versus 32 lines in the original version. From a performance standpoint, the cleaned version runs in less than half the time of the original version. Next week, we’ll go just a little bit deeper on this and show how you can halve the running time of the cleaned version with two lines of code.