Extend Range to Add New Series (VBA)
by Jon Peltier
Monday, May 11th, 2009
Peltier Technical Services, Inc., Copyright © 2010.
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.)

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

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

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.

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

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
Related Posts:
- Update Regular Chart when Pivot Table Updates
- Dynamic Chart using Pivot Table and VBA
- Build an Excel Add-In 2 – Enhanced Functionality
- VBA to Split Data Range into Multiple Chart Series
- Build an Excel Add-In 1 – Basic Routine
- How To: Assign a Macro to a Button or Shape
- Quick VBA Routine: XY Chart with Axis Titles
- Link Chart Text to a Cell
- Split Data Range into Multiple Chart Series without VBA
- Build an Excel Add-In 4 – Create the Dialog
Posted: Monday, May 11th, 2009 under VBA.
Comments: 2
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.