I am trying to create a macro in VBA that will take a large data set in Sheet1 (called Raw Data) and create a XY scatter plot for every 8000 data points in another worksheet. The macro will also need to label each graph with what range it represents (ie 1-8000, 8001-16000 etc).
The large data set consists of temperature readings from 8 different thermocouples which record data every second. The number of data points will vary based on how long the experiment was run. The temperature values are stored in columns C through J and the time parameter is in column T.
What I have right now is a "batch" approach where the macro is set up to graph data in chunks of 8000 up to 32000 (4 different plots). This approach is not practical because the data set will almost always be significantly larger than 32000 points.
What I would like the macro to do is automatically graph and label every 8000 data points until there is no more data to graph.
I have been looking into using a loop but I am new to writing code and not sure how.
Any suggestions or help is greatly appreciated!
Here's some of my batch code:
'creates graph for first 8000 seconds in TC 1
Sheets("TC 1").Select
ActiveSheet.Shapes.AddChart.Select
ActiveChart.ChartType = xlXYScatterSmoothNoMarkers
ActiveChart.SeriesCollection.NewSeries
ActiveChart.SeriesCollection(1).Name = "='Raw Data'!$C$1"
ActiveChart.SeriesCollection(1).XValues = "='Raw Data'!$t$2:$t$8000"
ActiveChart.SeriesCollection(1).Values = "='Raw Data'!$C$2:$C$8000"
With ActiveChart
'X axis name
.axes(xlCategory, xlPrimary).HasTitle = True
.axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "Time (seconds)"
'y-axis name
.axes(xlValue, xlPrimary).HasTitle = True
.axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "Temperature (F)"
'chart title
.HasTitle = True
.ChartTitle.Text = ("1-8000 seconds")
'adjusts the size/placement of graph and x-axis values
Set RngToCover = ActiveSheet.Range("A1:T25")
Set ChtOb = ActiveChart.Parent
ChtOb.Height = RngToCover.Height ' resize
ChtOb.Width = RngToCover.Width ' resize
ChtOb.Top = RngToCover.Top ' repositon
ChtOb.Left = RngToCover.Left ' reposition
ActiveChart.axes(xlCategory).Select
ActiveChart.axes(xlCategory).MinimumScale = 0
ActiveChart.axes(xlCategory).MaximumScale = 8000
End With
Here is what I came up with.
The macro calculates the total number of used rows, then divides that number by 8000.
The For...Next loop runs from 0 to the total rows divided by 8000.
Dim i As Integer
Dim j As Variant
Dim p As Integer
Dim start_row As Long
Dim end_row As Long
Dim RngToCover As Range
Dim ChtOb As ChartObject
i = Worksheets("Raw Data").UsedRange.Rows.Count
j = i / 8000
Sheets("TC 1").Activate
For p = 0 To j
start_row = (p * 8000) + 2
end_row = ((p + 1) * 8000) + 1
Set ChtOb = ActiveSheet.ChartObjects.Add(Left:=20, Width:=800, Top:=20, Height:=250)
ChtOb.Chart.ChartType = xlXYScatterSmoothNoMarkers
ChtOb.Activate
With ActiveChart.SeriesCollection.NewSeries
.Name = Worksheets("Raw Data").Cells(1, 3)
.XValues = Worksheets("Raw Data").Range(Worksheets("Raw Data").Cells(start_row, 20), Worksheets("Raw Data").Cells(end_row, 20))
.Values = Worksheets("Raw Data").Range(Worksheets("Raw Data").Cells(start_row, 3), Worksheets("Raw Data").Cells(end_row, 3))
End With
Next
It sounds like you already understand how to generate the charts for a given 8000 records. Below is a WHILE loop to keep running your export code until it finds an empty cell in the source column for the X-axis (column T).
Dim i As Integer
Dim ws As Worksheet
i = 2
Set ws = ThisWorkbook.Worksheets("Raw Data")
While ws.Cells(i, 20).Value <> ""
''' Create Chart for Next Data Set Starting at Row i (up to 8000 records)
i = i + 8000
Wend
Related
My code should create one chart for every row of a data base. This data base is in a different sheet. Since that data base should change the number of columns I'm counting how many columns and changing the data source. Every time I run the code it comes with an error in the SetSourceData.
I couldn't find what am I doing wrong.
Can someone help me find a solution?
Sub createColumnChartMatriz12()
Dim ChartName As String
Dim Row As Integer
Dim ChartRow As Integer
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("Matriz 1")
Dim k As Long
Dim z As Long
k = sh.Range("A1", sh.Range("A1").End(xlDown)).Rows.Count
z = sh.Cells(1, sh.Columns.Count).End(xlToLeft).Column - 4
ThisWorkbook.Sheets("Matriz1Chart").Select
Cells.Select
Selection.RowHeight = 15.5
Cells(1, 1).Select
ChartRow = 49
Row = 2
For Row = 2 To k
ChartName = "Utilização no Período " & sh.Cells(Row, 1).Value
ActiveSheet.Shapes.AddChart2(201, xlColumnClustered).Select
With ActiveChart
.SetSourceData Source:=sh.Range(Cells(Row, 4), Cells(Row, z)), _
PlotBy:=xlRows
.FullSeriesCollection(1).XValues = "='Matriz 1'!$D$1:$AM$1"
.Parent.Height = Range("A1:A15").Height
.Parent.Width = Range("A1:J1").Width
.Parent.Top = Range("A" & ChartRow).Top
.Parent.Left = Range("A" & ChartRow).Left
.HasTitle = True
.ChartTitle.Text = ChartName
.Axes(xlCategory, xlPrimary).HasTitle = True
.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "Meses"
.Axes(xlValue, xlPrimary).HasTitle = True
.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "Utilização"
.Axes(xlCategory, xlPrimary).TickLabels.NumberFormat = "mm-yyyy"
End With
ChartRow = ChartRow + 16
Next
End Sub
Not sure if this is your only problem, but when you access a Range by providing two cells (Cells are in fact also Ranges), you have to qualify these cells also.
Your statement sh.Range(Cells(Row, 4), Cells(Row, z)) tries to define a Range object of sheet "Matriz 1" (saved in variable sh), but Cells(Row, 4) refers to the active sheet. That makes the range itself invalid and causes the failure of the .SetSourceData command.
You should write sh.Range(sh.Cells(Row, 4), sh.Cells(Row, z)) instead. As a general advice: split the logic of such complicated command - it is much easier to debug and figure out what fails. In your case, first define the range, write it into a variable and after that assign it to the chart:
With ActiveChart
dim chartRange as Range
set chartRange = sh.Range(sh.Cells(Row, 4), sh.Cells(Row, z))
.SetSourceData Source:=chartRange, PlotBy:=xlRows
...
end with
or, if you prefer (but note the leading .)
With ActiveChart
dim chartRange as Range
with sh
set chartRange = .Range(.Cells(Row, 4), .Cells(Row, z))
end with
.SetSourceData Source:=chartRange, PlotBy:=xlRows
...
end with
I have a list of data and I need to generate a chart for every two lines and give a chart title associated to the 1st line. Example of the data is:
Example
And so on.
The code I am using to create the charts is:
Sub loopChart()
Dim mychart As Chart
Dim myRange As Range
Dim c As Integer
Dim r As Integer
Dim s As Integer
Dim ttl As String
r = 2
While r <= 10 '1=dataSource1, 4=dataSource2, 7=dataSource3
'set data source for the next chart
With Worksheets("Sheet9")
Set myRange = .Range(.Cells(r, 2), .Cells(r + 1, 14))
End With
'create chart
Sheets("Chart").Select
ActiveSheet.Shapes.AddChart.Select
With ActiveChart
ttl = Range("A" & r)
.ChartType = xlLineMarkers 'xlLine
.SetSourceData Source:=myRange, PlotBy:=xlRows 'sets source data for graph including labels
.SetElement (msoElementLegendRight) 'including legend
.HasTitle = True
'dimentions & location:
.Parent.Top = 244 'defines the coordinates of the top of the chart
'.Parent.Left = r * 150 'defines the coordinates for the left side of the chart
.Parent.Height = 200
.Parent.Width = 300
.ChartTitle.Formula = ttl
End With
r = r + 2
Wend
End Sub
So, the 1st chart that generates should get the title on row 2, next chart should have title of row 4...
I always get the Chart title on 1st chart that generates but not on any of the other charts. Can anyone please help me on this?
Please fix below.
ttl = Range("A" & r)
to
ttl = Worksheets("Sheet9").Range("A" & r).Value
I think #Dy.Lee answer will do the trick but to go a bit further :
Try avoiding using .select
Proposed workaround :
Sub loopChart()
Dim Ch As Chart
Dim Sh1 As Worksheet: Set Sh1 = Sheets("Sheet9")
Dim Sh2 As Worksheet: Set Sh2 = Sheets("Chart")
Dim L As Integer
L = 0
For i = 2 To 18 Step 2
Set Ch = Sh2.Shapes.AddChart.Chart
Ch.SetSourceData Sh1.Range(Sh1.Cells(i, 2), Sh1.Cells(i + 1, 14))
Ch.ChartType = xlLineMarkers
Ch.SetElement (msoElementLegendRight)
Ch.HasTitle = True
Ch.Parent.Top = 244
Ch.Parent.Height = 200
Ch.Parent.Width = 300
Ch.Parent.Left = L
Ch.ChartTitle.Caption = Sh1.Cells(i, 1).Value
L = L + 300
Next i
End Sub
Your code will create each graph at the same location so you'll see only one (the last one) hence the Ch.Parent.Left line with variable value.
I have a code that gets data from a sheet and creates a graph. In the source sheet, each column is a series, and the number of series may change.
What my code does: it reads the used ranges so that it can graph the values.
Obs1: For 2 of the time series I create, the data is annualized, so as I count backwards for the calculation, if the data before is less than one year, the code shows as "Not Enough Data".
Problem: If I run the code with 2 time series (2 columns), I get two lines in the charts. But if I then delete one of the series and run it again, I get one line with values and a second empty line in the chart.
Question: How can this problem be solved?
What I already tried: I am trying to change the way I reference the ranges, so that it rerun the code, it returns to the graph only lines that have values. Issue is I cannot find a way to properly reference the range like that.
Relevant part of the code:
Function Grapher(ChartSheetName As String, SourceWorksheet As String, ChartTitle As String, secAxisTitle As String)
Dim lColumn As Long, lRow As Long
Dim LastColumn As Long, LastRow As Long
Dim RetChart As Chart
Dim w As Workbook
Dim RetRange As Range
Dim chrt As Chart
Dim p As Integer
Dim x As Long, y As Long
Dim numMonth As Long
Dim d1 As Date, d2 As Date
Dim i As Long
Set w = ThisWorkbook
'find limit
LastColumn = w.Sheets(SourceWorksheet).Cells(1, w.Sheets(SourceWorksheet).Columns.Count).End(xlToLeft).column
LastRow = w.Sheets(SourceWorksheet).Cells(w.Sheets(SourceWorksheet).Rows.Count, "A").End(xlUp).Row
'check for sources that do not have full data
'sets the range
i = 3
If SourceWorksheet = "Annualized Ret" Or SourceWorksheet = "Annualized Vol" Then
Do While w.Worksheets(SourceWorksheet).Cells(i, 2).Text = "N/A"
i = i + 1
Loop
'##### this is the part I believe is giving the problem:
'##### the way to reference the last cell keeps getting the number of columns (for the range) from the original column count.
Set RetRange = w.Worksheets(SourceWorksheet).Range(w.Worksheets(SourceWorksheet).Cells(i, 1), w.Worksheets(SourceWorksheet).Cells.SpecialCells(xlLastCell)) '****************
Else
Set RetRange = w.Sheets(SourceWorksheet).UsedRange
'Set RetRange = w.Sheets(SourceWorksheet).Range("A1:" & Col_Letter(LastColumn) & LastRow)
End If
'''''''''''''''''''''''
For Each chrt In w.Charts
If chrt.Name = ChartSheetName Then
Set RetChart = chrt
RetChart.Activate
p = 1
End If
Next chrt
If p <> 1 Then
Set RetChart = Charts.Add
End If
'count the number of months in the time series, do the ratio
d1 = w.Sheets(SourceWorksheet).Range("A2").Value
d2 = w.Sheets(SourceWorksheet).Range("A" & LastRow).Value
numMonth = TestDates(d1, d2)
x = Round((numMonth / 15), 1)
'ratio to account for period size
If x < 3 Then
y = 1
ElseIf x >= 3 And x < 7 Then
y = 4
ElseIf x > 7 Then
y = 6
End If
'create chart
With RetChart
.Select
.ChartType = xlLine
.HasTitle = True
.ChartTitle.Text = ChartTitle
.SetSourceData Source:=RetRange
.Axes(xlValue).MaximumScaleIsAuto = True
.Axes(xlCategory, xlPrimary).HasTitle = True
.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "Date"
.Axes(xlValue, xlPrimary).HasTitle = True
.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = secAxisTitle
.Name = ChartSheetName
.SetElement (msoElementLegendBottom)
.Axes(xlCategory).TickLabelPosition = xlLow
.Axes(xlCategory).MajorUnit = y
.Axes(xlCategory).MajorUnitScale = xlMonths
'sets header names for modified sources
If SourceWorksheet = "Drawdown" Then
For lColumn = 2 To LastColumn
.FullSeriesCollection(lColumn - 1).Name = "=DD!$" & Col_Letter(lColumn) & "$1"
.FullSeriesCollection(lColumn - 1).Values = "=DD!$" & Col_Letter(lColumn) & "$3:$" & Col_Letter(lColumn) & "$" & LastRow
Next lColumn
ElseIf SourceWorksheet = "Annualized Ret" Then
For lColumn = 2 To LastColumn
.FullSeriesCollection(lColumn - 1).Name = "='Annualized Ret'!$" & Col_Letter(lColumn) & "$1"
Next lColumn
ElseIf SourceWorksheet = "Annualized Vol" Then
For lColumn = 2 To LastColumn
.FullSeriesCollection(lColumn - 1).Name = "='Annualized Vol'!$" & Col_Letter(lColumn) & "$1"
Next lColumn
End If
End With
End Function
Obs2: My code is currently functional (there are some functions I haven't added, so as not to waste more space).
Obs3: This is the problem when I decrease the number of columns (data series):
Since I could find no better, more elegant way to approach this problem (even the tables where yielding the same error), I corrected, by explicitly deleting the extra series in the end, based on their names.
Obs: If the Series contained no data, the new inserted code will change that series name to one of the ones below, and delete that series altogether.
Code to be added to the end:
'deleting the extra empty series
Dim nS As Series
'this has to be fixed. For a permanent solution, try to use tables
For Each nS In RetChart.SeriesCollection
If nS.Name = "Series2" Or nS.Name = "Series3" Or nS.Name = "Series4" Or nS.Name = "Series5" Or nS.Name = "Series6" Or nS.Name = "Series7" Or nS.Name = "Series8" Or nS.Name = "" Then
nS.Delete
End If
Next nS
I am extremely new to excel vba and am using this first attempt as a learning experience. I am hoping to make a matrix of scatterplots in a separate sheet from the sheet they are taking the data from.
So heres a kind of schematic of the graphs I would like to be generated in an excel sheet. This represents a single satterplot [x-axis(ColumnletterRownumber), y-axis(ColumnletterRownumber)]
[(S2:S372),(AW2:AW372)] [(T2:T372),(AW2:AW372)] [(U2:U372),(AW2:AW372)]
[(S2:S372),(AX2:AX372)] [(T2:T372),(AX2:AX372)] [(U2:U372),(AX2:AX372)]
[(S2:S372),(AY2:AY372)] [(T2:T372),(AY2:AY372)] [(U2:U372),(AY2:AY372)]
[(S2:S372),(AZ2:AZ372)] [(T2:T372),(AZ2:AZ372)] [(U2:U372),(AZ2:AZ372)]
So those would be the scatterplots on the next sheet. Obviously I need a lot more graphs than that but that should give you an idea.
Here's what I got so far:
Sorry in advance for the large amount of commented out things... those are ideas I think might help but I haven't gotten them to work.
Sub SPlotMatrix1()
Application.ScreenUpdating = False
'SPlotMatrix1 Macro
'Define the Variables
'---------------------
Dim Xaxis As range
Dim Yaxis As range
''Initialize the Variables
''-------------------------
Set Xaxis = range("S2:S372")
Set Yaxis = range("AW2:AW372")
'Tell macro when to stop
'-----------------------
Dim spot As Long
spot = 0
Do Until spot > 50
Sheets("2ndFDAInterimData").Select
''MAIN LOOP
'Graph1
'-------
'Selection Range
range("S2:S372,AW2:AW372").Select
'range("Xaxis,Yaxis").Select
'range("AW1:AW372",S1:S372").Offset(0, rng).Select
'range("AW1:AW372", 0).Select
'range("0,S1:S372").Offset(0, rng).Select
range("S372").Activate
'Select Graph Range
ActiveSheet.Shapes.AddChart2(240, xlXYScatter).Select
' ActiveChart.SetSourceData Source:=range( _
"'2ndFDAInterimData'!$AW$1:$AW$372,'2ndFDAInterimData'!$S$1:$S$372")
'Graph Title
ActiveChart.SetElement (msoElementChartTitleAboveChart)
ActiveChart.FullSeriesCollection(1).Select
ActiveChart.FullSeriesCollection(1).name = "='2ndFDAInterimData'!$DL$1"
'Add Trendline
ActiveChart.Axes(xlValue).MajorGridlines.Select
ActiveChart.FullSeriesCollection(1).Trendlines.Add Type:=xlLinear, Forward _
:=0, Backward:=0, DisplayEquation:=0, DisplayRSquared:=0, name:= _
"Linear (Ave.Score)"
ActiveChart.FullSeriesCollection(1).Trendlines.Add Type:=xlLinear, Forward _
:=0, Backward:=0, DisplayEquation:=0, DisplayRSquared:=0, name:= _
"Linear (Ave.Score)"
ActiveChart.FullSeriesCollection(1).Trendlines(2).Select
Selection.DisplayRSquared = True
'Move Rsquare Label to Corner
ActiveChart.FullSeriesCollection(1).Trendlines(2).DataLabel.Select
Selection.Left = 30.114
Selection.Top = 13.546
'Format Trendline
ActiveChart.FullSeriesCollection(1).Trendlines(2).Select
With Selection.Format.Line
.Visible = msoTrue
.ForeColor.ObjectThemeColor = msoThemeColorText1
.ForeColor.TintAndShade = 0
.ForeColor.Brightness = 0
.Transparency = 0
End With
With Selection.Format.Line
.Visible = msoTrue
.DashStyle = msoLineSolid
End With
ActiveChart.ChartArea.Select
With Selection.Format.Line
.Visible = msoTrue
.Weight = 1.75
End With
'Resize Graph
ActiveChart.Parent.Height = 180
ActiveChart.Parent.Width = 239.76
'Y axis scale
ActiveChart.FullSeriesCollection(1).Select
ActiveChart.Axes(xlValue).Select
ActiveChart.Axes(xlValue).MaximumScale = 100
'Move graph to center (for the purposes of design and debugging)
ActiveChart.Parent.Cut
range("V4").Offset(spot, 0).Select
ActiveSheet.Paste
' 'Move Graph to other sheet
' ActiveChart.Parent.Cut
' Sheets("graphs").Select
' range("A1").Offset(spot, 0).Select
' ActiveSheet.Paste
spot = spot + 14
Loop
Application.ScreenUpdating = True
End Sub
I've gotten to the point where I am creating a number of the same graphs in a row or column if I want. But I can't successfully get the graphs ranges to change so that they are plotting different data.
Please help, let me know if I can further clarify. Thank you!
You can define the data with a couple simple loops. Create the chart and embellish it within the inner loop.
Sub InsertMultipleCharts()
' data particulars
Dim wksData As Worksheet
Const Xcol1 As Long = 19 ' column S
Const Xcol2 As Long = 21 ' column U
Const Ycol1 As Long = 49 ' column AW
Const Ycol2 As Long = 52 ' column AZ
Const Row1 As Long = 2
Const Row2 As Long = 372
' chart dimensions
Const FirstChartLeft As Long = 50
Const FirstChartTop As Long = 50
Const ChartHeight As Long = 180
Const ChartWidth As Long = 240
' working variables
Dim wksChart As Worksheet
Dim cht As Chart
Dim Xrange As Range
Dim Yrange As Range
Dim Xcol As Long
Dim Ycol As Long
' define sheets
Set wksData = ActiveSheet
Set wksChart = Worksheets.Add
' loop X
For Xcol = Xcol1 To Xcol2
' define x values
Set Xrange = Range(wksData.Cells(Row1, Xcol), wksData.Cells(Row2, Xcol))
' loop Y
For Ycol = Ycol1 To Ycol2
' define y values
Set Yrange = Range(wksData.Cells(Row1, Ycol), wksData.Cells(Row2, Ycol))
' insert chart
Set cht = wksChart.Shapes.AddChart2(Style:=240, XlChartType:=xlXYScatter, _
Left:=FirstChartLeft + (Xcol - Xcol1) * ChartWidth, _
Top:=FirstChartTop + (Ycol - Ycol1) * ChartHeight, _
Width:=ChartWidth, Height:=ChartHeight).Chart
' assign data to chart
cht.SetSourceData Source:=Union(Xrange, Yrange)
' chart title
cht.HasTitle = True
With cht.ChartTitle.Font
.Size = 12
.Bold = False
End With
' axis scale
cht.Axes(xlValue).MaximumScale = 100
' legend
cht.HasLegend = False
' series: name, trendline, and Rsquared
With cht.SeriesCollection(1)
.Name = "Series Name" '''' don't know where these are coming from
With .Trendlines.Add(Type:=xlLinear, DisplayRSquared:=True).DataLabel
.Format.Line.DashStyle = msoLineSolid
.Top = cht.PlotArea.InsideTop
.Left = cht.PlotArea.InsideLeft
End With
End With
Next
Next
End Sub
Macro recorder code is messy, but it gives you syntax.
Try using the macro recorder to edit an existing range so you get the code for setting the ranges for X, Y and the range name and size.
Once recorded you can swap out the new ranges as variables to get the new charts.
I wrote a macro to produce a histogram, given a certain selection. The code for the macro looks like this
Sub HistogramHelper(M As Range)
Dim src_sheet As Worksheet
Dim new_sheet As Worksheet
Dim selected_range As Range
Dim r As Integer
Dim score_cell As Range
Dim num_scores As Integer
Dim count_range As Range
Dim new_chart As Chart
Set selected_range = M
Set src_sheet = ActiveSheet
Set new_sheet = Application.Sheets.Add(After:=src_sheet)
title = selected_range.Cells(1, 1).Value
new_sheet.Name = title
' Copy the scores to the new sheet.
new_sheet.Cells(1, 1) = "Data"
r = 2
For Each score_cell In selected_range.Cells
If Not IsNumeric(score_cell.Text) Then
'MsgBox score_cell.Text
Else
new_sheet.Cells(r, 1) = score_cell
End If
r = r + 1
Next score_cell
num_scores = selected_range.Count
'Creates the number of bins to 5
'IDEA LATER: Make this number equal to Form data
Dim num_bins As Integer
num_bins = 5
' Make the bin separators.
new_sheet.Cells(1, 2) = "Bins"
For r = 1 To num_bins
new_sheet.Cells(r + 1, 2) = Str(r)
Next r
' Make the counts.
new_sheet.Cells(1, 3) = "Counts"
Set count_range = new_sheet.Range("C2:C" & num_bins + 1)
'Creates frequency column for all counts
count_range.FormulaArray = "=FREQUENCY(A2:A" & num_scores + 1 & ",B2:B" & num_bins & ")"
'Make the range labels.
new_sheet.Cells(1, 4) = "Ranges"
For r = 1 To num_bins
new_sheet.Cells(r + 1, 4) = Str(r)
new_sheet.Cells(r + 1, 4).HorizontalAlignment = _
xlRight
Next r
' Make the chart.
Set new_chart = Charts.Add()
With new_chart
.ChartType = xlBarClustered
.SetSourceData Source:=new_sheet.Range("C2:C" & _
num_bins + 1), _
PlotBy:=xlColumns
.Location Where:=xlLocationAsObject, _
Name:=new_sheet.Name
End With
With ActiveChart
.HasTitle = True
.HasLegend = False
.ChartTitle.Characters.Text = title
.Axes(xlCategory, xlPrimary).HasTitle = True
.Axes(xlCategory, _
xlPrimary).AxisTitle.Characters.Text = "Scores"
.Axes(xlValue, xlPrimary).HasTitle = True
.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text _
_
= "Out of " & num_scores & " responses"
' Display score ranges on the X axis.
.SeriesCollection(1).XValues = "='" & _
new_sheet.Name & "'!R2C4:R" & _
num_bins + 1 & "C4"
End With
ActiveChart.SeriesCollection(1).Select
With ActiveChart.ChartGroups(1)
.Overlap = 0
.GapWidth = 0
.HasSeriesLines = False
.VaryByCategories = False
End With
r = num_scores + 2
new_sheet.Cells(r, 1) = "Average"
new_sheet.Cells(r, 2) = "=AVERAGE(A1:A" & num_scores & _
")"
r = r + 1
new_sheet.Cells(r, 1) = "StdDev"
new_sheet.Cells(r, 2) = "=STDEV(A1:A" & num_scores & ")"
End Sub
I am currently using a WorkBook that looks like this:
Eventually, I want to produce a macro that automatically iterates over each column, calling the Histogram Helper function with each column, producing multiple histograms over multiple worksheets. For now, I'm just trying to test putting in TWO ranges into HistogramHelper, like so:
Sub GenerateHistograms()
HistogramHelper Range("D3:D30")
HistogramHelper Range("E3:E30")
End Sub
However, upon running the Macro, I get a dialog box with the error number 400, one of the sheets is produced successfully with the worksheet title Speaker, and another sheet is produced with a numerical title and no content.
What is going on?
Edit: The workbook in question: https://docs.google.com/file/d/0B6Gtk320qmNFbGhMaU5ST3JFQUE/edit?usp=sharing
Edit 2- Major WTF?:
I switched the beginning FOR block to this for debugging purposes:
For Each score_cell In selected_range.Cells
If Not IsNumeric(score_cell.Text) Then
MsgBox score_cell.Address 'Find which addresses don't have numbers
Else
new_sheet.Cells(r, 1) = score_cell
End If
r = r + 1
Next score_cell
Whenever you run this, no matter which range you put as the second Macro call (in this case E3:E30) the program prints out that each cell $E$3- $E$30 is a non-text character. Why oh why?
Don't you need this?
Sheets(title).Activate
TIP: for this kind of recursive implementations implying many creations/deletions and getting every day more and more complex, I wouldn't ever rely on "Active" elements (worksheet, range, etc.), but in specific ones (sheets("whatever")) avoiding problems and easing the debugging.
------------------------ UPDATE
No, apparently, you don't need it.
Then, update selected_range.Cells(1, 1).Value such that it takes different values for each new worksheet, because this is what is provoking the error: creating two worksheets with the same name.
------------------------ UPDATE 2 (after downloading the spreadsheet)
The problem was what I thought: two worksheets created with the same name (well... not exactly: one of the spreadhsheets was intended to be called after a null variable). And the reason for this problem, what I thought too: relying on "Active elements". But the problem was not while using the ActiveSheet, but while passing the arguments: the ranges are given without spreadsheet and were taken from the last created spreadsheet. Thus, solution:
HistogramHelper Sheets("Sheet1").Range("D3:D30")
HistogramHelper Sheets("Sheet1").Range("E3:E30")
Bottom line: don't rely on "Active"/not-properly-defined elements for complex situations.