Peltier Tech Blog

Excel Charting Utilities | Custom Solutions | Training | Charts and Tutorials | PTS Blog

 

Main menu:

 
Peltier Tech
Chart Utilities

PTS Waterfall Chart Utility
PTS Cluster-Stack Column Chart Utility
PTS Box and Whisker Chart Utility
PTS Marimekko Chart Utility
PTS Dot Plot Utility
PTS Cascade Chart Utility

Subscribe

Site search

Subscribe

Site search


Recent Posts

Recently Commented

Popular Posts

Archive


 

Categories


 

Buy me a coffee

If this topic or the whole blog has been helpful, support further development by treating me to a cup of coffee.


Privacy Policy

Creative Commons License
Licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License.

How To: Fix a Recorded Macro

by Jon Peltier
Tuesday, March 11th, 2008
Peltier Technical Services, Inc., Copyright © 2010.
Licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License.

In a recent post, I showed how to record a macro to save yourself time and effort with that repetitive task. The recorder has captured all of your keystrokes, intentional and otherwise. Objects are selected first, then acted upon. Defaults are applied indiscriminately every time the recorder followed you into a dialog. Actions you take and undo are all recorded. The result is syntactically accurate, but inefficient.

Let’s clean up the code to make it run faster and smoother, without the flashing shown on screen. Go to the VB Editor and open the code module containing your recorded macro. The code recorded in the previous example is shown below.

Sub RecordedMacro()
 '
 ' RecordedMacro Macro
 ' Macro recorded 3/7/2008 by Jon Peltier
 '

'
     With Selection
         .HorizontalAlignment = xlCenter
         .VerticalAlignment = xlBottom
         .WrapText = False
         .Orientation = 0
         .AddIndent = False
         .IndentLevel = 0
         .ShrinkToFit = False
         .ReadingOrder = xlContext
         .MergeCells = False
     End With
     With Selection.Font
         .Name = "Arial"
         .Size = 10
         .Strikethrough = False
         .Superscript = False
         .Subscript = False
         .OutlineFont = False
         .Shadow = False
         .Underline = xlUnderlineStyleNone
         .ColorIndex = xlAutomatic
     End With
     With Selection.Font
         .Name = "Arial"
         .Size = 12
         .Strikethrough = False
         .Superscript = False
         .Subscript = False
         .OutlineFont = False
         .Shadow = False
         .Underline = xlUnderlineStyleNone
         .ColorIndex = xlAutomatic
     End With
     Selection.Font.ColorIndex = 3
 End Sub
 

That’s a lot of code for the small number of actions that were done while recording. We centered the text in the selected cells, changed the font to Arial, changed the font size to 12 points, and changed the text to red. Every time an action was taken, properties which were not changed during that action were still recorded, despite being unchanged. For example, the font’s ColorIndex was twice ”changed” to xlAutomatic, before finally being changed to 3 (red in the default Excel color palette). Removing the redundant and default statements greatly reduces the code.

Sub RecordedAndFixedMacro()
 ' Macro recorded & fixed up 3/7/2008 by Jon Peltier
 '
     With Selection
         .HorizontalAlignment = xlCenter
     End With
     With Selection
         With .Font
             .Name = "Arial"
             .Size = 12
             .ColorIndex = 3
         End With
     End With
 End Sub
 

This macro didn’t have the usual repeated cycle of select an object, format the selection, select another object, so I’ve included another sample below.

Sub SelectAndFormatRecording()
 '
     Range("C9:G9").Select
     Selection.Font.Bold = True
     Range("C11:G11").Select
     Selection.Font.ColorIndex = 5
 End Sub
 

By avoiding the sequence of selections, the code is smaller and runs faster, and the screen doesn’t change or even flash with each subsequent selection change.

Sub FormatByReference()
 '
     Range("C9:G9").Font.Bold = True
     Range("C11:G11").Font.ColorIndex = 5
 End Sub
 

A technique for streamlining code is to group operations performed on each object within With/End With blocs. The first recorded macro above was recorded with several With/End With blocks. But frequently when recording macros, we are carrying out operations as we think of them, and operations on the same object may be scattered around the macro. In this case, we can construct our own blocks, first rearranging the code, then forming the blocks.

Sub DisorderlyRecording()
 '
     Range("J12:M19").Font.Bold = True
     Range("J14:M14").Font.ColorIndex = 5
     Range("J12:M19").Font.Name = "Courier New"
     Range("J14:M14").Font.Italic = True
     Range("J12:M19").HorizontalAlignment = xlCenter
 End Sub
 

Reordering…

Sub ReorderedRecording()
 '
     Range("J12:M19").HorizontalAlignment = xlCenter
     Range("J12:M19").Font.Bold = True
     Range("J12:M19").Font.Name = "Courier New"
     Range("J14:M14").Font.ColorIndex = 5
     Range("J14:M14").Font.Italic = True
 End Sub
 

Blocking…

Sub ReorderedAndBlocked()
 '
     With Range("J12:M19")
         .HorizontalAlignment = xlCenter
         With .Font
             .Bold = True
             .Name = "Courier New"
         End With
     End With
     With Range("J14:M14").Font
         .ColorIndex = 5
         .Italic = True
     End With
 End Sub
 

Note that you can nest one With/End With block within another.

For a more detailed look at optimizing recorded macros and using Excel’s object model more effectively, see my colleague Tushar Mehta’s Beyond the macro recorder.

In a series of upcoming posts, I’ll cover the following VB topics:

Related Posts:

Bookmark and share this entry:
  • Twitter
  • Digg
  • Facebook
  • LinkedIn
  • del.icio.us
  • Technorati
  • StumbleUpon
  • Google Bookmarks
  • Reddit
  • MySpace
  • Slashdot
  • Yahoo! Buzz
  • Tumblr

Learn how to create Excel dashboards.

Comments


Comment from ckz
Time: Monday, March 23, 2009, 2:02 pm

Using VBA I am assigning several different charts to the same worksheet. Based on a button the user presses, the correct chart will appear.

So, to change the title of the worksheet and within the chart I assign the title, simply by saying Title = “Water”. Where ever I need that specific text in the code, I use Title.

My question is, how do I subscript in the text of the editor box. This code changing is not my own. The previous programmer was able to add superscript within the editor box. Is there a way to do subscript?

He simply had Title = “Water m³”

I am trying to say Title = “CO2 emissions”
(I cut and pasted the m3 from the program and the format stays, even in this email. I cut and pasted from a word document the CO2… and the 2 was subscript, but didn’t carry over in this email)

I hope this question makes sense. I have seen a lot of website resources for formating specific cells, but nothing within the VBA editor.

Thanks,


Comment from Jon Peltier
Time: Monday, March 23, 2009, 2:40 pm

One suggestion is to find a font that has sub- and superscripted characters.

The way I had to do it on one project was to assign the superscript format to only some of the characters in the text element. I show this in the Scientific/Exponential Notation Axis Labels tutorial to produce the exponent on the powers of ten.

With srs.Points(Counter)
    ' Apply label to point
    .HasDataLabel = True
    .DataLabel.Characters.Text = _
        myString1
    ' Superscript part of the label
    With .DataLabel.Characters(3, Len(myString1) - 2).Font
        .Superscript = True
        .Size = .Size + 1
    End With
End With

 
The segment of the label is accessed using .Characters(start, length). I increased the size of the superscripted text by one point to make it legible.


Comment from ckz
Time: Monday, March 23, 2009, 4:26 pm

Thank you for the help. I am a little confused because the sample code is looking for a range of cells.

In my situation, the title is actually written in the code, not drawn from data in a cell.

Sub Title()
Dim Title As String
Dim StringLength As Integer

Title = “CO2 Emissions”
StringLength = Len(Title)

Sheets(“Sheet1″).Cells(1, 1) = Title

End Sub

I don’t understand how to use the With statements to make the 2 in CO2 subscript.

Thank you.


Comment from Jon Peltier
Time: Monday, March 23, 2009, 4:42 pm

Here is the relevant code:

Sub SubScriptTitle()
  Dim sTitle As String

  sTitle = "CO2 Emissions"

  With Sheets("Sheet1").Cells(1, 1)
    .Value = sTitle
    .Characters(3, 1).Font.Subscript = True
  End With
End Sub

 
Here, With means take Sheets(“Sheet1″).Cells(1, 1) and perform the following actions with it. The first action is to put the title into the cell, the second is to take a substring starting at character 3, one character long, and subscript it.

Write a comment

I welcome comments from my readers. If you have an opinion on this post, if you have a question or if there is anything to add, I want to hear from you. Whether you agree or disagree, please join the discussion.

If you want to include an image in your comment, post it on your own site or on one of the many free image sharing sites, and include a link in your comment. I'll download your image and insert the necessary html to display the image inline.

Read the PTS Blog Comment Policy.





Subscribe without commenting

PTS Waterfall Chart Utility PTS Cluster-Stack Column Chart Utility PTS Box and Whisker Chart Utility PTS Marimekko Chart Utility PTS Dot Plot Utility PTS Cascade Chart Utility

Create Excel dashboards quickly with Plug-N-Play reports.