Forum Discussion
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
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...
- SergeiBaklanDiamond Contributor
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.
- SergeiBaklanDiamond Contributor
That doesn't matter