Fixing range of y values for graph with VBA - excel

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

Related

Adding new series to a graph automatically

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

VBA - Modification of SourceData (Dynamic Range) of existing STock OHLC Chart

I am working on Stock OHLC Chart present in Sheets("Exhibit") and selecting Data from Sheets("75Min"). However i am succeeding to choose appropriate data range but can not add at Line Nu 15 .SetSourcedata, could you please help me to get out from this problem
Code is as follows.
Sub Edit75MinChartToOHLCCandlestickChart()
Dim OHLCChart As ChartObject
Dim LastRow As Integer
Dim RngSt As Integer
Sheets("75Min").Select
Range("A1").Select
Range("A1").End(xlDown).Select
LastRow = ActiveCell.Row
RngSt = LastRow - 59
RngEnd = LastRow + 15
Set OHLCChart = ThisWorkbook.Worksheets("Exhibit").ChartObjects(1)
With OHLCChart.Chart 'Worksheets("Exhibit").ChartObjects("Chart 2").Chart
.SetSourceData ThisWorkbook.Worksheets("75Min").Range(RngSt, RngEnd)
.ChartType = xlStockOHLC
.HasTitle = True
.ChartTitle.Text = "75Min Candlestick chart"
.Axes(xlValue, xlPrimary).HasTitle = False
.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "Price"
.PlotArea.Format.Fill.ForeColor.RGB = RGB(242, 242, 242)
.ChartArea.Format.Line.Visible = msoFalse
.Parent.Name = "OHLC Chart"
End With
End Sub
Thank You
Best to avoid Select and Activate. Your range is not a valid range. You are saying Range(#,#), which isn't valid and I doubt you were trying to get whole rows. Assuming you only wanted the first column, this will work. You can expand the column from 1 if you need the labels.
Sub Edit75MinChartToOHLCCandlestickChart()
Dim OHLCChart As ChartObject
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Set ws1 = ThisWorkbook.Worksheets("75Min")
Set ws2 = ThisWorkbook.Worksheets("Exhibit")
Dim MyRng As Range
Dim LastRow As Long
Dim RngSt As Long
Dim RngEnd as Long
LastRow = ws1.Cells(ws1.Rows.Count, 1).End(xlUp).Row
RngSt = LastRow - 59
RngEnd = LastRow + 15
Set MyRng = ws1.Range(ws1.Cells(RngSt, 1), ws1.Cells(RngEnd, 1))
Set OHLCChart = ws2.ChartObjects(1)
With OHLCChart.Chart 'Worksheets("Exhibit").ChartObjects("Chart 2").Chart
.SetSourceData MyRng
You can include these lines to adjust the Y axis scale:
Dim Ymin As Double, Ymax As Double
Ymin = WorksheetFunction.Min(MyRng)
Ymax = WorksheetFunction.Max(MyRng)
With OHLCChart.Chart.Axes(xlValue)
.MinimumScale = Ymin
.MaximumScale = Ymax
End With
But these are probably going to be ugly axis limits. I've written a tutorial called Calculate Nice Axis Scales in Excel VBA which contains an algorithm to adjust the min and max outwards slightly so that the scale is more human-readable.

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

How to skip empty cells in a range to use as range for a scatterplot?

I'm fairly new to VBA and trying to dynamically select the data i need for my scatter plot. I'm trying skip any rows that have a blank in the "A" column so the scatter plot is continuous.
The code in the commented section is what i tried first, but that gives me a method range of object_global failed error on the setsourcedata line. I expect the code to skip the empty cell and continue through mydatatest variable until it reaches the end. However, the actual output stops at the first empty cell.
Set mydatatest = ActiveWorkbook.Sheets("Data - PLC").Range("A3:A94")
'Set mydata = ActiveWorkbook.Sheets("Data - PLC").Range("A2:C2")
Set mydata = ActiveWorkbook.Sheets("Data - PLC").Range("A2")
For Each mydatapoint In mydatatest
If IsEmpty(mydatapoint) = False Then
'Set mydata = Union(mydata, Range(mydatapoint, mydatapoint.Offset(0, 2)))
Set mydata = Union(mydata, mydatapoint)
End If
Next mydatapoint
ActiveWorkbook.Sheets("Report").Select
Set cht1 = Sheet1.ChartObjects.Add(10, 365, 275, 200)
With cht1.Chart
.ChartType = xlXYScatterLinesNoMarkers
.SeriesCollection.Add Source:=Range(mydata, mydata.Offset(0, 2))
'.SetSourceData Source:=Range(mydata)
End With
The error is in .SetSourceData Source:=Range(mydata). It should be .SetSourceData Source:=myData. myData is already declared as Range(). The rest is quite ok:
Option Explicit
Sub TestMe()
Dim myDataTest As Range
Dim myData As Range
Dim wks As Worksheet
Set wks = Worksheets(1)
Set myDataTest = wks.Range("A3:A94")
Set myData = wks.Range("A2")
Dim myDataPoint As Range
For Each myDataPoint In myDataTest
If Not IsEmpty(myDataPoint) Then
Set myData = Union(myData, myDataPoint)
End If
Next myDataPoint
Dim cht As Object
Set cht = wks.ChartObjects.Add(10, 365, 275, 200)
With cht.Chart
.ChartType = xlXYScatterLinesNoMarkers
.SeriesCollection.Add Source:=wks.Range(myData, myData.Offset(0, 2))
.SetSourceData Source:=myData
End With
End Sub

Modifying Data Labels from Center to Above in Excel VBA

I am trying to make some revisions to my DataLabels.
I would like the column width (Down, Up and Total) to match the size of the text. I would also like to make the data label text bolded and easier to see.
Does anyone know the best method to do this given my code and the existing chart that I have right now?
Thanks!
Sub Waterfall()
'
' Waterfall Macro
'
'
Range("A7").Select
Dim rngData As Range
Dim intCounter As Integer
Dim rngToSelect As Range
Dim srs As Series
Dim i As Long
Set rngData = ActiveCell.CurrentRegion
Set rngToSelect = Range(rngData.Cells(1, 1), rngData.Cells(rngData.Rows.Count, 1))
For intCounter = 1 To rngData.Columns.Count
If rngData.Cells(1, intCounter).Value <> "Values" Then
Set rngToSelect = Union(rngToSelect, Range(rngData.Cells(1, intCounter), rngData.Cells(rngData.Rows.Count, intCounter)))
End If
Next intCounter
rngToSelect.Select
ActiveSheet.Shapes.AddChart.Select
ActiveChart.SetSourceData Source:=rngToSelect
ActiveChart.ChartType = xlColumnStacked
ActiveChart.ChartGroups(1).GapWidth = 75
ActiveChart.SeriesCollection("Blank").Select
Selection.Format.Fill.Visible = msoFalse
For Each srs In ActiveChart.SeriesCollection
For i = 1 To UBound(srs.Values)
srs.Points(i).HasDataLabel = srs.Values(i) > 0
Next i
Next srs
ActiveChart.SeriesCollection("Blank").DataLabels.ShowValue = False
ActiveChart.SeriesCollection("Down").Interior.Color = RGB(255, 0, 0)
ActiveChart.SeriesCollection("Up").Interior.Color = RGB(0, 204, 0)
ActiveChart.Legend.LegendEntries(3).Select
Selection.delete
'Remove Gridlines
Dim axs As Axis
For Each axs In ActiveChart.Axes
axs.HasMajorGridlines = False
axs.HasMinorGridlines = False
Next
Range("A1").Select
End Sub
In order to change your data laebls text to bold try the following command:
ActiveChart.SeriesCollection("Down").DataLabels.Font.Bold = True

Resources