PTS Blog

Custom Solutions | Commercial Utilities | 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.

Extend Range to Add New Series (VBA)

by Jon Peltier
Peltier Technical Services, Inc., Copyright © 2009.
Licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License.

In some of the analyses I do, I’ll have a range of data and some charts based on this range. As the analysis unfolds, more columns may be added to the data range, and these have to be added to the chart. Until last week, I would add a series by copying the series formula of an existing series, selecting the plot area, pasting the formula into the formula bar, editing the formula, and pressing Enter. Adding series has been the most tedious part of the analysis, and finally I decided to speed it up.

I wrote some code to create a new series based on the range next to the last series in the chart. The code copies the series formula from the last series, then edits the formula to reference the next column for the name and Y value parameters of the formula. Finally a new series is created, and the edited formula is assigned to this series.

Wonderful! One click to add each new series. Well, a few clicks, but it’s still much faster than the old way.

Then I embellished the routine, added some checks (is a chart selected, is the series formula well-formed, are the ranges readily manipulated, etc.), generalized it to series by rows as well as by columns, and ran a few tests. Worked like a charm.

Here’s a sample chart which initially uses the first three data columns as the Y values for its three series. (With the plot area or chart area selected, the source data range for the chart is highlighted.)

Series by Column: Before

Run the macro: press Alt+F8, select the macro from the list, and click Run.

Macro Dialog: AddSeriesToEnd

Here’s the result, which adds the fourth column as the chart’s fourth series.

Series by Column: After

Naturally, this can be changed using the Source Data dialog, or by dragging the colored outlines that indicate the source data. However, if the existing source data is in a pivot table, the chart would be converted to a pivot chart. Also, if the data is on another worksheet (or multiple worksheets), or if it is discontiguous or even more complicated, this is likely to produce unexpected results, or fail completely.

This procedure only requires that the last series have a series formula that it can parse. The added series is related only to the last series in the chart, using the next row or column in the worksheet.

Here is a chart that initially uses the first three rows of the data range for its three series.

Series by Row: Before

After the macro is run, the chart has four series, using the first four rows of the data range.

Series by Row: After

Here’s the VBA procedure. If you’re not sure how to implement it, refer to my introductory VBA tutorial, How To: Use Someone Else’s Macro

Sub AddSeriesToEnd()
  '' Add series to active chart
  '' Use same X values
  '' Use Name and Y values one column to right of last existing series
  Dim sFmla As String
  Dim iParen As Long
  Dim sFmlaArgs As String
  Dim vFmlaArgs As Variant
  Dim sMsg As String
  Dim iOffset As Long
  Dim jOffset As Long
  Dim rValues As Range
  Dim rName As Range

  If ActiveChart Is Nothing Then
    sMsg = "Series Formula too complicated to parse"
    GoTo CantHandle
  End If

  With ActiveChart
    sFmla = .SeriesCollection(.SeriesCollection.count).Formula
    iParen = InStr(sFmla, "(")
    sFmlaArgs = Mid$(sFmla, iParen + 1)
    sFmlaArgs = Left$(sFmlaArgs, Len(sFmlaArgs) - 1)
    vFmlaArgs = Split(sFmlaArgs, ",")

    If UBound(vFmlaArgs) + 1 - LBound(vFmlaArgs) <> 4 Then
      sMsg = "Series Formula too complicated to parse"
      GoTo CantHandle
    End If

    On Error Resume Next
    Set rValues = Range(vFmlaArgs(2))
    Set rName = Range(vFmlaArgs(0))
    On Error GoTo 0

    If rValues Is Nothing Then
      sMsg = "Last series values are not in a range"
      GoTo CantHandle
    End If

    If rValues.Rows.count > 1 And rValues.Columns.count = 1 Then
      ' series in columns
      jOffset = 1
    ElseIf rValues.Rows.count = 1 And rValues.Columns.count > 1 Then
      ' series in rows
      iOffset = 1
    Else
      ' one cell or multiple rows and columns
      sMsg = "Series values range cannot be parsed"
      GoTo CantHandle
    End If

    vFmlaArgs(3) = vFmlaArgs(3) + 1
    If Not rName Is Nothing Then
      vFmlaArgs(0) = rName.Offset(iOffset, jOffset).Address(True, True, xlA1, True)
    Else
      vFmlaArgs(0) = "New Series " & vFmlaArgs(3)
    End If
    vFmlaArgs(2) = rValues.Offset(iOffset, jOffset).Address(True, True, xlA1, True)

    sFmlaArgs = Join(vFmlaArgs, ",")
    sFmla = Left$(sFmla, iParen) & sFmlaArgs & ")"
    With .SeriesCollection.NewSeries
      .Formula = sFmla
    End With
  End With

ExitSub:
  Exit Sub

CantHandle:
  MsgBox sMsg, vbCritical + vbOKOnly
  GoTo ExitSub
End Sub
 


Possibly Related Posts:

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

Learn how to create Excel dashboards.

Comments


Comment from Sebastien
Time: Tuesday, May 12, 2009, 3:48 pm

I always assumed that I could achieve this by using a dynamic named range as the source. I just tried it and unfortunately, the source automatically switches to the name’s resulting range.

At least it does in Excel 2007.

Thanks for the tip.


Comment from Jon Peltier
Time: Tuesday, May 12, 2009, 4:31 pm

It would seem like a viable approach, but a dynamic name has always been converted to its static address in the Source Data dialog. It’s only when used for X and Y values for individual series that the dunamic names are retained.

That’s why we have to resort to tricks like this. And this trick is more flexible, because the data range for the chart doesn’t need to be a nicely defined block of cells for it to work.

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.