Adding new series to a graph automatically - excel

I'm trying to create a dynamic Scatterchart in the worksheet("Graphs") using a button.
The Seriesname has to be equal to Worksheets("VS_P240_X").Cells(1,i), where i is a counter for the columns.
The XValues have to be equal to Worksheets("VS_P240_X").Range(cells(3,i).cells(1000,i)).
The YValues have to be equal to Worksheets("VS_P240_Y").Range(cells(3,i).cells(1000,i)).
When I Update the workbook the counter i will change, and I want that the chart will automatically update with the new series. I wrote this code but it is not working, do you have some suggestions?
Private Sub CommandButton5_Click()
'Graph generation NON COMPLETO
Dim i As Integer
Dim Chart1 As Chart
Set Chart1 = Sheets("Graphs").ChartObjects("Chart 1").Chart
For i = 1 To Lastcolumn
With Chart1
.ChartType = xlXYScatter
.SeriesCollection.NewSeries
'Change to what your series should be called
.SeriesCollection(i).Name = Worksheets("VS_P240_X").Cells(1, i).Value
.SeriesCollection(i).XValues = Worksheets("VS_P240_X").Range(Cells(3, i), Cells(1000, i))
.SeriesCollection(i).Values = Worksheets("VS_P240_Y").Range(Cells(3, i), Cells(1000, i))
End With
Next i
End Sub

To avoid confusion/bugs, it's best to specify a worksheet every time you use Range or Cells()
Something like this should work:
Private Sub CommandButton5_Click()
Dim i As Long, Lastcolumn As Long 'use long not integer
Dim Chart1 As Chart, wsX As Worksheet, wsY As Worksheet
Set wsX = Worksheets("VS_P240_X")
Set wsY = Worksheets("VS_P240_Y")
Set Chart1 = Sheets("Graphs").ChartObjects("Chart 1").Chart
Do While Chart1.SeriesCollection.Count > 0 'remove any existing data
Chart1.SeriesCollection(1).Delete
Loop
Chart1.ChartType = xlXYScatter 'do this outside of the loop...
Lastcolumn = wsX.Cells(1, wsX.Columns.Count).End(xlToLeft).Column
For i = 1 To Lastcolumn
With Chart1.SeriesCollection.NewSeries
.Name = wsX.Cells(1, i).Value
.XValues = wsX.Range(wsX.Cells(3, i), wsX.Cells(1000, i))
.Values = wsY.Range(wsY.Cells(3, i), wsY.Cells(1000, i))
End With
Next i
End Sub

Related

Fixing range of y values for graph with VBA

I have written the following code to display a basic line graph.
Sub addchart()
If ActiveSheet.ChartObjects.Count > 0 Then
ActiveSheet.ChartObjects.Delete
End If
Dim ws As Worksheet
Dim ch As chart
Dim dt As Range
Dim i As Integer
i = Cells(Rows.Count, "M").End(xlUp).Row
Set ws = ActiveSheet
Set dt = Range(Cells(2, 14), Cells(i, 14))
Set ch = ws.Shapes.AddChart2(Width:=1300, Height:=300, Left:=Range("a13").Left, Top:=Range("a13").Top).chart
With ch
.SetSourceData Source:=dt
.ChartTitle.Text = "Deflection Curve"
.ChartType = xlLineMarkers
End With
End Sub
But the trouble with this is that the range of Y axis adjusts itself according to the data automatically. I want to fix this range so that the change in the graph is noticeable.
For example, the following two graphs vary in the range of values they cover but they look basically the same because the y axis is adjusting itself. One goes from 0 to -9 and the other from 0 to -25. If I can fix the range to say 0 to -30, the difference in the two graphs would be more apparent.
With ch.Axes(xlValue)
.Minimumscale = -30
.Maximumscale = 0
End with
Relevant links:
Chart.Axes method
Axis Object
Thanks to Spencer, the following code gets the result I want
Sub addchart()
If ActiveSheet.ChartObjects.Count > 0 Then
ActiveSheet.ChartObjects.Delete
End If
Dim ws As Worksheet
Dim ch As chart
Dim dt As Range
Dim i As Integer
i = Cells(Rows.Count, "M").End(xlUp).Row
Set ws = ActiveSheet
Set dt = Range(Cells(2, 14), Cells(i, 14))
Set ch = ws.Shapes.AddChart2(Width:=1300, Height:=300, Left:=Range("a13").Left, Top:=Range("a13").Top).chart
With ch
.SetSourceData Source:=dt
.ChartTitle.Text = "Deflection Curve"
.ChartType = xlLineMarkers
End With
With ch.Axes(xlValue) 'fixing range of values
.MinimumScale = -30
.MaximumScale = 0
End With
End Sub

How can I create a chart from unique values in a range

I have items that are being populated on a worksheet via userform. When I open the workbook I'm trying to get the tool to go to the sheet grab the data and generate a chart/dashboard on the main landing sheet.
In the range of data contains statuses. I want VBA to look through one column of data and create a chart that counts each different status and put that in a bar chart.
yaxis = the different statuses
xaxis = count
my code so far
Sub populatecharts()
Dim ws As Worksheet
Dim ch As Chart
Dim tablerng As Range
Dim rng1 As Range
Dim rng2 As Range
Dim rng3 As Range
Dim sh As String
Set ws = ActiveSheet
'When the workbook opens it should always check the data and populate the BA Dashboard
'I need to check for sheets and if they exist generate a chart from the data
sh = "Action"
On Error Resume Next
Worksheets("Action").Visible = True
If CheckSheetExist(sh) = False Then
GoTo nextchart1
Else
Worksheets(sh).Activate
'Set ws = ActiveSheet
Set rng1 = Range("G4", Range("G4", "G4").End(xlDown))
rng1.Select
'Set rng2 = Range("B2")
'Set rng3 = Range("C3")
'Set tablerng = rng1 '& rng2 & rng3
Set ch = ws.Shapes.AddChart2(Width:=200, Height:=200, Left:=Range("B4").Left, Top:=Range("B4").Top).chart
With ch
.SetSourceData Source:=rng1
.ChartType = xlBarClustered
.ChartTitle.Text = "Action Items by Status"
End With
ws.Activate
Worksheets("Action").Visible = False
End If
Seems easy but I'm not able to think through it, also the location is hit or miss even though I define the top and bottom and size. Sometimes it's to the right of the cell I chose to be the left.
Try the next way, please. It uses a dictionary to extract the unique values and their count and array to feed the necessary series. Try running it on active sheet and adapt it to your situation only after having the confirmation that what it returns is what you need:
Sub populatecharts()
Dim shT As Worksheet, ch As Chart, lastRow As Long
Dim arrY, arrX, i As Long, dict As Object
Set shT = ActiveSheet 'use here the sheet you need
lastRow = shT.Range("G" & shT.Rows.count).End(xlUp).row
arrX = shT.Range("G4:G" & lastRow).Value 'put the range in a array
Set dict = CreateObject("Scripting.Dictionary") 'needed for the next step
On Error Resume Next
shT.ChartObjects("MyChartXY").Delete 'for the case of re running need
On Error GoTo 0
For i = 1 To UBound(arrX)
If Not dict.Exists(arrX(i, 1)) Then
dict(arrX(i, 1)) = 1 'create the unique keys
Else
dict(arrX(i, 1)) = dict(arrX(i, 1)) + 1 'increment the key next occurrrence
End If
Next i
arrX = dict.Keys: arrY = dict.Items 'extract the necessary arrays
Set ch = shT.ChartObjects.Add(left:=shT.Range("B4").left, _
top:=shT.Range("B4").top, width:=200, height:=200).Chart
With ch
.ChartType = xlBarClustered
.HasTitle = True
.ChartTitle.Text = "Action Items by Status"
.SeriesCollection.NewSeries.Values = arrY 'feed it with the array elements
.SeriesCollection(1).XValues = arrX 'feed it with the array elements
End With
End Sub
Please, test it and send some feedback.

Invalid parameter error when method is called from another sub

I have the below code that creates charts from some worksheets and put the charts in their own worksheets. When I run the macro on it's own it works perfectly. When I use Call InsertDNCCharts from another macro I get a "Invalid Parameter" error on .Period = 7 from within the With tl block. Why is there a difference? If the code runs on its own shouldn't it run the same way when called from another sub?
Sub InsertDNCCharts()
Dim ws As Worksheet
Dim cws As Worksheet
Dim country As String
Dim lastrow As Long
Dim chrt As Shape
Dim chrtname As String
Dim xvalues As Range
Dim yvalues As Range
Dim tl As Trendline
For Each ws In ThisWorkbook.Worksheets
If Right(ws.Name, 6) = "_Chart" Then
country = Left(ws.Name, Len(ws.Name) - 6)
Set cws = ThisWorkbook.Worksheets(country)
lastrow = cws.Cells(Rows.count, "c").End(xlUp).Row
Set xvalues = cws.Range("c5:c" & lastrow)
Set yvalues = cws.Range("l5:l" & lastrow)
cws.Activate
Application.Union(xvalues, yvalues).Select
Set chrt = cws.Shapes.AddChart2(201, xlColumnClustered, Cells(5, 2).Left, Cells(5, 2).Top, 1000, 420)
chrt.Name = ws.Name
chrtname = chrt.Name
cws.Cells(5, 1).Select
With chrt.Chart
.Location Where:=xlLocationAsObject, Name:=ws.Name
.Axes(xlCategory).HasMajorGridlines = True
.Axes(xlCategory).HasMinorGridlines = False
.Axes(xlValue).HasMajorGridlines = True
.Axes(xlValue).HasMinorGridlines = False
.HasLegend = False
End With
ws.ChartObjects(chrtname).Activate
ActiveChart.ChartWizard Title:=country & " Daily New Cases (DNC)"
Set tl = ws.ChartObjects(chrtname).Chart.SeriesCollection(1).Trendlines.Add
With tl
.Type = xlMovingAvg
.Period = 7 '*******Error on this line. Debug says period=2, which is the default moving average period.
.DisplayEquation = False
.DisplayRSquared = False
.Format.Line.DashStyle = msoLineSysDot
.Format.Line.Weight = 3.5
.Format.Line.ForeColor.RGB = RGB(255, 0, 0)
.Format.Line.Style = msoLineSingle
End With
End If
Next ws
End Sub
If the chart in discussion (the created one) has at least 7 points, it is possible that the code is not referring to the appropriate chart, or the chart has not been created as necessary.
In order to check that, I would suggest you putting a break point on line With tl and visually check if the active chart is the one you need and if it looks as expected. It looks that the problem has to be before the line raising the error.

how do i offset all the charts in the same worksheet in VBA?

Currently, all my charts are cramped together in the same spot in the same worksheet after running my code. So to view them i have to manually drag and move them to another spot. So is there a way such that i can place all the charts in a orderly manner as shown in expected output? If it is really impossible to do something like this, i am ok with offsetting the graph for every 20 cells even though it is abit inconvenient for viewing but still i attempted to do it but fail to make it happen when i include code with current output with the offsetting code.
Current output(looks like there is 1 chart but all the charts are in the same spot)
Below is the code for my current output
Sub plotgraphs()
'Call meangraph
Call sigmagraph
End Sub
Private Sub sigmagraph()
Dim i As Long, c As Long
Dim shp As Shape
Dim Cht As chart, co As Shape
Dim rngDB As Range, rngX As Range, rngY As Range
Dim Srs As Series
Dim ws As Worksheet
Set ws = Sheets("Data")
Set rngDB = ws.Range("A1").CurrentRegion
Set rngX = rngDB.Columns(1)
Set rngY = rngDB.Columns(4)
Do While Application.CountA(rngY) > 0
Set co = Worksheets("meangraphs").Shapes.AddChart
Set Cht = co.chart
With Cht
.ChartType = xlXYScatter
'remove any data which might have been
' picked up when adding the chart
Do While .SeriesCollection.Count > 0
.SeriesCollection(1).Delete
Loop
'add the data
With .SeriesCollection.NewSeries()
.XValues = rngX.Value
.Values = rngY.Value
End With
'formatting...
With Cht.Axes(xlValue)
.MinimumScale = 0
.MaximumScale = 0.5
.TickLabels.NumberFormat = "0.00E+00"
End With
Cht.Axes(xlCategory, xlPrimary).HasTitle = True
Cht.Axes(xlValue, xlPrimary).HasTitle = True
End With
Set rngY = rngY.Offset(0, 2) 'next y values
Loop
Code for offsetting chart for every 20 cells (fail to make it happen)
Dim OutSht As Worksheet
'
Dim PlaceInRange As Range
Set OutSht = ActiveWorkbook.Sheets("sigmagraphs") '<~~ Output sheet
Set PlaceInRange = OutSht.Range("B2:J21") '<~~ Output location
'
' To place charts at a distance between them
For Each chart In Sheets("sigmagraphs").ChartObjects
' OutSht.Paste PlaceInRange
' Code below changes the range itself to something 20 rows below
Set PlaceInRange = PlaceInRange.Offset(20, 0)
Next chart
Expected output
What you are looking for is the .Left and .Top properties of the Shape containing the Chart.
For example, a macro that would setup your charts into a 2-column grid would look like this:
Sub SetupChartsIntoGrid()
Const TopAnchor As Long = 50
Const LeftAnchor As Long = 50
Const HorizontalSpacing As Long = 10
Const VerticalSpacing As Long = 10
Const ChartHeight As Long = 211
Const ChartWidth As Long = 360
Dim shp As Shape
For Each shp In ActiveSheet.Shapes
If shp.Type = msoChart Then
Dim Counter As Long
Counter = Counter + 1
With shp
.Top = TopAnchor + (WorksheetFunction.RoundUp(Counter / 2, 0) - 1) * (VerticalSpacing + ChartHeight)
.Left = LeftAnchor + ((Counter + 1) Mod 2) * (HorizontalSpacing + ChartWidth)
End With
End If
Next
End Sub

Create multiple line charts using Macro in Excel

I have created a macro which creates line chart for each row. Below is the code.
The data is in following format:
Format in which I have the data:
Sub createChartWithLoop()
Dim wks As Worksheet
Set wks = Worksheets("Sheet1")
Dim chrt As Chart
Set chrt = wks.Shapes.AddChart.Chart
Dim chartRange As Range
Set chartRange = wks.Range("A1:A4")
With chrt
.ChartType = xlLine
.SetSourceData Source:=Range(wks.Range("A" & chartRange.Row & ":D" & chartRange.Row).Address)
For i = chartRange.Row + 1 To chartRange.Rows.Count
.SeriesCollection.NewSeries
.SeriesCollection(i).Name = wks.Cells(i, 1)
.SeriesCollection(i).Values = wks.Range("B" & i & ":D" & i)
Next i
End With
End Sub
However, now I have a little different requirement. Assume I have 30 rows same format.
Requirement: I have to consider the first 3 rows as 1 set. 2nd 3 rows as 2nd Set and so on. So here effective we will have 10 set (30 rows/3). Each set should give me a chart.
Right now, I'm getting a chart with 3 lines (3 records). Above is my code. Can anyone help on the above request?
I wrote a procedure which will plot a stated number of charts each using a stated number of rows. Then I wrote a short procedure that shows how to have it create 10 charts with three rows each.
Here is the procedure to create nCharts charts, using nRows rows for each:
Sub CreateChartWithLoop(nCharts As Long, nRows As Long)
Dim wks As Worksheet
Set wks = ActiveSheet
Dim DataRange As Range
Set DataRange = ActiveSheet.UsedRange
Dim iChart As Long
For iChart = 1 To nCharts
Dim cht As Chart
Set cht = wks.Shapes.AddChart(xlLine, DataRange.Width, DataRange.Rows(1 + (iChart - 1) * nRows).Top).Chart
Do Until cht.SeriesCollection.Count = 0
cht.SeriesCollection(1).Delete
Loop
Dim iRow As Long
For iRow = 1 To nRows
With cht.SeriesCollection.NewSeries
.Name = "=" & DataRange.Cells(iRow + (iChart - 1) * 3, 1).Address(, , , True)
.Values = DataRange.Rows(iRow + (iChart - 1) * 3).Offset(, 1).Resize(, DataRange.Columns.Count - 1)
End With
Next
cht.HasTitle = True
cht.ChartTitle.Text = "Chart " & iChart
Next
End Sub
Here's the procedure that calls the main procedure, telling it to make 10 charts with 3 rows each:
Sub Create10ChartsWith3RowsEach()
CreateChartWithLoop 10, 3
End Sub

Resources