How can I write a loop in vba for this code - excel

59.30 15 16 17
1 1,162,912,036.90 1,248,737,016.99 1,306,573,912.08
2 245,665,383.94 261,416,880.69 276,613,283.05
3 393,313,441.29 379,169,039.15 418,680,492.19
4 13,920,572.74 14,464,854.92 15,120,474.58
5 54,501,581.55 56,319,351.21 58,832,588.24
6 15,165,376.28 11,694,942.56 10,809,661.03
7 194,397,643.30 170,427,013.85 182,567,862.46
8 15,165,376.28 11,694,942.56 10,809,661.03
9 2,079,876,036.00 2,142,229,099.38 2,269,198,273.62
3% 6%
There are 7 tables like the above data in one excel tab in different area.I want to create a stacked column chart for each table. I wrote a code to create. Just want to know is that possiable to use loop to solve this problem? Code attached.
Sub FormatChartNIX()
'PURPOSE: Create a chart (chart dimensions are not required)
Dim rng As Range
Dim cht As Object
Dim ser As Series
Dim tmpCHR As ChartObject
'Chart1
'Your data range for the chart
Set rng = ActiveSheet.Range("B8:E17")
'Create a chart
Set cht = ActiveSheet.Shapes.AddChart
'Give chart some data
cht.chart.SetSourceData Source:=rng, PlotBy:=xlRows
'Determine the chart type
cht.chart.ChartType = xlColumnStacked
With ActiveSheet
.ChartObjects(1).Top = .Range("C24").Top
.ChartObjects(1).Left = .Range("C24").Left
End With
ActiveSheet.ChartObjects(1).Activate
ActiveChart.Axes(xlValue).Select
Selection.delete
ActiveChart.HasTitle = True
ActiveChart.ChartTitle.Text = ActiveSheet.Range("c1")
'Chart2
Set rng = ActiveSheet.Range("G8:J17")
Set cht = ActiveSheet.Shapes.AddChart
cht.chart.SetSourceData Source:=rng, PlotBy:=xlRows
cht.chart.ChartType = xlColumnStacked
With ActiveSheet
.ChartObjects(2).Top = .Range("H24").Top
.ChartObjects(2).Left = .Range("H24").Left
End With
ActiveSheet.ChartObjects(2).Activate
ActiveChart.Axes(xlValue).Select
Selection.delete
ActiveChart.HasTitle = True
ActiveChart.ChartTitle.Text = ActiveSheet.Range("h1")
'Chart3
Set rng = ActiveSheet.Range("L8:o17")
Set cht = ActiveSheet.Shapes.AddChart
cht.chart.SetSourceData Source:=rng, PlotBy:=xlRows
cht.chart.ChartType = xlColumnStacked
With ActiveSheet
.ChartObjects(3).Top = .Range("M24").Top
.ChartObjects(3).Left = .Range("M24").Left
End With
ActiveSheet.ChartObjects(3).Activate
ActiveChart.Axes(xlValue).Select
Selection.delete
ActiveChart.HasTitle = True
ActiveChart.ChartTitle.Text = ActiveSheet.Range("h1")
'Chart4
Set rng = ActiveSheet.Range("B82:E91")
Set cht = ActiveSheet.Shapes.AddChart
cht.chart.SetSourceData Source:=rng, PlotBy:=xlRows
cht.chart.ChartType = xlColumnStacked
With ActiveSheet
.ChartObjects(4).Top = .Range("C51").Top
.ChartObjects(4).Left = .Range("C51").Left
End With
ActiveSheet.ChartObjects(4).Activate
ActiveChart.Axes(xlValue).Select
Selection.delete
ActiveChart.HasTitle = True
ActiveChart.ChartTitle.Text = ActiveSheet.Range("c75")
'Chart5
Set rng = ActiveSheet.Range("G82:J91")
Set cht = ActiveSheet.Shapes.AddChart
cht.chart.SetSourceData Source:=rng, PlotBy:=xlRows
cht.chart.ChartType = xlColumnStacked
With ActiveSheet
.ChartObjects(5).Top = .Range("H51").Top
.ChartObjects(5).Left = .Range("H51").Left
End With
ActiveSheet.ChartObjects(5).Activate
ActiveChart.Axes(xlValue).Select
Selection.delete
ActiveChart.HasTitle = True
ActiveChart.ChartTitle.Text = ActiveSheet.Range("h75")
'Chart6
Set rng = ActiveSheet.Range("L82:o91")
Set cht = ActiveSheet.Shapes.AddChart
cht.chart.SetSourceData Source:=rng, PlotBy:=xlRows
cht.chart.ChartType = xlColumnStacked
With ActiveSheet
.ChartObjects(6).Top = .Range("M51").Top
.ChartObjects(6).Left = .Range("M51").Left
End With
ActiveSheet.ChartObjects(6).Activate
ActiveChart.Axes(xlValue).Select
Selection.delete
ActiveChart.HasTitle = True
ActiveChart.ChartTitle.Text = ActiveSheet.Range("m75")
'Chart7
Set rng = ActiveSheet.Range("Q82:T91")
Set cht = ActiveSheet.Shapes.AddChart
cht.chart.SetSourceData Source:=rng, PlotBy:=xlRows
cht.chart.ChartType = xlColumnStacked
With ActiveSheet
.ChartObjects(7).Top = .Range("R51").Top
.ChartObjects(7).Left = .Range("R51").Left
End With
ActiveSheet.ChartObjects(7).Activate
ActiveChart.Axes(xlValue).Select
Selection.delete
ActiveChart.HasTitle = True
ActiveChart.ChartTitle.Text = ActiveSheet.Range("r75")
End Sub

Using named ranges and some arrays you can loop through it.
First, create named ranges for the ranges for each chart.
I added a small table in the spreadsheet and named each one the text in the first cell of the range (i.e., Chart1,... Chart7). The other ranges each go in the next cell, so the range named "Chart 1" is 4 cells.
(I also used the same ranges and cells that you did in your code above)
Chart1 B8:E17 C24 C1
Chart2 G8:J17 H24 H1
Chart3 L8:O17 M24 H1
Chart4 B82:E91 C51 C75
Chart5 G82:J91 H51 H75
Chart6 L82:O91 M51 R75
Chart7 Q82:T91 R51 R75
Sub FormatChartNIX_Modified()
Dim rng As Range
Dim cht As Object
Dim ser As Series
Dim tmpCHR As ChartObject
Dim MyArray(1 To 7, 0 To 3) As String
Dim i As Integer
For i = LBound(MyArray) To UBound(MyArray)
'Set Values - possibly with named ranges
Dim vArray() As Variant
Dim strNamedRange As String
strNamedRange = "Chart" & i
Set rng = Worksheets("Sheet1").Range(strNamedRange)
vArray = rng
Dim j As Integer
For j = LBound(MyArray, 2) To UBound(MyArray, 2)
MyArray(i, j) = vArray(1, j + 1)
Debug.Print MyArray(i, j)
Next j
Next i
For i = LBound(MyArray) To UBound(MyArray)
With ActiveSheet
Set rng = .Range(MyArray(i, 1)) '1 represents the data range
Set cht = .Shapes.AddChart
cht.Chart.SetSourceData Source:=rng, PlotBy:=xlRows
cht.Chart.ChartType = xlColumnStacked
.ChartObjects(i).Top = .Range(MyArray(i, 2)).Top '0 represents the chart name
.ChartObjects(i).Left = .Range(MyArray(i, 2)).Left '2 represents the cell identifying the chart location
.ChartObjects(i).Activate
With ActiveChart
.Axes(xlValue).Select
.Axes(xlValue).Delete
.HasTitle = True
.ChartTitle.Text = ActiveSheet.Range(MyArray(i, 3)).Text '3 represents the cell where the title text is located
End With
End With
Next i
End Sub
Do that, run the sub and it will create 7 charts as described in the table - using a loop.

Related

VBA-Excel - Graph creator

I'm trying to create a code for generate some graphs with some data already stored in arrays.
The actual final result of the macro is this graph:
The code used for it is the following:
Dim sht As Worksheet
Set sht = ActiveSheet
Dim chtObj As ChartObject
Set chtObj = sht.ChartObjects.Add(100, 10, 500, 300)
Dim cht As Chart
Set cht = chtObj.Chart
If IsZeroLengthArray(yData_TSI) = False Then
Dim ser As Series
Set ser = cht.SeriesCollection.NewSeries
ser.Values = yData_TSI
ser.XValues = xData_TSI
ser.Name = "TSI Predicant"
ser.ChartType = xlXYScatterSmooth
End If
If IsZeroLengthArray(yData_Pallet) = False Then
Dim ser2 As Series
Set ser2 = cht.SeriesCollection.NewSeries
ser2.Values = yData_Pallet
ser2.XValues = xData_Pallet
ser2.Name = "Pallet Decant"
ser2.ChartType = xlXYScatterSmooth
End If
If IsZeroLengthArray(yData_Vendor) = False Then
Dim ser3 As Series
Set ser3 = cht.SeriesCollection.NewSeries
ser3.Values = yData_Vendor
ser3.XValues = xData_Vendor
ser3.Name = "Vendor Decant"
ser3.ChartType = xlXYScatterSmooth
End If
If IsZeroLengthArray(yData_Prep) = False Then
Dim ser4 As Series
Set ser4 = cht.SeriesCollection.NewSeries
ser4.Values = yData_Prep
ser4.XValues = xData_Prep
ser4.Name = "Each"
ser4.ChartType = xlXYScatterSmooth
End If
If IsZeroLengthArray(yData_Each) = False Then
Dim ser5 As Series
Set ser5 = cht.SeriesCollection.NewSeries
ser5.Values = yData_Each
ser5.XValues = xData_Each
ser5.Name = "Prep"
ser5.ChartType = xlXYScatterSmooth
End If
I have in other arrays (tData_XXX) numbers that I would like to add as a label to the bullet points in the graph. To make myself clear, for the same graph generated before, let's imagine than for the "Vendor Decant" data the tData_Vendor array has the numbers (34, 5, 12). The desired result should be something like this:
How can I do this on the code?
Thanks!
Note:
All the arrays (yData_XXX, xData_XXX and tData_XXX) are always the same size
Untested, but something like this should work:
Sub CreateChart()
Dim sht As Worksheet, chtObj As ChartObject, cht As Chart
Set sht = ActiveSheet
Set chtObj = sht.ChartObjects.Add(100, 10, 500, 300)
Set cht = chtObj.Chart
AddSeries cht, "TSI Predicant", yData_TSI, xData_TSI, tData_TSI
AddSeries cht, "Pallet Decant", yData_Pallet, xData_Pallet, tData_Pallet
AddSeries cht, "Vendor Decant", yData_Vendor, xData_Vendor, tData_Vendor
AddSeries cht, "Each", yData_Prep, xData_Prep, tData_Prep '???
AddSeries cht, "Prep", yData_Each, xData_Each, tData_Each '???
End Sub
Sub AddSeries(cht As Chart, seriesName As String, xVals, yVals, labelVals)
Dim i As Long
If Not IsZeroLengthArray(yVals) Then
With cht.SeriesCollection.NewSeries
.ChartType = xlXYScatterSmooth
.Values = yVals
.XValues = xVals
.Name = seriesName
.ApplyDataLabels
'loop over series points and apply label from array
For i = 1 To .Points.Count
.Points(i).DataLabel.Text = labelVals(i - 1) 'assuming arrays are zero-based
Next
End With
End If
End Sub
Note you can reduce your code volume by factoring out the repeated "add a series" steps into a separate method.

VBA place two charts on one sheet

How can I place two different sheets on one page.
I create a chart with this code
'Create a chart
Set cht = Worksheets("Dashboard").Shapes.AddChart2
'Set cht = ActiveSheet.Shapes.AddChart2
With cht
.Chart.SetSourceData Source:=rng 'Give chart some data
.Chart.ChartType = xlColumnStacked 'Determine the chart type
.Chart.PlotBy = xlColumns
.ScaleHeight 1.7, msoFalse
.Chart.SetElement (msoElementLegendRight)
.Chart.ChartTitle.Text = Range("E1")
End With
Worksheets("Dashboard").Select
ActiveSheet.ChartObjects(1).Name = "FalseCall"
Range("A1") = ActiveSheet.ChartObjects(1).Name
ActiveSheet.Shapes("FalseCall").Left = Range("A1").Left
ActiveSheet.Shapes("FalseCall").Top = Range("A1").Top
ActiveSheet.Shapes("FalseCall").Width = Range("A1:G1").Width
ActiveSheet.Shapes("FalseCall").Height = Range("A1:A26").Height
It will add a chart on sheet "Dashboard".
Next I want to add a new chart with another name on the same page on H1 with
ActiveSheet.ChartObjects(1).Name = "Ng"
The existing chart will be renamed with the name of the second Chart and moves to H1, instead of the new chart is getting that name and moving the H1
It's not more complicated than repeating the steps with new ranges specified.
Sub InsertTwoCharts()
Dim ws As Worksheet
Set ws = Worksheets("Dashboard")
' CHART 1
' range that chart will cover
Dim ChtRng1 As Range
Set ChtRng1 = ws.Range("A1:G26")
' chart data range
Dim ChtData1 As Range
Set ChtData1 = Worksheets("Whatever").Range("A1:E12") ' or whatever
' insert and modify the chart
Dim cht1 As ChartObject
Set cht1 = ws.Shapes.AddChart2
With cht1
.Name = "FalseCall"
.Chart.SetSourceData Source:=ChtData1, PlotBy:=xlColumns
.Chart.ChartType = xlColumnStacked
.Chart.SetElement msoElementLegendRight
.Chart.ChartTitle.Text = ws.Range("E1").Value ' pick a worksheet and cell
.Left = ChtRng1.Left
.Top = ChtRng1.Top
.Width = ChtRng1.Width
.Height = ChtRng1.Height
End With
' CHART 2
' range that chart will cover
Dim ChtRng2 As Range
Set ChtRng2 = ws.Range("H1:N26")
' chart data range
Dim ChtData2 As Range
Set ChtData2 = Worksheets("Whatever").Range("G1:K12") ' or whatever
' insert and modify the chart
Dim cht2 As ChartObject
Set cht2 = ws.Shapes.AddChart2
With cht2
.Name = "TrueCall"
.Chart.SetSourceData Source:=ChtData1, PlotBy:=xlColumns
.Chart.ChartType = xlColumnStacked
.Chart.SetElement msoElementLegendRight
.Chart.ChartTitle.Text = ws.Range("H1").Value ' pick a worksheet and cell
.Left = ChtRng2.Left
.Top = ChtRng2.Top
.Width = ChtRng2.Width
.Height = ChtRng2.Height
End With
End Sub

Finding and highlighting the last data point in a series/column VBA

I have a macro for creating a graph and part of it identifies and highlights the final data point like below:
This works all well and good when there's data in the final row of a column, but in some cases the final row is empty therefore no point is highlighted like so:
I was wondering if there was a way to make it highlight the last point that has actual data, so even though the last row may be empty, it highlights the last row with data.
Could the following be incorporated into my code? it finds the last data point in column B:
Dim lRow As Long
lRow = Cells(Rows.Count, 2).End(xlUp).Row
Here is my code:
With co.Chart
.FullSeriesCollection(1).ChartType = xlXYScatter
.FullSeriesCollection(1).AxisGroup = 1
.FullSeriesCollection(2).ChartType = xlLine
.FullSeriesCollection(2).AxisGroup = 1
.SetSourceData Source:=my_range
.Axes(xlCategory).TickLabels.NumberFormat = "m/yy"
'highlight final dot of data
.FullSeriesCollection(1).Points(.FullSeriesCollection(1).Points.Count).ApplyDataLabels Type:=xlShowValue
.FullSeriesCollection(1).Points(.FullSeriesCollection(1).Points.Count).MarkerSize = 7
.FullSeriesCollection(1).Points(.FullSeriesCollection(1).Points.Count).MarkerStyle = xlCircle
.FullSeriesCollection(1).Points(.FullSeriesCollection(1).Points.Count).MarkerBackgroundColorIndex = 6
.FullSeriesCollection(1).Points(.FullSeriesCollection(1).Points.Count).MarkerForegroundColorIndex = 1
.HasTitle = True
.ChartTitle.Text = t
ResolveSeriesnames co.Chart
.Location Where:=xlLocationAsObject, Name:="Graphs"
I found this code on https://peltiertech.com/label-last-point-for-excel-2007/ and made a couple adjustments which works
Sub LastPointLabel2()
Dim srs As Series
Dim iPts As Long
Dim cht As ChartObject
Dim vYVals As Variant
Dim vXVals As Variant
Set ws = ActiveSheet
If ActiveChart Is Nothing Then
MsgBox "Select a chart and try again.", vbExclamation
Else
Application.ScreenUpdating = False
For Each cht In ws.ChartObjects
Set srs = cht.Chart.SeriesCollection(1)
With srs
vYVals = .Values
'vXVals = .XValues
' clear existing labels
.HasDataLabels = False
For iPts = .Points.Count To 1 Step -1
If Not IsEmpty(vYVals(iPts)) Then
' add label
srs.Points(iPts).ApplyDataLabels _
ShowSeriesName:=False, _
ShowCategoryName:=False, ShowValue:=True, _
AutoText:=True, LegendKey:=False
Exit For
End If
Next
End With
Next
' legend is now unnecessary
Application.ScreenUpdating = True
End If
End Sub

Chart not showing data when selecting data with vba

I'm using VBA to update my chart. With VBA I select the data that should be shown in the chart. My code does select the data, but somehow my chart doesn't show anything. When I click on my chart end select "Select data" it does show selected data, bu somehow my chart is still empty. Because my chart is empty, the rest of my code doesn't work
My chart is a combo chart with both dataranges as bars, absolute on the primary axis and relative on the secondary axis.
Dim DataSite As Range
Dim DataAbsolute As Range
Dim DataRelative As Range
Set DataSite = Range(Cells(7, 1), Cells(7, 1).End(xlDown))
Set DataAbsolute = Range(Cells(7, 4), Cells(7, 4).End(xlDown))
Set DataRelative = Range(Cells(7, 5), Cells(7, 5).End(xlDown))
GraphsFrames.Select
For Each serie In cht.Chart.SeriesCollection
serie.Select
serie.Delete
Next serie
With cht.Chart
With .SeriesCollection.NewSeries
.XValues = DataSite
.Values = DataAbsolute
.Name = "Absolute"
.AxisGroup = 1
End With
With .SeriesCollection.NewSeries
.Values = DataRelative
.Name = "Relative"
.AxisGroup = 2
End With
.ChartGroups(1).GapWidth = 50
.ChartGroups(2).GapWidth = 300
.Refresh
End With
What can I do to make sure my chart shows the data selected?
Well, I don't know what GraphFrames is, so I ignored it. I made only minor adjustments to your code, below, and it worked just fine. I assume the data is on the active sheet, and so is the chart object you're adding data to.
Sub DoChartData()
Dim DataSite As Range
Dim DataAbsolute As Range
Dim DataRelative As Range
With ActiveSheet
Set DataSite = .Range(.Cells(7, 1), .Cells(7, 1).End(xlDown))
Set DataAbsolute = .Range(.Cells(7, 4), .Cells(7, 4).End(xlDown))
Set DataRelative = .Range(.Cells(7, 5), .Cells(7, 5).End(xlDown))
End With
Dim cht As ChartObject
Set cht = ActiveSheet.ChartObjects(1)
Dim serie As Series
For Each serie In cht.Chart.SeriesCollection
serie.Delete
Next serie
With cht.Chart
With .SeriesCollection.NewSeries
.XValues = DataSite
.Values = DataAbsolute
.Name = "Absolute"
.AxisGroup = 1
End With
With .SeriesCollection.NewSeries
.Values = DataRelative
.Name = "Relative"
.AxisGroup = 2
End With
.ChartGroups(1).GapWidth = 50
.ChartGroups(2).GapWidth = 300
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