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"
Related
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.
I am trying to add a secondary vertical axis to my chart in VBA. I keep running into this error that says that the Method Axes of the Object _Chart has failed.
I have looked up solutions and implemented a few that stated to make sure that the secondary axis is first active. My code is below. The error occurs in the third to last line when I am trying to state that the secondary axis has a title. Any help is much appreciated since I am still a beginner in VBA.
Public Sub CreateChartForColumnsOneThreeandFive()
Dim myChartColumnsOneThreeandFive As ChartObject
Set myChartColumnsOneThreeandFive = ActiveSheet.ChartObjects.Add(Left:=150, Top:=150, Width:=500, Height:=400)
myChartColumnsOneThreeandFive.Chart.HasTitle = True
myChartColumnsOneThreeandFive.Chart.ChartTitle.Text = "Phase Detector Readback vs Substrate Forward Power"
myChartColumnsOneThreeandFive.Chart.Type = xlLine
myChartColumnsOneThreeandFive.Chart.SetSourceData Source:=ActiveWorkbook.Sheets("Sheet2").Range("C" & processRowBegin & ":C" & processRowEnd)
myChartColumnsOneThreeandFive.Chart.SetSourceData Source:=ActiveWorkbook.Sheets("Sheet2").Range("E" & processRowBegin & ":E" & processRowEnd)
myChartColumnsOneThreeandFive.Chart.SeriesCollection(1).Name = Range("C1")
myChartColumnsOneThreeandFive.Chart.SeriesCollection(1).Name = Range("E1")
myChartColumnsOneThreeandFive.Chart.SeriesCollection(1).Select
myChartColumnsOneThreeandFive.Chart.SeriesCollection(1).AxisGroup = 2
myChartColumnsOneThreeandFive.Chart.HasTitle = True
myChartColumnsOneThreeandFive.Chart.ChartTitle.Text = "Substrate Forward Power vs Phase Detector Readback"
myChartColumnsOneThreeandFive.Chart.Axes(xlCategory).HasTitle = True
myChartColumnsOneThreeandFive.Chart.Axes(xlCategory).AxisTitle.Caption = "Time"
myChartColumnsOneThreeandFive.Chart.Axes(xlValue, xlPrimary).HasTitle = True
myChartColumnsOneThreeandFive.Chart.Axes(xlValue, xlPrimary).AxisTitle.Caption = "Substrate Forward Power"
myChartColumnsOneThreeandFive.Chart.SeriesCollection(1).AxisGroup = xlSecondary
myChartColumnsOneThreeandFive.Chart.HasAxis(xlValue, xlSecondary) = True
myChartColumnsOneThreeandFive.Chart.Axes(xlValue, xlSecondary).HasTitle = True
myChartColumnsOneThreeandFive.Chart.Axes(xlValue, xlSecondary).AxisTitle.Select
myChartColumnsOneThreeandFive.Chart.Axes(xlValue, xlSecondary).AxisTitle.Text = _
"Phase Detector Readback"
End Sub
Even though not in this code, I assume processRowBegin and processRowEnd are defined somewhere else as Long and they have a numeric value.
Try the code below, it runs without errors, I am not sure what is your final goal and how your chart suppose to look like, but I think you can modify it easily to fit your needs.
Option Explicit
Public Sub CreateChartForColumnsOneThreeandFive()
Dim myChartColumnsOneThreeandFive As ChartObject
Set myChartColumnsOneThreeandFive = ActiveSheet.ChartObjects.Add(Left:=150, Top:=150, Width:=500, Height:=400)
With myChartColumnsOneThreeandFive.Chart
.HasTitle = True
.ChartTitle.Text = "Phase Detector Readback vs Substrate Forward Power"
.Type = xlLine
' create series 1, set values and name
.SeriesCollection.NewSeries
.SeriesCollection(1).Name = Range("C1")
.SeriesCollection(1).Values = ActiveWorkbook.Sheets("Sheet2").Range("C" & processRowBegin & ":C" & processRowEnd)
' create series 2, set values and name
.SeriesCollection.NewSeries
.SeriesCollection(2).Name = Range("E1")
.SeriesCollection(2).Values = ActiveWorkbook.Sheets("Sheet2").Range("E" & processRowBegin & ":E" & processRowEnd)
.SeriesCollection(1).AxisGroup = 2
.HasTitle = True
.ChartTitle.Text = "Substrate Forward Power vs Phase Detector Readback"
' set X-axis
.Axes(xlCategory).HasTitle = True
.Axes(xlCategory).AxisTitle.Caption = "Time"
' set Y-axis
.Axes(xlValue, xlPrimary).HasTitle = True
.Axes(xlValue, xlPrimary).AxisTitle.Caption = "Substrate Forward Power"
.SeriesCollection(1).AxisGroup = xlSecondary
' add a secondary Y-axis ans set it
.HasAxis(xlValue, xlSecondary) = True
.Axes(xlValue, xlSecondary).HasTitle = True
.Axes(xlValue, xlSecondary).AxisTitle.Select
.Axes(xlValue, xlSecondary).AxisTitle.Text = "Phase Detector Readback"
End With
End Sub
I ran into this issue and solved it by changing the order of my code. Here is the order that worked:
Delete previous chart series (optional)
Set chart type
Add primary y-axis series
Add secondary y-axis series
Format secondary y-axis
Format x axis
Format primary y-axis
I think what solved it was setting the chart type right near the beginning. There's definetly some flexibility in the order I've written here, but I haven't explored it.
My problem is that I want to make many graph in one chart but the data is from different sheets.
At the moment my code can only take multi data from one sheet, meaning I can plot 2 graph from one sheet.
My code at the moment is:
Sub ChartSheet()
Dim ChartSheet1 As Chart
Set ChartSheet1 = Charts.Add
With ChartSheet1
.SetSourceData Source:=Sheets("Sheet1").Range("E12:E6232, Y12:Y6232")
.ChartType = xlLine
.HasTitle = True
.ChartTitle.Characters.Text = "Test Chart"
.Axes(xlCategory, xlPrimary).HasTitle = True
.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "x"
.Axes(xlValue, xlPrimary).HasTitle = True
.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "y"
End With
End Sub
What I want is to say:
.SetSourceData Source:=Sheets("Sheet1").Range("E12:E6232, Y12:Y6232")
.SetSourceData Source:=Sheets("Sheet2").Range("D12:E23")
.SetSourceData Source:=Sheets("Sheet3").Range("Y12:Y6232, G27:G496, H3:5977")
and so on..
But when I do this my code it only print the last line from .SetSoureData
Hope some of you can help me work around this, Many thank in advarnce :)
Update:
I found abit of a work around by looping but this is not my total answer
But here is my other code:
Sub MultiSheetPlot()
Dim cht As Chart, s As Series, xRng As Range
Dim i As Long, chartName As String
Set cht = Charts.Add
cht.ChartType = xlLine
For i = 1 To 3
chartName = "Sheet" & i
Set xRng = Sheets("Sheet1").Range("A1:A20, C1:C20")
With cht.SeriesCollection.NewSeries()
.Values = xRng
.Name = chartName
End With
Next i
End Sub
the problem in this code is that it ignores the last range I define like the C10:C20
Responding to your latest update, I have a Sub that creates a series each time it's called from MultiSheetPlot Sub.
You can actually add more parameters to this Sub (as long as you remeber to pass them in the Calling).
Option Explicit
Dim cht As Chart
Sub MultiSheetPlot()
Set cht = Charts.Add
cht.ChartType = xlLine
' call the series creation chart function (each time for each series you want to add to the existing chart
Call Create_SeriesChart("Sheet1", Sheets("Sheet1").Range("E12:E6232"), 1, True, msoThemeColorText1)
Call Create_SeriesChart("Sheet1", Sheets("Sheet1").Range("Y12:Y6232"), 1, True, msoThemeColorText1)
End Sub
' ------ this Sub creates a series to the chart, it receives the following parameters: ------
' 1. seriesName - String
' 2. serValues - Range
' 3. lineWeight - Double (the weight of the line)
' 4. lineVis - Boolean (if you want to hide a certail series)
' 5. lineColor - MsoColorType (using the current's PC Theme colors
Sub Create_SeriesChart(seriesName As String, serValues As Range, lineWeight As Double, lineVis As Boolean, lineColor As MsoColorType)
Dim Ser As Series
Set Ser = cht.SeriesCollection.NewSeries
With Ser
.Name = seriesName
.Values = serValues
.Format.Line.Weight = lineWeight
If lineVis = True Then
.Format.Line.Visible = msoTrue
Else
.Format.Line.Visible = msoFalse
End If
.Format.Line.ForeColor.ObjectThemeColor = lineColor ' Line color Black
End With
End Sub
My solution is use Name of plage, you can give a name of your range
Like in my photo :
Everytime when you want to use these datas you just need call them
Like this plage i gived them name Poste_EtatDeLaDemande
When i want to use these elements i just call it like Range("Poste_EtatDeLaDemande") Excel will find it you don't need tell them where it is anymore ; )
I am writing a code that creates a pivot chart with a variable title based on the filter criteria chosen.
I am having trouble typing a formula into the .charttitle.characters.text format and having it auto update when a new filter is chosen in the pivot table.
Here is my code. As you can see, I am trying to relate the Chart title back to a cell that formulates based off of the pivot table. If there an easier way to code this, please let me know.
The Pivot Table filter is located in Sheet("Database Pivot").Range("B1") if that wasn't particularly clear.
Set objTable = ActiveSheet.PivotTables("SA Pivot Table")
Set objPivRange = objTable.TableRange1
Sheets("SA").Range("Z1").Formula = "=IF('Database Pivot'!$B$1=""(All)"", ""Since "" & TEXT('Database'!$L$2,""MM/DD/YYYY""), IF('Database Pivot'!$B$1=""(Multiple Items)"", ""For Selected Dates"", ""On "" & TEXT('Database Pivot'!$B$1,""MM/DD/YYYY"")))"
Set objChart = Charts.Add
With objChart
.HasTitle = True
.ChartTitle.Characters.Text = "=""Average WC Adherence "" & 'SA'!$Z$1"
.ChartType = xlColumnClustered
.Location xlLocationAsNewSheet, Name:="Adherence Chart"
.PlotBy = xlColumns
.SetSourceData objPivRange
With .Axes(xlValue, xlPrimary)
.HasTitle = True
.AxisTitle.Characters.Text = "% Adherence"
End With
With .Axes(xlCategory, xlPrimary)
.HasTitle = True
.AxisTitle.Characters.Text = "Work Center"
.TickLabels.Orientation = 90
.TickLabels.Font.Size = 7.5
End With
End With
I don't know why, but it appears that certain formulas and operators cannot be used in the formula of a dynamic Chart table. We know that a simple, single cell reference in a formula will work, like "='SA'!$Z$1".
Therefore, your best option would be to create the dynamic chart title in another cell, and then have the formula in your chart title reference the single cell containing your dynamic chart title. Below the line where you set the formula of cell Z1, add the following line
' I use Z2, use whatever cell you see fit
Sheets("SA").Range("Z2") = "Average WC Adherence " & Sheets("SA").Range("Z1")
Then update the chart title formula to reference cell
.ChartTitle.Caption = "='SA'!$Z$2"
Noticed I also changed .Characters.Text to .Caption, since the Caption property can detect if it should contain text or a formula
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)