I'm trying to automate plotting of a box and whiskers chart. The code below compiles and runs but the error bars do not appear in the chart.
Dim ws As Worksheet
Dim datarange As Range
Dim chtChart As Chart
Dim objChrt As ChartObject
Set ws = Sheets("sheet1")
Set datarange = ws.Range("F8:G10")
Set chtChart = Charts.add
With chtChart
chtChart.ChartType = xlColumnStacked
chtChart.SetSourceData Source:=datarange, PlotBy:=xlColumns
With .Axes(xlCategory, xlPrimary)
.CategoryNames = ws.Range("A2:A13")
.TickLabels.Font.Bold = True
End With
.SeriesCollection(1).Format.Fill.Visible = msoFalse
.SeriesCollection(2).Format.Fill.Visible = msoTrue
Dim Sec1 As Series
Set Sec1 = .SeriesCollection.NewSeries
.SeriesCollection(3).HasErrorBars = True
.SeriesCollection(3).ErrorBars.EndStyle = xlCap
.SeriesCollection(3).ErrorBars.Format.Line.Visible = msoTrue
.SeriesCollection(3).ErrorBars.Format.Line.ForeColor.RGB = RGB(0, 0, 0)
.SeriesCollection(3).ErrorBars.Format.Line.Transparency = 0
.SeriesCollection(3).ErrorBars.Format.Line.Weight = 1.5
.SeriesCollection(3).ErrorBar Direction:=xlX, Include:=xlErrorBarIncludeBoth, Type:=xlErrorBarTypeCustom, Amount:="=CHART!F12:G12", MinusValues:="=CHART!F12:G12"
Solved.
.SeriesCollection(3).values= <data range for whisker length>
type variant, data values required to plot whiskers
IMPORTANT: this overwrites the series collection values (seriescollection(3) in this case)
values can be replaced after plotting whiskers
Related
How can I place two different sheets on one page.
I create a chart with this code
'Create a chart
Set cht = Worksheets("Dashboard").Shapes.AddChart2
'Set cht = ActiveSheet.Shapes.AddChart2
With cht
.Chart.SetSourceData Source:=rng 'Give chart some data
.Chart.ChartType = xlColumnStacked 'Determine the chart type
.Chart.PlotBy = xlColumns
.ScaleHeight 1.7, msoFalse
.Chart.SetElement (msoElementLegendRight)
.Chart.ChartTitle.Text = Range("E1")
End With
Worksheets("Dashboard").Select
ActiveSheet.ChartObjects(1).Name = "FalseCall"
Range("A1") = ActiveSheet.ChartObjects(1).Name
ActiveSheet.Shapes("FalseCall").Left = Range("A1").Left
ActiveSheet.Shapes("FalseCall").Top = Range("A1").Top
ActiveSheet.Shapes("FalseCall").Width = Range("A1:G1").Width
ActiveSheet.Shapes("FalseCall").Height = Range("A1:A26").Height
It will add a chart on sheet "Dashboard".
Next I want to add a new chart with another name on the same page on H1 with
ActiveSheet.ChartObjects(1).Name = "Ng"
The existing chart will be renamed with the name of the second Chart and moves to H1, instead of the new chart is getting that name and moving the H1
It's not more complicated than repeating the steps with new ranges specified.
Sub InsertTwoCharts()
Dim ws As Worksheet
Set ws = Worksheets("Dashboard")
' CHART 1
' range that chart will cover
Dim ChtRng1 As Range
Set ChtRng1 = ws.Range("A1:G26")
' chart data range
Dim ChtData1 As Range
Set ChtData1 = Worksheets("Whatever").Range("A1:E12") ' or whatever
' insert and modify the chart
Dim cht1 As ChartObject
Set cht1 = ws.Shapes.AddChart2
With cht1
.Name = "FalseCall"
.Chart.SetSourceData Source:=ChtData1, PlotBy:=xlColumns
.Chart.ChartType = xlColumnStacked
.Chart.SetElement msoElementLegendRight
.Chart.ChartTitle.Text = ws.Range("E1").Value ' pick a worksheet and cell
.Left = ChtRng1.Left
.Top = ChtRng1.Top
.Width = ChtRng1.Width
.Height = ChtRng1.Height
End With
' CHART 2
' range that chart will cover
Dim ChtRng2 As Range
Set ChtRng2 = ws.Range("H1:N26")
' chart data range
Dim ChtData2 As Range
Set ChtData2 = Worksheets("Whatever").Range("G1:K12") ' or whatever
' insert and modify the chart
Dim cht2 As ChartObject
Set cht2 = ws.Shapes.AddChart2
With cht2
.Name = "TrueCall"
.Chart.SetSourceData Source:=ChtData1, PlotBy:=xlColumns
.Chart.ChartType = xlColumnStacked
.Chart.SetElement msoElementLegendRight
.Chart.ChartTitle.Text = ws.Range("H1").Value ' pick a worksheet and cell
.Left = ChtRng2.Left
.Top = ChtRng2.Top
.Width = ChtRng2.Width
.Height = ChtRng2.Height
End With
End Sub
I am trying to print one graph for each row/table, the graphs should keep the same format, only the data should change among graphs. I need to do it for about 120 rows/tables so I would like to avoid doing it manually, also, I would prefer not to use the sparklines as its format is not appropriate for the purpose of the analysis.
I have tried to use a dynamic chart with the combo button but when I change the filtered line, every copied graph changes as well, making it impossible to have at the same time graphs showing different rows - one solution may be pasting it as image but it is not optimal as I would like to check the data for each graph if needed.
Below I show the example for two different "items", in the original dataset there are about 350/400 rows and about 120 "items", every 3 rows create one graph.
The graphs I have created manually are: (one for each 3 rows)
for "item" xxx:
For "item" yyy:
I need to print this type of graph for other different ~120 "items", all at once.
In terms of showing the format of the chart, see the below for the first graph:
The blank is:
The second quartile is:
The third quartile:
and the "item", which is the black point in the graph:
Same reasoning for the second graph, but considering the three rows with yyy.
I hope you can help me!
Sorry for the big amount of images, but I wanted it to be clear!
Thank you in advance!
Best,
Ema
It is easy to create a typical procedure for creating a chart and use parameters to iterate over the sheet.
Sub makeCharts()
Dim Ws As Worksheet
Dim Cht As Chart, Shp As Shape
Dim obj As ChartObject
Dim Target As Range, rngShp As Range
Dim r As Long, n As Long, i As Long
Set Ws = ActiveSheet
For Each obj In Ws.ChartObjects
obj.Delete
Next
r = Ws.Range("a" & Rows.Count).End(xlUp).Row
n = 1
For i = 3 To r Step 3
Set rngShp = Ws.Range("k" & n).Resize(10, 8)
Set Target = Ws.Range("a" & i)
Set Shp = Ws.Shapes.AddChart
With Shp
.Top = rngShp.Top
.Left = rngShp.Left
.Width = rngShp.Width
.Height = rngShp.Height
End With
Set Cht = Shp.Chart
setCharts Target, Cht
n = n + 12
Next i
End Sub
Sub setCharts(Target As Range, Cht As Chart)
Dim Srs As Series
Dim vColor
Dim i As Integer
vColor = Array(RGB(246, 246, 246), RGB(255, 224, 140), RGB(47, 157, 39), RGB(0, 0, 0))
With Cht
.ChartType = xlColumnStacked
.HasLegend = False
.HasTitle = True
.ChartTitle.Text = Target.Value
.Axes(xlValue, xlPrimary).HasTitle = True
.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "OCF Percentiles"
.Axes(xlValue).MajorUnit = 20
For Each Srs In .SeriesCollection
Srs.Delete
Next Srs
For i = 0 To 2
Set Srs = .SeriesCollection.NewSeries
With Srs
.Values = Target.Offset(0, 1).Resize(3).Offset(0, i)
.XValues = Array("A", "D", "I")
.Format.Fill.ForeColor.RGB = vColor(i)
If i = 0 Then
.Format.Fill.Transparency = 1 '<~~~~~ Transparency was adjusted
End If
End With
Next i
Set Srs = .SeriesCollection.NewSeries
With Srs
.ChartType = xlXYScatter
.Values = Target.Offset(0, 4).Resize(1, 3)
.MarkerStyle = xlMarkerStyleSquare
.MarkerBackgroundColor = vColor(3) 'vbBlack
End With
End With
End Sub
Result image
When I plot my chart using one set of data(current 1), the graph shows the correct output. However when I plot 2 sets of data concurrently(current 1 and current 2), part of the graph is missing(circled in red) for both data consisting of current 1 and current 2. Btw the data are the same for both scenarios and no data are missing. As my data for them is huge, I can only show you the part of my data sample which looks like this as shown below for current 1 and current 2. I know the code for plotting graph of current1 only contains a lot of variables that you all might deem as the one that causes problem so let me clarify that totalsample1 and myarray values should be correct as they are the ones responsible for the data(Like the one shown in data sample for current1) for plotting the graph for current and all data for plotting are present in this case. So what could be the code that causes this problem and how to remedy it?
Data sample for current 1
Data sample for current 2
1st update:add wsf to range and cells
2nd update: replaced activechart with cht1
3rd update: Remove from For i = 2 To totalsample1 Step 1 till all the cht1.series collection
4th update: I make a simpler version of my code to plot graph for current 1.
5th update: And using the code suggested by #Dy.Lee, the ideal graph for current 1 is as shown.
Private Sub addgraph_Vramp1()
Application.ScreenUpdating = False
Dim i As Long
Dim wf As Workbook
Set wf = ActiveWorkbook
Dim wsf As Worksheet
Set wsf = wf.Worksheets("current1")
Dim shp1 As Shape
Dim Cht1 As Chart
Set shp1 = wsf.Shapes.AddChart
Set Cht1 = shp1.Chart
wsf.Activate
With Cht1
Cht1.SetSourceData Source:=wsf.Range("A1:BQ750")
Cht1.ChartType = xlXYScatterSmoothNoMarkers
Cht1.Axes(xlValue).ScaleType = xlLogarithmic
Cht1.Axes(xlValue).MaximumScale = 0.001
Cht1.Axes(xlValue).MinimumScale = 0.000000000000001
End With
With Cht1
.Legend.Delete
.Axes(xlCategory, xlPrimary).HasTitle = True
.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "Voltage"
.Axes(xlValue, xlPrimary).HasTitle = True
.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "Current"
End With
changes to the graph for the current 1 after using updated codes
changes to the graph after removing cht1.series collection(it still remains in the updated code just to let other knows what is being removed here)
Ideal graph :))))
Caught wrong range
Cht1.SeriesCollection(i).XValues = wsf.Range(Cells(2, 2 * i - 1), wsf.Cells(myarray(i + 1), 2 * i - 1))
To
Cht1.SeriesCollection(i).XValues = wsf.Range(wsf.Cells(2, 2 * i - 1), wsf.Cells(myarray(i + 1), 2 * i - 1))
This is an example of creating a chart using a parameterized procedure.
Sub test()
Dim Ws As Worksheet
Dim Ws2 As Worksheet
Set Ws = Sheets("current1")
Set Ws2 = Sheets("current2")
addgraph_Vramp1 Ws
addgraph_Vramp1 Ws2
End Sub
Private Sub addgraph_Vramp1(Ws As Worksheet)
Dim i As Long, c As Long
Dim shp As Shape
Dim Cht As Chart
Dim rngDB As Range, rngX As Range, rngY As Range
Dim Srs As Series
Set rngDB = Ws.UsedRange
c = rngDB.Columns.Count
Set shp = Ws.Shapes.AddChart
Set Cht = shp.Chart
With Cht
.ChartType = xlXYScatterSmoothNoMarkers
.HasLegend = False
For Each Srs In .SeriesCollection
Srs.Delete
Next Srs
For i = 1 To c Step 2
With Ws
Set rngX = Ws.Range(.Cells(2, i), .Cells(2, i).End(xlDown))
Set rngY = rngX.Offset(, 1)
End With
Set Srs = .SeriesCollection.NewSeries
With Srs
.XValues = rngX
.Values = rngY
End With
Next i
.Axes(xlValue).ScaleType = xlLogarithmic
.Axes(xlValue).MaximumScale = 0.001
.Axes(xlValue).MinimumScale = 0.000000000000001
.Axes(xlCategory, xlPrimary).HasTitle = True
.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "Voltage"
.Axes(xlValue, xlPrimary).HasTitle = True
.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "Current"
End With
End Sub
I need to plot charts at a predefined position in my worksheet when I run the macro to plot the charts. The problem is that the charts are automatically plotted in a weird manner and I don't like that. I want to make sure I can predefine the exact positions at which I want the charts to be plotted on running the macro. I have attached 2 images here, 1 image shows how it's currently plotted and the other shows how I want the charts to be plotted. Any kind of help would be highly appreciated.
This is how I want the charts to be shown on the sheet:
This is how it's currently showing up, with one pie chart overlapping the other and the line chart obscuring the macro buttons as well
This is the code I used, starting with the line chart, followed by the pie charts. I'm new to VBA and coding so please excuse the code structure.
' CHART Code
Dim chart As chart
Dim k As Integer
Dim p As Integer
Dim j As Integer
Dim arrDEM() As Long
Dim arrDATE() As Integer
ReDim arrDEM(1 To 65) As Long
ReDim arrDATE(1 To 65) As Integer
Dim DEM As Integer
j = findcell.Select
ActiveCell.Offset(0, 1).Select
For DEM = 1 To 65
arrDEM(DEM) = ActiveCell.Value
ActiveCell.Offset(0, 1).Select
Next DEM
Debug.Print arrDEM(65)
Range("B1").Activate
For p = 1 To 65
arrDATE(p) = ActiveCell.Value
ActiveCell.Offset(0, 1).Select
Next p
Debug.Print arrDATE(65)
Range("B31:B031") = arrDEM
Range("B31:B031").Select
Set cht1 = ActiveSheet.ChartObjects.Add(Left:=200, Width:=4500, Top:=200, Height:=4000)
ActiveSheet.Shapes.AddChart.Select
Set chart = ActiveChart
chart.ChartType = 4
chart.SeriesCollection(1).Name = x
chart.SeriesCollection(1).XValues = arrDATE
chart.SeriesCollection(1).Values = arrDEM
With ActiveChart
'chart name
.HasTitle = True
.ChartTitle.Characters.Text = "Demand Distribution"
'X axis name
.Axes(xlCategory, xlPrimary).HasTitle = True
.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "Weeks"
'y-axis name
.Axes(xlValue, xlPrimary).HasTitle = True
.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "Demand"
'Copy chart from Original file
ActiveChart.ChartArea.Copy
'Paste chart in destination file
Worksheets("Model Calculations").Paste
'Deleting Charts
Worksheets("Sheet1").ChartObjects.Delete
'Activating destination chart
Worksheets("Model Calculations").Activate
Application.DisplayAlerts = False
End With
' PieC Macro
Range("C10:D11").Select
ActiveSheet.Shapes.AddChart2(262, xl3DPie).Select
ActiveChart.SetSourceData Source:=Range("'Model Calculations'!$C$10:$D$11")
With ActiveChart
'chart name
.HasTitle = True
.ChartTitle.Characters.Text = "Continuous Review"
' .Name = "Continuous Chart"
End With
' PieP Macro
'
Range("C10,D10,C12,D12").Select
ActiveSheet.Shapes.AddChart2(262, xl3DPie).Select
ActiveChart.SetSourceData Source:=Range("'Model Calculations'!$C$10,'Model Calculations'!$D$10,'Model Calculations'!$C$12,'Model Calculations'!$D$12")
With ActiveChart
'chart name
.HasTitle = True
.ChartTitle.Characters.Text = "Periodic Review"
'.Name = "Periodic Chart"
End With
End Sub
Your code could use some help in a number of ways. To answer your question, I'll ignore all that, and fix one piece of code. Here is what I'm replacing:
' PieC Macro
Range("C10:D11").Select
ActiveSheet.Shapes.AddChart2(262, xl3DPie).Select
ActiveChart.SetSourceData Source:=Range("'Model Calculations'!$C$10:$D$11")
With ActiveChart
'chart name
.HasTitle = True
.ChartTitle.Characters.Text = "Continuous Review"
' .Name = "Continuous Chart"
End With
I'll start by declaring and assigning a few variables, then create, populate, and position a chart.
Dim WkSht As Worksheet
Set WkSht = Worksheets("Model Calculations")
WkSht.Activate
Dim rChartData As Range
Set rChartData = WkSht.Range("C10:D11")
Dim rChartCover As Range
Set rChartCover = WkSht.Range("F10:K18")
Dim NewChart As Chart
Set NewChart = WkSht.Shapes.AddChart2(262, xl3DPie).Chart
With NewChart
.SetSourceData rChartData
With .Parent
.Left = rChartCover.Left
.Top = rChartCover.Top
.Width = rChartCover.Width
.Height = rChartCover.Height
End With
End With
You could replace this:
Set WkSht = Worksheets("Model Calculations")
WkSht.Activate
with this:
Set WkSht = ActiveSheet
to make it more general, and if you know the position and size of the resulting chart, you can plug those in instead of using the position and size of a given range (like I used rChartCover above).
I have the following macro which plots a Scatter graph for three columns. One column (AL13, downwards) is on the x axis. How do I get it to plot the other two columns (AK and AM) onto the same scatter? Also in different colour to each other? Thank You
Sub Graphing()
Set rng4 = ActiveSheet.Range(Range("AP13"), Range("AV33"))
With ActiveSheet.ChartObjects.Add(Left:=rng4.Left, Width:=rng4.Width, Top:=rng4.Top, Height:=rng4.Height)
.Chart.ChartType = xlXYScatter
.Chart.HasLegend = False
.Chart.Axes(xlCategory).TickLabels.Font.Size = 18
.Chart.Axes(xlValue).TickLabels.Font.Size = 18
Set srs = .Chart.SeriesCollection.NewSeries
srs.Values = Range(Range("AK13"), Range("AK13").End(xlDown))
srs.XValues = Range(Range("AL13"), Range("AL13").End(xlDown))
srs.Values = Range(Range("AM13"), Range("AM13").End(xlDown))
End With
End Sub
I will repost the code that I revised for you above, thanks for crediting me :)
Sub Graphing()
'Declare all the variables to be used:'
Dim rng4 as Range
Dim srs as Series
Dim cht as Chart
Dim xVals as Range
Dim srsVals as Range
'Set the chart's data range:'
Set rng4 = ActiveSheet.Range(Range("AP13"), Range("AV33"))
'Set the range variable to contain the series values'
' You can later modify this to include any number of columns, and the '
' loop structure below will add each column as a series to the chart.'
Set srsVals = ActiveSheet.Range(Range("AL13"),Range("AM13").End(xlDown))
'Set the cht variable:'
Set cht= ActiveSheet.ChartObjects.Add(Left:=rng4.Left, Width:=rng4.Width, Top:=rng4.Top, Height:=rng4.Height).Chart
'Set the Range variable for xValues:
Set xVals = Range(Range("AK13"),Range("AK13").End(xlDown))
'Format the chart and add series to the chart by iterating over the columns in srsVals:'
With cht
.ChartType = xlXYScatter
.HasLegend = False
.Axes(xlCategory).TickLabels.Font.Size = 18
.Axes(xlValue).TickLabels.Font.Size = 18
'Create the series in a loop
For c = 1 to srsVal.Columns.Count
Set srs = .SeriesCollection.NewSeries
With srs
.Values = xVals
.XValues = Range(srsVals.Columns(c).Address)
.Name = "Series " & c '<-- Modify as needed.'
End With
Next
End With
End Sub
I found that if I set the series as two separate series then it will plot both and give them different colours. Not sure if it is the most efficient way of doing it but it works.
Sub Graphing()
'Declare all the variables to be used:'
Dim rng4 as Range
Dim srs as Series
Dim cht as Chart
Dim xVals as Range
Dim srsVals as Range
'Set the chart's data range:'
Set rng4 = ActiveSheet.Range(Range("AP13"), Range("AV33"))
'Set the range variable to contain the series values'
' You can later modify this to include any number of columns, and the '
' loop structure below will add each column as a series to the chart.'
Set srsVals = ActiveSheet.Range(Range("AL13"),Range("AM13").End(xlDown))
'Set the cht variable:'
Set cht= ActiveSheet.ChartObjects.Add(Left:=rng4.Left, Width:=rng4.Width, Top:=rng4.Top, Height:=rng4.Height).Chart
'Set the Range variable for xValues:
Set xVals = Range(Range("AK13"),Range("AK13").End(xlDown))
'Format the chart and add series to the chart by iterating over the columns in srsVals:'
With cht
.ChartType = xlXYScatter
.HasLegend = False
.Axes(xlCategory).TickLabels.Font.Size = 18
.Axes(xlValue).TickLabels.Font.Size = 18
'Create the series in a loop
For c = 1 to srsVal.Columns.Count
Set srs = .SeriesCollection.NewSeries
With srs
.Values = xVals
.XValues = Range(srsVals.Columns(c).Address)
.Name = "Series " & c '<-- Modify as needed.'
End With
Next
End With
End Sub