Why is my LineChart plotting data incorrectly? - vba

I have been working on an excel Macro to graph some data on Chartsheet, but all of a sudden, it now graphs 7 different series instead of 2...
The Code for the graph is:
Public Sub GraphResults()
Dim ws As Worksheet
Dim LineGraph As Chart
Set ws = ActiveSheet
Set LineGraph = Charts.Add
With LineGraph
.SetSourceData Source:=ws.Range("B29:B35,G29:G35")
.ChartType = xlLineMarkers
.HasTitle = True
.ChartTitle.Text = ""
.Axes(xlCategory, xlPrimary).HasTitle = True
.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "X-axis"
.Axes(xlValue, xlPrimary).HasTitle = True
.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "Y-axis"
.SeriesCollection(1).XValues = ws.Range("A29:A35")
End With
End Sub
Instead of graphing 2 lines where one line has Y-values of B29:B35 and the other has Y values of G29:G35, it graphs 7 lines
Each line has a B value and a G value. For example, series 1 contains 2 points: B29 and G29. Series 2 contains 2 points B30 and G30. I didn't change the code at all. In fact when I open the Macro from the last time it was saved, the graph that displays only has 2 lines! When I re-run the macro, the graph changes to 7 lines.
What's going on here?...

Your chart is plotting values by rows, not columns as you want. See SetSourceData Method for more info.
Add PlotBy:=xlColumns to the .SetSourceData line to automatically plot by columns.

Related

creating a scatter plot containing series dynamically using VBA in microsoft excel

I am rather new to VBA so I would appreciate more thorough explanations of what you did to solve this minor issue.
I am tasked with creating a simple VBA program that takes an already sorted set of data (I learned about it and then used a VBA program to sort my data alphabetically already based on a particular column's values) and does the following two things with it:
Graphs a scatter plot with it (either within that sheet or in a separate sheet)
AND
Creates series with that scatter plot dynamically (meaning that scatter plot has series on it based on a particular column's value). I will not know how many series I need but I do know that since it's sorted, the column defining the type of data in that row will be in alphabetical order (and I assume the VBA program can first create a series with the first row's name and then not create more series until it finds a different name in that column until it is finished graphing the data)
an example of a simple 3 column table is shown below:
SERIES NAME ___X VALUE_____Y VALUE
A__________________1___________1
A__________________2___________2
A__________________3___________3
A__________________4___________4
B__________________5___________5
B__________________6___________6
B__________________7___________7
C__________________8___________8
C__________________9___________9
C__________________1___________1
(there could be more rows and more unique series names of course... )
so in this example, the graph is already sorted and I would like there to be a scatter plot with 3 series on it (A being the 1st, B being the 2nd, and 3 being the 3rd)
I have the code to create a scatter plot with one series so far but I've been stuck trying to figure this out (code shown below). Any help with explanation is greatly appreciated :D
Here's my code so far (without the dynamic series part ofc)
Sub creatingmyscatterplot()
'Dim aRng As Range
'Dim seriescheck As Range
Dim Chart1 As Chart
Set Chart1 = Charts.Add
'Set aRng = Selection.CurrentRegion
'Set aRng = aRng.Offset(1, 0).Resize(aRng.Rows.Count - 1)
'Set seriescheck = aRng.Resize(aRng.Rows.Count, 1)
'Dim seriesName As String, seriesData As Range
'These lines, as their names suggest, turn off screen refresh and recalculating the workbook's formulas before running the macro.
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
With Chart1
.ChartType = xlXYScatterLines
.SeriesCollection.NewSeries
'This creates the graph
.SeriesCollection(1).Name = "=Sheet1!$A$2"
.SeriesCollection(1).XValues = "=Sheet1!$B$2:$B$26001"
.SeriesCollection(1).Values = "=Sheet1!$C$2:$C$26001"
'Titles
.HasTitle = True
.ChartTitle.Characters.Text = "X vs. Y"
.Axes(xlCategory, xlPrimary).HasTitle = True
.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "SOME TEXT"
.Axes(xlValue, xlPrimary).HasTitle = True
.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "SOME TEXT AS WELL"
.Axes(xlCategory).HasMajorGridlines = True
'Formatting
.Axes(xlCategory).HasMinorGridlines = False
.Axes(xlValue).HasMajorGridlines = True
.Axes(xlValue).HasMinorGridlines = False
.HasLegend = False
.Axes(xlValue).MaximumScale = 100
.Axes(xlValue).MinimumScale = 0
End With
'These lines, as their names suggest, turn off screen refresh and recalculating the workbook's formulas before running the macro.
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Sorry about the indentation of the first and last lines. I just wanted those lines to be in the code block instead of outside it.
THANKS :D
After collect range by your series name, and add series.
Sub creatingmyscatterplot()
Dim rngData() As Range, rngDB As Range
Dim Ws As Worksheet
Dim i As Long, n As Long
Set Ws = Sheets(1)
With Ws
Set rngDB = .Range("a2", .Range("a" & Rows.Count).End(xlUp))
End With
'By same value area, set rngData() array
n = 1
ReDim Preserve rngData(1 To n) 'dynamic array
For i = 1 To rngDB.Rows.Count
If rngData(n) Is Nothing Then
Set rngData(n) = rngDB(i)
Else
Set rngData(n) = Union(rngData(n), rngDB(i))
End If
If rngDB(i) <> rngDB(i + 1) Then
n = n + 1
ReDim Preserve rngData(1 To n)
End If
Next i
'Dim aRng As Range
'Dim seriescheck As Range
Dim Chart1 As Chart
Set Chart1 = Charts.Add
'Set aRng = Selection.CurrentRegion
'Set aRng = aRng.Offset(1, 0).Resize(aRng.Rows.Count - 1)
'Set seriescheck = aRng.Resize(aRng.Rows.Count, 1)
'Dim seriesName As String, seriesData As Range
'These lines, as their names suggest, turn off screen refresh and recalculating the workbook's formulas before running the macro.
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
With Chart1
.ChartType = xlXYScatterLines
'if your activecel in data range, series is created automatically Unintentionally. So,all series are to be deleted
For i = .SeriesCollection.Count To 1 Step -1
.SeriesCollection(i).Delete
Next i
'This creates the graph
For i = 1 To n - 1 'useful rngData()'s count is n -1
.SeriesCollection.NewSeries
.SeriesCollection(i).Name = rngData(i)(1)
.SeriesCollection(i).XValues = rngData(i).Offset(, 1)
.SeriesCollection(i).Values = rngData(i).Offset(, 2)
Next i
'Titles
.HasTitle = True
.ChartTitle.Characters.Text = "X vs. Y"
.Axes(xlCategory, xlPrimary).HasTitle = True
.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "SOME TEXT"
.Axes(xlValue, xlPrimary).HasTitle = True
.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "SOME TEXT AS WELL"
.Axes(xlCategory).HasMajorGridlines = True
'Formatting
.Axes(xlCategory).HasMinorGridlines = False
.Axes(xlValue).HasMajorGridlines = True
.Axes(xlValue).HasMinorGridlines = False
.HasLegend = False
.Axes(xlValue).MaximumScale = 100
.Axes(xlValue).MinimumScale = 0
End With
'These lines, as their names suggest, turn off screen refresh and recalculating the workbook's formulas before running the macro.
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub

Plotting multiple lines on a graph

I am attempting to plot a graph which has a number of Series plotted on the same axis. So we have:
Sheet1.ChartObjects(1).Activate
ActiveChart.ChartType = xlLineMarkers
Set ChartRange1 = Sheets("Series_2").Range("$E$8:$E20$")
ChartRangeAddr1 = ChartRange1.Address(External:=True)
Set ChartRange2 = Sheets("Series_3").Range("$E$8:$E$20")
ChartRangeAddr2 = ChartRange2.Address(External:=True)
(we could have many more here)
ActiveChart.SetSourceData Source:=Range(ChartRangeAddr1, ChartRangeAddr2)
ActiveChart.SeriesCollection(1).XValues = "=Series_1!$D$8:$D20"
ActiveChart.Axes(xlCategory, xlPrimary).HasTitle = True
ActiveChart.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "Dates"
ActiveChart.Axes(xlValue, xlPrimary).HasTitle = True
ActiveChart.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "USD"
ActiveChart.Axes(xlCategory).HasMajorGridlines = True
Note: Series_1 and Series_2 are data taken from different sheets. For some reason this code is only producing series one on the graph. Please, can anyone correct a mistake I am not seeing or point my compass to a solution to the general problem of plotting more than one line onto a graph in VBA. thanks
see if you can add a line like:
ActiveChart.SeriesCollection(1).YValues = "=Series_2!$E$8:$E20$"
ActiveChart.SeriesCollection(2).YValues = "=Series_3!$E$8:$E20$"
I find that when you record a macro it sometimes skips important steps.
SetSourceData only works with data on one sheet. You could do this (skip ChartRange1Address etc.):
ActiveChart.SetSourceData Source:=ChartRange1
ActiveChart.SeriesCollection(1).XValues = "=Series_1!$D$8:$D20"
With ActiveChart.SeriesCollection.NewSeries
ActiveChart.SeriesCollection(2).Values = ChartRange2
End With

Add horizontal axis labels - VBA Excel

I have a macro that creates a graph. I want VBA to read a range from the spreadsheet and use the values for horizontal axis labels. Basically I want to make this graph:
look like this (add the months on the bottom)
Thanks!
Macro:
Sub AddChartSheet()
'Variable declaration
Dim chtChart As Chart
Dim name1 As String
'Name is currently used for the title of the new tab where the chart is created and the chart title
name1 = "AHU-10-8"
'Create a new chart.
Set chtChart = Charts.Add
With chtChart
'.Name is the name of the tab where the new Chart is created
.Name = name1
.ChartType = xlLine
'Link to the source data range.
.SetSourceData Source:=Sheets(3).Range("A1:B5861"), _
PlotBy:=xlColumns
.HasTitle = True
.ChartTitle.Text = name1
.Axes(xlCategory, xlPrimary).HasTitle = True
.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "Time"
.Axes(xlValue, xlPrimary).HasTitle = True
.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "Valve Position (-)"
myFileName = name1 & ".png"
chtChart.Export Filename:=ThisWorkbook.Path & "\" & myFileName, Filtername:="PNG"
End With
End Sub
To adjust the data series you are using for the Date (horizontal axes). You can either add the following
ActiveSheet.ChartObjects("Chart 15").Activate
ActiveChart.SeriesCollection(1).XValues = "=Sheet1!$D$5:$D$19"
Note: you will first need to select the chart and adjust the range that I have to the range that you need it to be.
OR you can add
.SeriesCollection(1).XValues = "=Sheet1!$D$5:$D$19"
Between your code
.SetSourceData Source:=Sheets(3).Range("A1:B5861"), _
PlotBy:=xlColumns
and
.HasTitle = True
Can you share your macro or workbook?
I am not sure how you have your data setup, but you can change the format of the data that you have selected for your horizontal labels to be a date format. Or, in VBA you can change the selection to a number format of "mmmm" to just show the months.
Selection.NumberFormat = "mmmm"
The following should work. Remember to adjust the chart name in the following code
ActiveSheet.ChartObjects("Chart 4").Activate
ActiveChart.Axes(xlCategory).Select
Selection.TickLabels.NumberFormat = "mmmm"

Can't set chart Axis title (.caption)

I have a script that sets some ranges, then creates a chart. All goes well until .Axes(xlCategory, xlPrimary).Caption = "Time from Sent to Rec'd" where I get the error "Run-time error '438': Object doesn't support this property or method".
Here's my code:
Sub CreateChart()
dim avgWS as worksheet: set avgWS = activesheet
...[code here, setting the ranges and such]....
''' TIME TO CREATE THE CHART!!
with avgws
Dim newChart As Chart
' Set newChart = Charts.Add
Set newChart = Charts.Add.Location(xlLocationAsObject, avgWS.name)
With newChart
.ChartType = xlLineMarkers
.SeriesCollection.NewSeries
With .SeriesCollection(1)
.name = chartName
.Values = thePeopleChartValues
End With
.SeriesCollection.NewSeries
With .SeriesCollection(2)
.name = avgWS.Cells(1, dayLimitCol).Value
.Values = dayLimitValues
End With
.SeriesCollection.NewSeries
With .SeriesCollection(3)
.name = avgWS.Cells(1, overalltheAvgCol).Value
.Values = theAverages
End With
.HasTitle = True
.Axes(xlCategory).CategoryType = xlCategoryScale
.SetElement (msoElementPrimaryValueAxisTitleRotated)
.Axes(xlCategory, xlPrimary).Caption = "Time from the Sent to Shares Rec'd" '''' ERROR HERE!!
.SetElement (msoElementPrimaryCategoryAxisTitleAdjacentToAxis)
.Axes(xlCategory).Caption = "the Date"
.SetElement (msoElementChartTitleCenteredOverlay)
.Axes(xlCategory).Caption = "='CY 2014-15B Averages'!R1C2"
.SetElement (msoElementLegendRightOverlay)
.SetElement (msoElementLegendBottom)
End With
I've only included the Chart part, but if you would like/need more of the code just let me know. I have ranges and such set up, and get no errors there. It's only when I try to create the .Captions. If I walk through the code, via F8 and skip the three .caption lines, the chart gets created like I want....just how do I set those Axis captions? The macro recorder isn't much help (that's how I got to where I am now).
edit: Hm, if I use
.Axes(xlCategory, xlPrimary).HasTitle = True
.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "whatever whatever"
it sets the horizontal axis caption to "Whatever whatever". I guess I'm making progress, but I want that to be the vertical title, not horizontal and can't figure out how to do so.
Before you start formatting the axis title, create it:
.Axes(xlCategory, xlPrimary).HasTitle = True
Then to access the caption make sure you go through the AxisTitle object:
.Axes(xlCategory, xlPrimary).AxisTitle.Caption = ""
Then use
.Axes(xlCategory, xlPrimary).AxisTitle.Orientation = xlVertical
Hope that helps.

Scatter Plot graphing excel VBA - wont graph my range of data

Here's the section of the code that is giving me trouble. I incorporated messagebox's to let me know that things are working up to that given point. So when I type "MsgBox xaxis.Address()" it comes out like $C$20:$C$42. Which is what im looking to graph on the x-axis. The issue is, my graph doesnt actually show up with that on the x-axis... it graphs like the entire sheet. I am guessing my issue lies with the syntax of xaxis that I am using.
Dim StartTime As Range
Dim EndTime As Range
Set StartTime = wb1.Sheets("Sheet2").Range("C:C").Find(wb1.Sheets("Sheet1").Range("$B$2").Text, MatchCase:=False, lookat:=xlWhole)
Set EndTime = wb1.Sheets("Sheet2").Range("C:C").Find(wb1.Sheets("Sheet1").Range("B3").Text, MatchCase:=False, lookat:=xlWhole)
'If Not StartTime Is Nothing Then
'End If
MsgBox StartTime.Address()
MsgBox EndTime.Address()
MsgBox StartTime.Value
MsgBox EndTime.Value
MsgBox "Hi"
Dim xaxis As Range
Dim yaxis As Range
Set xaxis = Range(StartTime.Address & ":" & EndTime.Address)
MsgBox xaxis.Address
'Set xaxis = Range("$C$16", Range("$C$16").End(xlDown))
Set yaxis = xaxis.Offset(0, ColumnOffset:=1)
MsgBox yaxis.Address
'''''''''''''''''''''''
'Dim x As String
'Dim y As String
' x = xaxis.Address
'MsgBox "Hi"
'y = yaxis.Address
'MsgBox x
Set Chrt = Charts.Add
With Chrt
.ChartType = xlXYScatter
.SeriesCollection.NewSeries
'.SeriesCollection(1).Name = "=""Scatter Chart"""
.SeriesCollection(1).Values = yaxis
.SeriesCollection(1).XValues = xaxis
'Titles
.HasTitle = True
.ChartTitle.Characters.Text = "Platen1"
.Axes(xlCategory, xlPrimary).HasTitle = True
.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "Time (Seconds)"
.Axes(xlValue, xlPrimary).HasTitle = True
.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "Temp (Deg. C)"
.Axes(xlCategory).HasMajorGridlines = True
'Formatting
.Axes(xlCategory).HasMinorGridlines = False
.Axes(xlValue).HasMajorGridlines = True
.Axes(xlValue).HasMinorGridlines = False
.HasLegend = False
End With
My overall goal: I have a spreadsheet with data that gets updated daily. I need the user to be able to input a start time, end time, and then machine number. This needs to be used to generate a graph from that data. The start and end time are always in column C, but the specific rows are always changing. So what I do is I locate the matching start time and end time from the data, and then I create this range (StartTime or EndTime). The machine will determine the column of data to use for the y-axis which im just offsetting from the x-axis.
Any help would be greatly appreciated.
Edit: I fixed the above by adding the following code right under the chart creation:
Do Until .SeriesCollection.Count = 0
.SeriesCollection(1).Delete
Loop
The issue i realize is that the "xaxis" and "yaxis" are grabbing data from Sheet1 while i want it to grab data from Sheet 2. How do I go about declaring that it should be graphing from Sheet2?
Do it like this
Set xaxis = Sheets("Sheet2").Range(StartTime.Address & ":" & EndTime.Address)
Set yaxis = xaxis.Offset(0, ColumnOffset:=1)