Forum Discussion
JJ Eggers
Oct 19, 2017Copper Contributor
I am trying to make a separate charts for each row on the same sheet.
I am having an issue with making the charts uniform.
Row 1 is the Titles for the columns
Row 2 - 5 is what I am looking to make separate charts for. Well this works well with Row 2, but when I try to make charts for 3-5 the charts do not look uniform. The titles from Row 1 do not carry over.
Is there a way to copy the chart from Row 2, then edit the copied chart so instead of pulling data from C2 it gets the data from C3?
23 Replies
Sort By
I wrote a little VBA routine to take a chart that uses Y values in one row, and make a copy of the chart, use the next row for the Y values (and name if it uses a cell for the name), and repeat until the next row has no numeric values. Here's how it looks at the start:
Here is the code:
Sub DuplicateActiveChartOncePerRow() If ActiveChart Is Nothing Then MsgBox "Select a chart and try again!", vbExclamation + vbOKOnly GoTo ExitSub End If Dim nCharts As Long nCharts = ActiveSheet.ChartObjects.Count Dim OriginalChart As Chart Set OriginalChart = ActiveChart ' SERIES formula Dim sFormula As String sFormula = OriginalChart.SeriesCollection(1).Formula ' formula arguments only sFormula = Mid$(Left$(sFormula, Len(sFormula) - 1), InStr(sFormula, "(") + 1) ' array of arguments Dim vFormula As Variant vFormula = Split(sFormula, ",") ' series name - first argument Dim sName As String sName = vFormula(LBound(vFormula)) Dim rName As Range On Error Resume Next Set rName = Range(sName) On Error GoTo 0 Dim bNameIsRange As Boolean bNameIsRange = Not rName Is Nothing ' y values - third argument Dim sYVals As String sYVals = vFormula(LBound(vFormula) + 2) Dim rYVals As Range On Error Resume Next Set rYVals = Range(sYVals) On Error GoTo 0 If rYVals Is Nothing Then MsgBox "Y Values Are Not in a Range!", vbExclamation + vbOKOnly GoTo ExitSub End If Dim iChart As Long iChart = 1 Do ' loop until we run out of Y values If WorksheetFunction.Count(rYVals.Offset(iChart)) = 0 Then MsgBox "Finished!", vbExclamation + vbOKOnly GoTo ExitSub End If ' make copy of original chart OriginalChart.Parent.Copy Do ' loop to avoid error because sometimes clipboard isn't ready to paste DoEvents On Error Resume Next ActiveSheet.Paste On Error GoTo 0 If ActiveSheet.ChartObjects.Count >= nCharts + iChart Then Exit Do Loop Dim NewChart As Chart Set NewChart = ActiveSheet.ChartObjects(ActiveSheet.ChartObjects.Count).Chart NewChart.Parent.Left = OriginalChart.Parent.Left NewChart.Parent.Top = OriginalChart.Parent.Top + iChart * rYVals.Height ' change Y values and name in new chart With NewChart.SeriesCollection(1) .Values = rYVals.Offset(iChart) If bNameIsRange Then .Name = "=" & rName.Offset(iChart).Address(, , , True) End If End With iChart = iChart + 1 Loop ExitSub: End Sub
And here is the end result:
- BGrover42Copper Contributor
I have been looking for something like this forever, except my scenario is with XY plots and I want to plot in groups of n. For example, my time is in column B and my data goes through column CT. I want to have 3 consecutive columns per graph. Can something similar be done for this or is that too complicated for excel?
Thanks!
- JonPeltierMVPIron ContributorAFK so I can't give you code now. It sounds like you want column B as X values for all charts, then columns C-E for Y values for the first chart, F-H for the second, etc. It's not really any more complicated than the earlier example.
- jasper1984Copper Contributor
Hello- I found this code very very helpful so thank you very much for sharing. I have modified it to include two data series. However, I am now struggling with adding a chart title. How can I make the chart title link to a column and change with each new chart generated per row? (As your posted code does but for two data series.) I can post my attempt below -
Sub DuplicateActiveChartOncePerRow()
If ActiveChart Is Nothing Then
MsgBox "Select a chart and try again!", vbExclamation + vbOKOnly
GoTo ExitSub
End If
Dim nCharts As Long
nCharts = ActiveSheet.ChartObjects.Count
Dim OriginalChart As Chart
Set OriginalChart = ActiveChart
' SERIES formula
Dim sFormula As String
Dim sFormula2 As String
sFormula = OriginalChart.SeriesCollection(1).Formula
sFormula2 = OriginalChart.SeriesCollection(2).Formula
' formula arguments only
sFormula = Mid$(Left$(sFormula, Len(sFormula) - 1), InStr(sFormula, "(") + 1)
sFormula2 = Mid$(Left$(sFormula2, Len(sFormula2) - 1), InStr(sFormula2, "(") + 1)
' array of arguments
Dim vFormula As Variant
Dim vFormula2 As Variant
vFormula = Split(sFormula, ",")
vFormula2 = Split(sFormula2, ",")
' series name - first argument
Dim sName As String
sName = vFormula(LBound(vFormula))
Dim rName As Range
On Error Resume Next
Set rName = Range(sName)
On Error GoTo 0
Dim bNameIsRange As Boolean
bNameIsRange = Not rName Is Nothing
Dim sName2 As String
sName2 = vFormula2(LBound(vFormula2))
Dim rName2 As Range
On Error Resume Next
Set rName2 = Range(sName2)
On Error GoTo 0
Dim bNameIsRange2 As Boolean
bNameIsRange2 = Not rName2 Is Nothing
' y values - third argument
Dim sYVals As String
sYVals = vFormula(LBound(vFormula) + 2)
Dim rYVals As Range
On Error Resume Next
Set rYVals = Range(sYVals)
On Error GoTo 0
If rYVals Is Nothing Then
MsgBox "Y Values Are Not in a Range!", vbExclamation + vbOKOnly
GoTo ExitSub
End If
Dim sYVals2 As String
sYVals2 = vFormula2(LBound(vFormula2) + 2)
Dim rYVals2 As Range
On Error Resume Next
Set rYVals2 = Range(sYVals2)
On Error GoTo 0
If rYVals2 Is Nothing Then
MsgBox "Y Values Are Not in a Range!", vbExclamation + vbOKOnly
GoTo ExitSub
End If
Dim iChart As Long
iChart = 1
Do
' loop until we run out of Y values
If WorksheetFunction.Count(rYVals.Offset(iChart)) = 0 Then
MsgBox "Finished!", vbExclamation + vbOKOnly
GoTo ExitSub
End If
' make copy of original chart
OriginalChart.Parent.Copy
Do
' loop to avoid error because sometimes clipboard isn't ready to paste
DoEvents
On Error Resume Next
ActiveSheet.Paste
On Error GoTo 0
If ActiveSheet.ChartObjects.Count >= nCharts + iChart Then Exit Do
Loop
Dim NewChart As Chart
Set NewChart = ActiveSheet.ChartObjects(ActiveSheet.ChartObjects.Count).Chart
NewChart.Parent.Left = OriginalChart.Parent.Left
NewChart.Parent.Top = OriginalChart.Parent.Top + iChart * rYVals.Height
' change Y values and name in new chart
With NewChart.SeriesCollection(1)
.Values = rYVals.Offset(iChart)
If bNameIsRange Then
.Name = "=" & rName.Offset(iChart).Address(, , , True) & "!" & Cells(iChart, 3).Address(, , , True)
End If
End With
With NewChart.SeriesCollection(2)
.Values = rYVals2.Offset(iChart)
End With
iChart = iChart + 1
Loop
ExitSub:
End SubBefore
Dim iChart As Long
insert this block of code:
' chart title Dim sTitle As String sTitle = OriginalChart.ChartTitle.Formula sTitle = Mid$(sTitle, 2) ' trim leading = Dim rTitle As Range On Error Resume Next Set rTitle = Range(sTitle) On Error GoTo 0 Dim bTitleIsRange As Boolean bTitleIsRange = Not rTitle Is Nothing
then before
iChart = iChart + 1
insert this code:
If bTitleIsRange Then NewChart.ChartTitle.Formula = "=" & rTitle(Offset(iChart).Address(, , , True) End If
- Owen_BoyleCopper ContributorThat looks great! It's exactly what I'm trying to do; the columns (A,B,C,D,E) are the stages in a process. The numbers in the cells are the amount of product at each stage in the process. The rows are different times. So each graph is a snapshot of the production line. I want to see how it progresses over time, so I had a movie where each graph is a frame. The more frames, the more fine-grained the visualisation, so I need an automatic process to turn the data from the process monitor into individual frames. This looks like it could that!
I'll try it and get back to you...
Hi,
Right click on the chart you copied, Select Data and edit the Series
- JJ EggersCopper Contributor
The chart will not copy on the same sheet.
That doesn't matter