I am attempting to plot multiple named ranges on to a chart. These named ranges (named for example Time_Series_1) are of the form:
=INDIRECT(Ranges!$AJ$3) where this argument Ranges!$AJ$3 is for example
="'Source Data'!"&ADDRESS(N3,(Comparisons!$G$28+5))&":"&ADDRESS(N3(Comparisons!$I$28+5))
The code I'm attempting to use to plot the these ranges (I have started with one as any more remain to be impossible as one is not working) is:
Sheets("Comparisons").Select
Sheet10.ChartObjects("Chart 2").Activate
Set Rng = range("Time_Series_1")
Set Date_Rng = range("Time_Series_Dates_1")
With ActiveChart
.SetSourceData Source:=Rng
.XValues = Date_Rng
End With
It's not working! The Chart remains blank. Completely empty. What am I not updating? What am I not activating?
Thanks
I have no way of testing your model, but try this:
Dim Chart_Sheet As Worksheet
Dim My_Chart As ChartObject
Dim Rng As Range
Dim Date_Rng As Range
Set Chart_Sheet = ThisWorkbook.Sheets("Comparisons")
Set My_Chart = Chart_Sheet.ChartObjects("Chart 2")
Set Rng = Range("Time_Series_1")
Set Date_Rng = Range("Time_Series_Dates_1")
With My_Chart.Chart
.SetSourceData Source:=Rng
.SeriesCollection(1).XValues = Date_Rng
End With
(I am assuming that your Indirect reference works properly)
ActiveChart.SeriesCollection(1).XValues = Date_Rng
ActiveChart.SeriesCollection(1).Values = Rng
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 = "Pounds"
ActiveChart.Axes(xlCategory).HasMajorGridlines = True
Related
I have an assignment for my school exam project and i have tried and tried and hope u can help me
The question is like this:
As "delayed" students constitute a "risk" for the university, it is important for the Head of Studies to be prepared
Some additional statistics about this group of students. Create a sub / function that can graphs the following i
The sheet "Delayed Students":
The percentage distribution of late students between each Study Board
The percentage distribution of late students between each PROGRAM_ID's
The percentage distribution of late students between each faculty
The percentage distribution of late students between each campus
The number of late students distributed by ENROLL_PERIOD
The Head of Studies would like to be able to generate the statistics by pressing a button on the sheet "Delayed Students".
This is my code and it doesn't want to work:
Set rng = ActiveSheet.Range ("A2: I2")
Set cht = ActiveSheet.Shapes.AddChart2
cht.Chart.SetSourceData Source: = rng
cht.Chart.Chartype = xlXYScatterLines
cht.Chart.ChartTitle.Text = "Statistic of Student"
You have to declare the rng and the cht as objects. This works:
Public Sub TestMe()
Dim rng As Object, cht As Object
Set rng = ActiveSheet.Range("A2: I2")
Set cht = ActiveSheet.Shapes.AddChart2
With cht.Chart
.SetSourceData Source:=rng
.ChartType = xlXYScatterLines
.ChartTitle.Text = "Statistic of Student"
End With
End Sub
I found this MSDN-page which explains how to create graphs via VBA:
https://msdn.microsoft.com/en-us/library/office/aa203725(v=office.11).aspx
Code from their page:
Sub AddChartSheet()
Dim chtChart As Chart
'Create a new chart.
Set chtChart = Charts.Add
With chtChart
.Name = "Tool Sales2"
.ChartType = xlColumnClustered
'Link to the source data range.
.SetSourceData Source:=Sheets("Sheet1").Range("A1:D5"), _
PlotBy:=xlRows
.HasTitle = True
.ChartTitle.Text = "=Sheet1!R1C2"
.Axes(xlCategory, xlPrimary).HasTitle = True
.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "Month"
.Axes(xlValue, xlPrimary).HasTitle = True
.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "Sales"
End With
End Sub
So this removes your mistakes:
Dim cht As Chart
Dim rng as Range
Set rng = ActiveSheet.Range ("A2: I2")
Set cht = ActiveSheet.Shapes.AddChart2
cht.Chart.ChartType = xlXYScatterLines
cht.Chart.SetSourceData Source:= rng, PlotBy:=xlRows
cht.Chart.ChartTitle.Text = "Statistic of Student"
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
I have written a macro to generate graph in excel but i want that graph to be generated in the next sheet not in the same sheet.i have pasted my macro below its working properly i just want it to be in the next sheet. please provide me some solution*
Sub LumData1()
If IsEmpty(Range("B2,D2")) = False Then
Range("B:B,D:D,H:H,I:I,J:J,M:M").Select
Range("M1").Activate
ActiveSheet.Shapes.AddChart.Select
ActiveChart.ChartType = xlXYScatterSmoothNoMarkers
ActiveChart.SetSourceData Source:=Sheets(ActiveSheet.Name).Range( _
"$B:$B,$D:$D,$H:$H,$I:$I,$J:$J,$M:$M" _
)
ActiveChart.Location Where:=xlLocationAsObject, Name:=ActiveSheet.Name
With ActiveChart.ChartArea
.Width = 1060
.Height = 420
.Left = 0
End With
ActiveChart.SeriesCollection(1).Select
ActiveChart.SeriesCollection(1).AxisGroup = 2
ActiveChart.SeriesCollection(5).Select
ActiveChart.SeriesCollection(5).AxisGroup = 2
ActiveChart.Axes(xlCategory, xlPrimary).HasTitle = True
ActiveChart.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "Date"
ActiveChart.Axes(xlValue, xlPrimary).HasTitle = True
ActiveChart.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "Value"
ActiveChart.Axes(xlCategory).TickLabels.Orientation = 45
End If
End Sub
My answer covers not only how to solve your question in your post, but how to automatically define and set-up charts in VBA in a “cleaner” and safer way.
It's better if you avoid using ActiveSheet, Select, and ActiveChart. Instead always use referenced objects, in this case Worksheets and ChartObject. E.g Dim ChtObj As ChartObject , and later set it with Set ChtObj = ShtCht.ChartObjects.Add(100, 100, 500, 500) , where ShtCht is the worksheet where you create your chart.
Once you defined and set your ChartObject, its quite easy to modify its properties by using the With ChtObj , and also nested properties, by adding With .Chart.ChartArea under the first With statement.
Code
Option Explicit
Sub LumData1()
Dim ChtObj As ChartObject
Dim ShtSrc As Worksheet
Dim ShtCht As Worksheet
' change "Sheet1" to your sheet's name (where you have your chart's data)
Set ShtSrc = Worksheets("Sheet1") ' <-- I preffer not to work with ActiveSheet
'Set ShtCht = Worksheets("Sheet2") ' <-- set the chart's destination worksheet
Set ShtCht = Worksheets.Add ' <-- create a new worksheet to place the chart
ShtCht.Name = "Chart"
If Not IsEmpty(ShtSrc.Range("B2,D2")) Then
Set ChtObj = ShtCht.ChartObjects.Add(100, 100, 500, 500)
With ChtObj
.Chart.ChartType = xlXYScatterSmoothNoMarkers
.Chart.SetSourceData ShtSrc.Range("$B:$B,$D:$D,$H:$H,$I:$I,$J:$J,$M:$M")
' set position of the chart to Cell M1
.Top = ShtCht.Range("M1").Top
.Left = ShtCht.Range("M1").Left
' modify chart position and dimensions
With .Chart.ChartArea
.Width = 1060
.Height = 420
.Left = 0
End With
With .Chart
.SeriesCollection(1).AxisGroup = 2
.SeriesCollection(5).AxisGroup = 2
.Axes(xlCategory, xlPrimary).HasTitle = True
.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "Date"
.Axes(xlValue, xlPrimary).HasTitle = True
.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "Value"
.Axes(xlCategory).TickLabels.Orientation = 45
End With
End With
End If
End Sub
edited after OP's clarification he has to make a new sheet to host the chart into
to stick to your code as much as possible:
remove ActiveChart.Location Where:=xlLocationAsObject, Name:=ActiveSheet.Name
place the following code right before End if
Dim myChart As Chart: Set myChart = ActiveChart
Worksheets.Add
myChart.Location Where:=xlLocationAsObject, Name:=ActiveSheet.Name
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.
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)