Creating Charts in a Grid
by Jon Peltier
Friday, March 21st, 2008
Peltier Technical Services, Inc., Copyright © 2010.
Licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License.
A few days ago, in Arranging Charts in a Grid, I posted a VBA procedure that arranged all the chart objects on a worksheet into a regular grid. This is pretty nice, but it arranges the charts left to right, then top to bottom, based on the Z stacking order of the charts. If you make the charts in a different order, or change their stacking order, you will get a different positioning of the various charts within the grid.
Often you have your data in a table, and you want to plot them all and arrange them in a nice array. The enhanced VBA procedure in this post kills two birds: creating AND arranging the charts.
This procedure needs a worksheet with the following layout.

The yellow range is named “Settings” (B2:K3 in this example, but it can be any 2-row by 10 column range with the items in this order), and contains many of the adjustable constants from the previous procedure. Placing them in the worksheet makes it easier to adjust them, since you do not need to hunt through the code to change a parameter. The headers in B2:K2 are hard to read in the screen shot, so here they are again, with descriptions:
RowsHigh – Height of each chart, in worksheet rows
ColsWide – Width of each chart, in worksheet columns
FirstRow – Topmost worksheet row covered by charts
FirstCol – Leftmost worksheet column covered by charts
SkipRows – Worksheet rows to skip between rows of charts
SkipCols – Worksheet columns to skip between columns of charts
NAcross – Number of charts per row of charts
FontSize – Font size used in the charts
RowHeight – Height of worksheet rows, in points
ColWidth – Width of worksheet columns, in characters of default font
The green cell is named “DataAll” (B5 in this example). and is the top left cell of a two-row range with the category labels (C5:H5), the series name (B6), and values (C6:H6) for a series which will be plotted on each chart in the grid. The purple cell (B8) is named “DataEach”, and is the top left cell of a N+1 row range with category labels (C8:H8), N series names (B9 downward), and N sets of Y values (C9:H9 and downward), for N series that will be plotted in N charts. In this case there are 12 rows of Y values, and they will appear in 12 charts. The DataAll and DataEach ranges don’t need to be laid out nicely with respect to each other, but it makes it easier to keep track. They do need to be isolated, with empty rows and columns separating them from other data.
The procedure is shown below. The setup worksheet shown above should be activated before running the procedure. A new worksheet is inserted and the charts arrayed on this new sheet. The procedure steps down the DataEach range
Sub MakeGridOfCharts()
' Jon Peltier 3/19/2008
' inputs
Dim vSettings As Variant
Dim rDataAll As Range
Dim rDataEach As Range
' chart size - adjust as desired
Dim nRowsTall As Long
Dim nColsWide As Long
Dim nFontSize As Double
' chart layout - adjust as desired
Dim nChartsPerRow As Long
Dim nSkipRows As Long
Dim nSkipCols As Long
Dim nFirstRow As Long
Dim nFirstCol As Long
Dim wsData As Worksheet
Dim wsChart As Worksheet
Dim iChart As Long
Dim chtob As ChartObject
Dim srs As Series
Dim dWidth As Double
Dim dHeight As Double
Dim rData As Range
Dim dFirstChartTop As Double
Dim dFirstChartLeft As Double
Dim dRowsBetweenChart As Double
Dim dColsBetweenChart As Double
Dim dRowHeight As Double
Dim dColWidth As Double
Application.ScreenUpdating = False
' define worksheets
Set wsData = ActiveSheet
Set wsChart = Worksheets.Add(After:=wsData)
' define data inputs
vSettings = wsData.Range("Settings").Value
Set rDataAll = wsData.Range("DataAll").CurrentRegion
Set rDataEach = wsData.Range("DataEach").CurrentRegion
' extract layout parameters
nRowsTall = vSettings(2, 1)
nColsWide = vSettings(2, 2)
nFirstRow = vSettings(2, 3)
nFirstCol = vSettings(2, 4)
nSkipRows = vSettings(2, 5)
nSkipCols = vSettings(2, 6)
nChartsPerRow = vSettings(2, 7)
nFontSize = vSettings(2, 8)
dRowHeight = vSettings(2, 9)
dColWidth = vSettings(2, 10)
If dRowHeight > 0 Then
wsChart.Rows.RowHeight = dRowHeight
End If
If dColWidth > 0 Then
wsChart.Columns.ColumnWidth = dColWidth
End If
With wsChart.Cells(1, 1)
dWidth = nColsWide * .Width
dHeight = nRowsTall * .Height
dFirstChartLeft = (nFirstCol - 1) * .Width
dFirstChartTop = (nFirstRow - 1) * .Height
dRowsBetweenChart = nSkipRows * .Height
dColsBetweenChart = nSkipCols * .Width
End With
For iChart = 1 To rDataEach.Rows.Count - 1
' create the chart
Set chtob = wsChart.ChartObjects.Add( _
((iChart - 1) Mod nChartsPerRow) * (dWidth + dColsBetweenChart) + dFirstChartLeft, _
Int((iChart - 1) / nChartsPerRow) * (dHeight + dRowsBetweenChart) + dFirstChartTop, _
dWidth, dHeight)
' add standard series (common to all charts)
Set srs = chtob.Chart.SeriesCollection.NewSeries
With srs
.Name = rDataAll.Cells(2, 1)
.Values = rDataAll.Cells(2, 2).Resize(, rDataAll.Columns.Count - 1)
.XValues = rDataAll.Cells(1, 2).Resize(, rDataAll.Columns.Count - 1)
.ChartType = xlLine
.Border.Weight = xlMedium
End With
' add variable series (unique to each chart)
Set srs = chtob.Chart.SeriesCollection.NewSeries
With srs
.Name = rDataEach.Cells(iChart + 1, 1)
.Values = rDataEach.Cells(iChart + 1, 2).Resize(, rDataEach.Columns.Count - 1)
.XValues = rDataEach.Cells(1, 2).Resize(, rDataEach.Columns.Count - 1)
.ChartType = xlLine
.Border.Weight = xlMedium
End With
' format chart
With chtob.Chart
.HasTitle = True
.ChartTitle.Characters.Text = srs.Name
With .ChartArea
.AutoScaleFont = False
.Font.Size = nFontSize
.Border.ColorIndex = 2
End With
.HasLegend = False
With .Axes(xlValue)
.HasMajorGridlines = False
.Border.ColorIndex = 48
End With
With .Axes(xlCategory)
.Border.ColorIndex = 48
With .TickLabels
.Orientation = xlHorizontal
.Offset = 0
End With
End With
With .PlotArea
.Border.ColorIndex = 48
.Interior.ColorIndex = 2
.Left = 0
.Top = 0
.Height = chtob.Chart.ChartArea.Height
.Width = chtob.Chart.ChartArea.Width - 7
End With
With .ChartTitle
.Font.Bold = True
.Top = chtob.Chart.PlotArea.InsideTop
.Left = chtob.Chart.PlotArea.InsideLeft + 3
End With
End With
Next
Application.ScreenUpdating = True
End Sub
By adjusting the values in the yellow cells, you can change the output sheet remarkably. This is starting to look like a dashboard.



Related Posts:
- Arranging Charts in a Grid
- Dynamic Chart using Pivot Table and VBA
- Build an Excel Add-In 2 – Enhanced Functionality
- Stack Columns In Order Of Size With VBA
- Extract Chart Data
- Build an Excel Add-In 3 – Auxiliary Modular Functions
- Update Regular Chart when Pivot Table Updates
- Pivot Table Conditional Formatting with VBA
- Quick VBA Routine: XY Chart with Axis Titles
- Build an Excel Add-In 1 – Basic Routine
Posted: Friday, March 21st, 2008 under VBA.
Comments: 6
Comments
Comment from KC Cheung
Time: Sunday, December 28, 2008, 8:11 pm
Hi
Can you advise why I need to add “On Error Resume Next” before
“with .plotarea
.border.colorindex=48
.interior.colorindex=2
.left=0″
in order to get pass .left =0
please?
Comment from Jon Peltier
Time: Sunday, December 28, 2008, 8:56 pm
KC -
I have occasionally had issues in code changing the properties of borders of chart elements, typically of axes or gridlines. I often insert this before editing borders. Another workaround, which isn’t particularly reliable but works in a few more cases, is to select the chart element, then format the border.
I wish I could answer this question more definitively.
Comment from Ivan
Time: Thursday, June 3, 2010, 6:12 am
Dear Mr. Peltier,
I tried to replicate this particular example in the workbook but it always finishes with an error:
Runtime error “9″ – Subscript out of range.
I changed name of the cell B2 to RowsTall as it was written in the procedure. However when I try to run debugger it seems that it breaks at the line :
nRowsTall = vSettings(2, 1)
Regards, Ivan
Comment from Jon Peltier
Time: Thursday, June 3, 2010, 6:35 am
Ivan -
This error indicates a problem identifying the range with the settings. Did you apply the name “Settings” to the range containing the settings?
Comment from Ivan
Time: Thursday, June 3, 2010, 7:10 am
Indeed it was. Thank for your input. Range was not properly addressed.
But now some unknown error appears:
Run-time error: -2147467259(8004005)
Automation error
Unspecified error
And it creates just the first chart and then breaks.
Regards, Ivan
Comment from Ivan
Time: Thursday, June 3, 2010, 7:35 am
Suddnely it worked perfectly just out og nowhere, Just after I changed setting for
legend:
.HasLegend = True
.SetElement (msoElementLegendBottom)
I have no idea how. As you probably see I am absloute begginer with VBA.
Thank you for your time very much !
Regards, Ivan



















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.