Formatting with Charts - vba

I have a sheet and I am generating the Chart from a table.
I would like to generate 2 charts. One chart with absolute numbers and other chart for the same data with Percentage.
Right now, for this, I am using two code, just by adding a line for generating the chart with Y.axis in percentage.
I would like to define column where my chart will start (for eg: chart1 from G7) and chart2 from G15. (I don't have this in my code)
I also, would like to define the length , height and width for my chart.(I don't have this in my code)
It would be great if you can help me add this requirement and do it In a single program.
Sub chartstatus()
Dim rng As Range
Dim cht As Object
Set rng = ActiveSheet.Range("A2:E53")
Set sh = ActiveSheet.Shapes.AddChart
sh.Select
Set cht = ActiveChart
With cht
.SetSourceData Source:=rng
.ChartType = xlColumnClustered
cht.Axes(xlSecondary).TickLabels.NumberFormat = "0.0%"
End With
cht.SeriesCollection(1).Format.Fill.ForeColor.RGB = RGB(255, 255, 255) '<~~ Red
cht.SeriesCollection(2).Format.Fill.ForeColor.RGB = RGB(255, 0, 0)
cht.SeriesCollection(3).Format.Fill.ForeColor.RGB = RGB(0, 255, 0)
cht.HasTitle = True
cht.ChartTitle.Text = "Result 2017"
End Sub
I use the same code, deleting the line to generate the second chart
cht.Axes(xlSecondary).TickLabels.NumberFormat = "0.0%"

The easier way if to use the ChartObject to create and define the chart, and then modify all it's properties (such as position and dimension).
The code below will create the first chart, place it in Cell "G7", and I modifed it's dimensions to show you the properties you need to modify.
You can add another one for the second chart (with an easy copy>>paste).
Code
Option Explicit
Sub chartstatus()
Dim Rng As Range
Dim ChtObj As ChartObject
Set rng = ActiveSheet.Range("A2:E53")
' use ChartObject instead of shape
Set ChtObj = ActiveSheet.ChartObjects.Add(100, 100, 500, 500) '<-- default dimension and location >> can modify later
With ChtObj
.Chart.ChartType = xlColumnClustered
.Chart.SetSourceData Rng
With .Chart
.Axes(xlSecondary).TickLabels.NumberFormat = "0.0%"
.SeriesCollection(1).Format.Fill.ForeColor.RGB = RGB(255, 255, 255) '<~~ Red
.SeriesCollection(2).Format.Fill.ForeColor.RGB = RGB(255, 0, 0)
.SeriesCollection(3).Format.Fill.ForeColor.RGB = RGB(0, 255, 0)
.HasTitle = True
.ChartTitle.Text = "Result 2017"
End With
' set position of the chart to Cell G7
.Top = Range("G7").Top
.Left = Range("G7").Left
' change the dimensions of the chart
With .Chart.ChartArea
.Width = 1060
.Height = 420
End With
End With
End Sub

For changing the chart location :
vba to add a shape at a specific cell location in Excel
For chart size:
sh.Width =100
sh.Height =100

Related

Remove the blank row values in chart

I am generating a chart from table. the table rows are not completely filled.
so when I am generating an chart, I get the value of not filled columns also as "0". I would like to remove the "0" (value of blank rows") in my chart. Is
there a way I can do this? any lead would be helpful
Sub chartResult()
Dim rng As Range
Dim cht As Object
Set rng = ActiveSheet.Range("B2:D53")
ThisWorkbook.Sheets("Result").ChartObjects.delete
Set sh = ActiveSheet.ChartObjects.Add(Left:=440, _
Width:=600, _
Top:=340, _
Height:=250)
sh.Select
Set cht = ActiveChart
With cht
.SetSourceData Source:=rng
.ChartType = xlColumnClustered
End With
cht.SeriesCollection(1).name = "Ov"
cht.SeriesCollection(2).name = "O"
cht.SeriesCollection(3).name = "To"
cht.SeriesCollection(1).HasDataLabels = True
cht.SeriesCollection(2).HasDataLabels = True
cht.SeriesCollection(3).HasDataLabels = True
cht.SeriesCollection(1).Format.Fill.ForeColor.RGB = RGB(72, 118, 255) '<~~ Red
cht.SeriesCollection(2).Format.Fill.ForeColor.RGB = RGB(255, 0, 0)
cht.SeriesCollection(3).Format.Fill.ForeColor.RGB = RGB(0, 167, 0)
cht.HasTitle = True
cht.ChartTitle.Text = "Result "
End Sub
Try the property Chart.DisplayBlanksAs and set xlNotPlotted.
So in the code the change looks some what as shown below in with statement.
With cht
.SetSourceData Source:=rng
.ChartType = xlColumnClustered
.DisplayBlanksAs = xlNotPlotted //ADD THIS STAEMENT.
End With
#Jenny - I can't guarantee this will work, I don't work with charts, but give it a try.
With cht
.SetSourceData Source:=rng
.ChartType = xlColumnClustered
.PivotItems("0").Visible = False
End With

Customzing the Charts using VBA

I have a sheet with Pivot table and I am creating an Column stacked chart from the table.
I would like to change the colours of Legend entries in chart and would like to have an title for the chart every time I create the chart.
I tried the below code and I'm getting
Object variable or with block variable not set
I get the error in the line
cht.SeriesCollection(1).Format.Fill.ForeColor.RGB = RGB(155, 213, 91)
Could anyone, tell me how I could create chart for my requirements. I have added an image of my current chart and required chart.
Sub chart11()
Dim sh As Shape
Dim cht As Chart
If ActiveSheet.PivotTables.Count = 0 Then Exit Sub
Set ptable = ActiveSheet.PivotTables(1)
Set ptr = ptable.TableRange1
Set sh = ActiveSheet.Shapes.AddChart
sh.Select
With ActiveChart
.SetSourceData ptr
.ChartType = xlColumnStacked
End With
cht.SeriesCollection(1).Format.Fill.ForeColor.RGB = RGB(155, 213, 91)
cht.Axes(xlCategory).MinimumScale = 5
cht.Axes(xlCategory).MaximumScale = 40
cht.HasTitle = True
cht.ChartTitle.Text = "Default Chart"
End Sub
This is the chart generated by my code now, if I comment the error line:
I would like to have a chart of this type with change in colour legends and chart title:
You can't use cht.Axes(xlCategory).MinimumScale = 5 and MaximumScale.
Because Pivot chart do not assist Scatterchart.
Only in scatter chart, you can set xlCategory Scale.
Sub chart11()
Dim sh As Shape
Dim cht As Chart
If ActiveSheet.PivotTables.Count = 0 Then Exit Sub
Set ptable = ActiveSheet.PivotTables(1)
Set ptr = ptable.TableRange1
Set sh = ActiveSheet.Shapes.AddChart
sh.Select
Set cht = ActiveChart
With cht
.SetSourceData ptr
.ChartType = xlColumnStacked
End With
cht.SeriesCollection(1).Format.Fill.ForeColor.RGB = RGB(255, 0, 0) '<~~ Red
cht.SeriesCollection(2).Format.Fill.ForeColor.RGB = RGB(0, 255, 0) '<~~ green
'cht.Axes(xlCategory).MinimumScale = 5
'cht.Axes(xlCategory).MaximumScale = 40
cht.HasTitle = True
cht.ChartTitle.Text = "Default Chart"
End Sub

Black Border around the Column Chart in VBA

I try to set a black border around the Column chart from my Vba CODE. This is what i have now. The last row where i set Border.ColorIndex obviously does not work. Currently the column looks like this.
I want it to look like this.
Here is my code.
ActiveSheet.Cells(10000, 10000).Select
ActiveSheet.Shapes.AddChart.Select
With ActiveChart ' clear SeriesCollection
Do Until .SeriesCollection.Count = 0
.SeriesCollection(1).Delete
Loop
End With
ActiveChart.ChartType = xlColumnClustered
ActiveChart.PlotVisibleOnly = True
ActiveChart.Location Where:=xlLocationAsNewSheet, Name:="Plottt" ' rename chart sheets
' create SeriesCollection for each line
ActiveChart.SeriesCollection.NewSeries
ActiveChart.SeriesCollection(1).Name = "Hallo"
ActiveChart.SeriesCollection(1).XValues = breaks
ActiveChart.SeriesCollection(1).Values = freq
ActiveChart.ChartGroups(1).GapWidth = 0
ActiveChart.ChartGroups(1).Border.ColorIndex = 3
Also i would like to reduce the step size from my code. Help with this would also be appreciated.
To set the border color for a SeriesCollection(1) use the line below:
ActiveChart.SeriesCollection(1).Format.Line.ForeColor.RGB = RGB(255, 0, 0)
Note: it's better to not use ActiveChart, and it's "relatives". Instead use referenced objects. In this case use a ChartObject.
Simple reference code:
Dim Chtobj As ChartObject
' modify "Chart_Data" Name to your Sheet, and "Chart 1" to your chart's name
Set Chtobj = Sheets("Chart_Data").ChartObjects("Chart 1")
With Chtobj
' modify the chartobject properties here...
' modify the major unit of X-axis
.Axes(xlCategory).MajorUnit = 5 '<-- modify to whatever value you want
' modify the minor unit of X-axis
.Axes(xlCategory).MinorUnit = 1
End With
I am not sure why the border isn't showing, though I suspect that there must be a property that determines its visibility or thickness.
For cleaning up your code though, try this:
Dim oChart as Object
ActiveSheet.Cells(10000, 10000).Select
Set oChart = ActiveSheet.Shapes.AddChart
With oChart' clear SeriesCollection
Do Until .SeriesCollection.Count = 0
.SeriesCollection(1).Delete
Loop
.ChartType = xlColumnClustered
.PlotVisibleOnly = True
.Location Where:=xlLocationAsNewSheet, Name:="Plottt" ' rename chart sheets
' create SeriesCollection for each line
.SeriesCollection.NewSeries
With .SeriesCollection(1)
.Name = "Hallo"
.XValues = breaks
.Values = freq
End With
With .ChartGroups(1)
.GapWidth = 0
With .Border
.ColorIndex = 3
' You may need the LineStyle property of the border
' https://msdn.microsoft.com/en-us/library/office/ff821622.aspx
.Linestyle = xlContinuous
End With
End With
End With ' Ends the with block for the entire chart
This should not only clean up your code quite a bit and make it easier to debug, but I have had cases where an object I am working with doesn't update properly if I try to update it's properties outside of a with block. I am not sure if there is a reason for this or not, but I err on the side of using the With block just in case.

Macro recorded VBA not creating same column graph

This is my data in Excel, I am trying to create a column graph from it
Data in column A is for the column labels and data in column B is for the column heights.
This is a picture of the graph I'm looking for:
I need to do this through VBA so I created the graph manually whilst recording a macro. I got this code:
Sub Macro5()
Range("A1:B10").Select
ActiveSheet.Shapes.AddChart2(201, xlColumnClustered).Select
ActiveChart.SetSourceData Source:=Range("Report!$A$1:$B$10")
ActiveChart.FullSeriesCollection(1).Select
ActiveChart.ChartGroups(1).Overlap = 0
ActiveChart.ChartGroups(1).GapWidth = 0
ActiveChart.ChartTitle.Select
ActiveChart.ChartTitle.Text = "Frequency"
Selection.Format.TextFrame2.TextRange.Characters.Text = "Frequency"
With Selection.Format.TextFrame2.TextRange.Characters(1, 9).ParagraphFormat
.TextDirection = msoTextDirectionLeftToRight
.Alignment = msoAlignCenter
End With
With Selection.Format.TextFrame2.TextRange.Characters(1, 9).Font
.BaselineOffset = 0
.Bold = msoFalse
.NameComplexScript = "+mn-cs"
.NameFarEast = "+mn-ea"
.Fill.Visible = msoTrue
.Fill.ForeColor.RGB = RGB(89, 89, 89)
.Fill.Transparency = 0
.Fill.Solid
.Size = 14
.Italic = msoFalse
.Kerning = 12
.Name = "+mn-lt"
.UnderlineStyle = msoNoUnderline
.Spacing = 0
.Strike = msoNoStrike
End With
ActiveChart.ChartArea.Select
End Sub
Now, when I run this macro again, it doesn't give me the same graph that I created when I recorded this macro.
This is the graph I get when I run the macro:
So, my question is why is it doing this and how do I fix it? How would I make a graph like the one I made manually from the data I have?
Recording the macro didn't work at all for me and gives me a completely different graph as you can see.
To summarize I created a graph manually and recorded a macro but running the macro doesn't create the graph I created before.
Below are the programmatic steps you need to take to replicate your chart.
You must have initially followed steps that aren't the same as the ones taken by the chart wizard. The generated code from the chart wizard isn't always that helpful.
The steps:
create the data in the worksheet
create a new shape with a chart and get the chart reference
assign the data to the chart
get the first series in the chart
assign the labels to the series
change the 'GapWidth' property on the chart's first 'ChartGroup' to get that chunky look
set chart title
Just drop this code into an empty module and run it:
Option Explicit
Sub CreateGraph()
Dim ws As Worksheet
Dim rngLabels As Range
Dim rngData As Range
Dim shpChart As Shape
Dim cht As Chart
Dim srs As Series
' set a reference to worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1")
' get ranges for labels and data
Set rngLabels = ws.Range("A1:A10")
Set rngData = ws.Range("B1:B10")
'uncomment if you want to fake up some data for the this
'ws.Cells.Delete
'rngLabels.Value = WorksheetFunction.Transpose(Array(10, 20, 30, 40, 50, 60, 70, 80, 90, 100))
'rngData.Value = WorksheetFunction.Transpose(Array(0, 1, 4, 9, 4, 3, 6, 4, 8, 6))
' create a chart shape, get chart reference and set source data
Set shpChart = ws.Shapes.AddChart2(201, xlColumnClustered)
Set cht = shpChart.Chart
cht.SetSourceData Source:=rngData, PlotBy:=xlColumns
' update the series object with labels
Set srs = cht.SeriesCollection(1)
srs.XValues = rngLabels
' make the graph 'chunky'
cht.ChartGroups(1).GapWidth = 0
' set chart title
cht.ChartTitle.Text = "Frequency"
End Sub

Generating dynamic charts with VBA

I have to create almost 200 charts of time series. So I tried to write a macro that finishes most of the work I need to do.
I generated names for the time series like this as an example:
Name:= AKB_ExampleA
The name refers to a dynamic range which I declared with this formula:
=OFFSET('sheet1'!$C$7:$C$137;0;0;COUNT('sheet1'!$C$7:$C$206))
So now to the macro I coded so far:
Sub graphik_erstellen()
Call graphik1("AKB")
End Sub
Sub graphik(Name As String)
'
Dim Ch As Chart
Dim RngToCover As Range
Set Ch = charts.Add
Set Ch = Ch.Location(Where:=xlLocationAsObject, Name:="Charts")
With Ch
.ChartType = xlLine
.SetSourceData Source:=Range(Name & "_ExampleA")
.SeriesCollection(1).XValues = Range("Datum_Volumen")
.SeriesCollection(1).Name = "SERIES1"
.FullSeriesCollection(1).Select
With Selection.Format.Line
.Visible = msoTrue
.ForeColor.RGB = RGB(192, 0, 0)
.Transparency = 0
End With
.HasTitle = True
.ChartTitle.Text = Name & ", Volumen (nach Korrektur)"
.HasLegend = True
.Legend.Position = xlLegendPositionBottom
.Legend.Select
Selection.Format.TextFrame2.TextRange.Font.Size = 11
Selection.Format.TextFrame2.TextRange.Font.Bold = msoTrue
With .Parent
.top = 100
.left = 100
.height = 287.149606299
.width = 543.685039370078
.Name = Name & "_chart"
End With
End With
End Sub
My problem is, that if I do that, the dynamic range is not really considered. It takes the range of the name (which is $C$7:$C$137) but it should refer to the name itself (in order to be dynamic).
So if I click on the chart to see the series, the series values are declared as: ='sheet1'!$C$7:$C$137 instead of ='sheet1'!ExampleA.
I would be really, really grateful if somebody could help me out.
Best
Elio
I have rearranged a few lines of code and tried to place comments refering to them as well.
Let me know what works. Youjust might need to change SeriesCollection to FullSeriesCollection. Other than that the code works in my Excel 2010.
The first Sub I just get the Range size according to the data available in Column "C" from Row 7.
Let me know.
Option Explicit
Sub graphik_erstellen()
'You always want to use direct reference to a sheet/range chart
'Refering to the WorkBook they are in and the worksheet as well.
'especially if you are opening multiple WorkBooks / Sheets
Dim CurrentWorkSheet As Worksheet
Set CurrentWorkSheet = Workbooks("Book1").Worksheets("Sheet1")
'Dynamically finding the end of the data in Column C
Dim LastRow As Long
LastRow = CurrentWorkSheet.Cells(CurrentWorkSheet.Rows.Count, "C").End(xlUp).Row
'Setting the range using the document reference aswell
Dim AKB As Range
Set AKB = Workbooks("Book1").Worksheets("Sheet1").Range(Cells(7, "C"), Cells(LastRow, "C"))
Call graphik(AKB)
End Sub
Sub graphik(Name As Range)
Dim DataChart As Chart
Dim RngToCover As Range
Set DataChart = Workbooks("Book1").Charts.Add
'With Excel 2010 the line above will automatically add the chart as a sheet and not aobject in a sheet
'Set DataChart = DataChart.Location(Where:=xlLocationAsObject, Name:="Charts")
With DataChart
.Name = "Charts" ' This will be the Name of the CHart Tab
.ChartType = xlLine
.SetSourceData Source:=Name
'You can see below I avoided the Select and Selection
With .SeriesCollection(1)
'Using Offset I just used the data one cell to the left of the range
.XValues = Name.Offset(0, -1)
.Name = "SERIES1"
With .Format.Line
.Visible = msoTrue
.ForeColor.RGB = RGB(192, 0, 0)
.Transparency = 0
End With
End With
.HasTitle = True
.ChartTitle.Text = "MIDDEL TOP TEXT" 'Name & ", Volumen (nach Korrektur)"
.HasLegend = True
With .Legend
.Position = xlLegendPositionBottom
.Format.TextFrame2.TextRange.Font.Size = 11
.Format.TextFrame2.TextRange.Font.Bold = msoTrue
End With
'Not sure about this, it doesnt work in my Excel 2010
'
With .Parent
.Top = 100
.Left = 100
.Height = 287.149606299
.Width = 543.685039370078
.Name = Name & "_chart"
End With
End With
End Sub
Let me know what your intention is for the Sheet and Chart names and then I can help with getting that to what you need as well.