VBA looping through all series within all charts - vba

I'm having an issue with the looping through of several charts in my VBA code. I'm 99.7% sure that this is a really easy and quick fix but my brain isn't working today.
I want the code to loop through every chart on the ActiveSheet, and for every data series that the chart contains I want it to add the last value of the series. In my example I have 9 charts, each with 3 series in them (bound to change, some have 2 but I digress).
I have the following code
Sub AddLastValue()
Dim myChartObject As ChartObject
Dim myChart As Chart
Dim mySrs As Series
Dim myPts As Points
With ActiveSheet
For Each myChartObject In .ChartObjects
For Each myChart In .Chart
For Each mySrs In .SeriesCollection
Set myPts = .Points
myPts(myPts.Count).ApplyDataLabels Type:=xlShowValue
Next
Next
Next
End With
End Sub
If I remove the looping code and just do a
Set myPts = ActiveSheet.ChartObjects(1).Chart. _
SeriesCollection(1).Points
myPts(myPts.Count).ApplyDataLabels type:=xlShowValue
Then it works for that specific chart and series, so I'm positive it is the looping that I'm messing up.
Could someone tell me where I mess up the looping code?

Try following code:
Sub AddLastValue()
Dim myChartObject As ChartObject
Dim mySrs As Series
Dim myPts As Points
With ActiveSheet
For Each myChartObject In .ChartObjects
For Each mySrs In myChartObject.Chart.SeriesCollection
Set myPts = mySrs.Points
myPts(myPts.Count).ApplyDataLabels Type:=xlShowValue
Next
Next
End With
End Sub

Not work for empty values.
This code find last not empty value and then adds label.
For Each mySrs In myChartObject.Chart.SeriesCollection
Set myPts = mySrs.Points
Dim i As Integer
i = myPts.Count
Do Until i < 2 Or mySrs.Values(i) <> ""
i = i - 1
Loop
myPts(i).ApplyDataLabels Type:=xlShowValue
Next

Related

I need to reduce scatter chart plot size to allow -90 labels and add Errors Bars in VBA

I created an Excel 2016 VBA scatter chart (separate worksheet w/o legends) and labeled the points with VBA. Source labels are A1:A3 (Events (35-chars) / Date / Y-points) and Data is A2:C17. My labels (orientation -90) overwrite the Y-points and bunch up because the Y-axis plot area takes up the entire worksheet. I have tried different Y-axis values but the plot area expands to fill the worksheet. I have also tried to change the plot size with VBA. I need the labels above the actual chart plot.
The secondary issue is I cannot plot a Date & Time, just a Date and have a problem creating Error Bars with xlMinusValues 100% and SeriesCollection(1).
I have been doing this in separate modules for ease of use, but will be combining or using a Call. I find I cannot build a chart with more than 16 data records, so I will be working on a looping routine if more records are present.
TIMELINE MODULE
Option Explicit
Sub Timeline()
Dim sCount As Long
Dim labelrotation As Long
Dim TimelineChart As Chart
Dim LastCell As Long
Dim rng As Range
Dim rngAddr As String
Dim ChartRange As String
With ActiveSheet
Range("C1").End(xlDown).Activate
Set rng = ActiveCell
rngAddr = rng.Address(0, 0)
End With
Let ChartRange = "B2:" & rngAddr
Set TimelineChart = Charts.Add
TimelineChart.Name = "TimelineChart"
With TimelineChart
.SetSourceData Sheets("TimelineData").Range(ChartRange)
.ChartType = xlXYScatter
.Legend.LegendEntries(1).Delete
TimelineChart.HasAxis(xlSecondary) = False
End With
End Sub
LABEL MODULE
Option Explicit
Sub Labels()
Dim r As Range
Dim Events As Range
Dim EventCounter As Integer
Dim s As Series
Sheets("TimelineData").Select
Set Events = Range("A2", Range("A1").End(xlDown))
Set s = Chart1.SeriesCollection(1)
s.HasDataLabels = True
For Each r In Events
EventCounter = EventCounter + 1
s.Points(EventCounter).DataLabel.Text = r.Value
s.Points(EventCounter).DataLabel.Position = xlLabelPositionAbove
s.Points(EventCounter).DataLabel.Orientation = 45
Next r
End Sub
I am going to withdraw the question. The scatter plot was on a chart sheet versus in the same worksheet as the table from which data is used. Lots of hours spent with a conclusion I should use a bar chart, same worksheet, modified.
Thanks to all that looked and considered a response.

VBA Excel Charts

I am novice in VBA Excel and I have a column chart with multiple columns. I want to be able to set a column's color depending on it's value. At the moment I can select my Chart object and the SeriesCollection, in addition, I can see what values each column has. This is my code:
Sub changeChartColumnColor()
Dim ChtObj As ChartObject
Dim mySrs As Series
Dim myPts As Points
Dim x As Variant
For Each ChtObj In Worksheets("MyWorkSheet").ChartObjects
If ChtObj.Name = "My Chart" Then
For Each mySrs In ChtObj.Chart.SeriesCollection
For Each x In mySrs.Values
MsgBox x
Next x
Next mySrs
End If
Next ChtObj
End Sub
I tried looking it up in internet and on this website but I am not able to find any relevant information. Please note that I know how to change the color for the whole SeriesCollection (mySrs.Interior.Color = RGB(0, 255, 255)).
My problem is: How to change the color of each of the series' columns?
Thank you!

How can I edit this code to make it only apply to one chart?

I found Hide data label containing series name if value is zero on Super User but it removes data labels that have a value of 0 for all charts:
Sub RemoveZeroValueDataLabel()
'runs through every chart on the ActiveSheet
Dim cht As Chart
Dim chtObj As ChartObject
For Each chtObj In ActiveSheet.ChartObjects
Set cht = chtObj.Chart
Dim ser As Series
For Each ser In cht.SeriesCollection
Dim vals As Variant
vals = ser.Values
'include this line if you want to reestablish labels before deleting
ser.ApplyDataLabels xlDataLabelsShowLabel, , , , True, False, False, False, False
'loop through values and delete 0-value labels
Dim i As Integer
For i = LBound(vals) To UBound(vals)
If vals(i) = 0 Then
With ser.Points(i)
If .HasDataLabel Then
.DataLabel.Delete
End If
End With
End If
Next i
Next ser
Next chtObj
End Sub
I tried to edit it myself:
Sub RemoveZeroValueDataLabelonlyonechart()
Dim cht As Chart
Dim chtObj As ChartObject
Set cht = chtObj.Chart
Dim ser As Series
For Each ser In cht.SeriesCollection
Dim vals As Variant
vals = ser.Values
'include this line if you want to reestablish labels before deleting
ser.ApplyDataLabels xlDataLabelsShowLabel, , , , True, False, False, False, False
'loop through values and delete 0-value labels
Dim i As Integer
For i = LBound(vals) To UBound(vals)
If vals(i) = 0 Then
With ser.Points(i)
If .HasDataLabel Then
.DataLabel.Delete
End If
End With
End If
Next i
Next ser
End Sub
But this returns:
Microsoft visual basic | Run-time error '91' | Object variable or With block variable not set
How can I edit the code so it only removes data labels from the chart I have selected, not all charts in the sheet?
Dim chtObj As ChartObject
In the original loop chtObj loops on all the chart objects in the ActiveSheet. Here you want to set it only on a specific Chart object, so you removed the For loop, fine. But your chtObj, which you defined as a reference to a ChartObject, references nothing up till now. You need to assign it to some Chart object. You need to know either the name or the index of the Chart object you want to modify. Then you will add one simple line after the one above:
Set chtObj = ActiveSheet.ChartObjects("someName")
or, if the chart is the first one created within that worksheet:
Set chtObj = ActiveSheet.ChartObjects(1)
After you add one of these two lines, with the appropriate name or number that corresponds to the target Chart, the rest of the code should work fine.

Excel VBA to fill pie chart colors from cells with conditional formatting

I don't have experience with VBA and I'm trying to format all of the pie charts on one active sheet based on the colors of their data cells in Excel 2010. I found this code from: http://datapigtechnologies.com/blog/index.php/color-pie-chart-slices-to-match-their-source-cells/
Sub ColorPies()
Dim cht As ChartObject
Dim i As Integer
Dim vntValues As Variant
Dim s As String
Dim myseries As Series
For Each cht In ActiveSheet.ChartObjects
For Each myseries In cht.Chart.SeriesCollection
If myseries.ChartType <> xlPie Then GoTo SkipNotPie
s = Split(myseries.Formula, ",")(2)
vntValues = myseries.Values
For i = 1 To UBound(vntValues)
myseries.Points(i).Interior.Color = Range(s).Cells(i).Interior.Color
Next i
SkipNotPie:
Next myseries
Next cht
End Sub
This code works well, however it is unable to pick up the colors from conditional formatting.
I came across this solution for VBA to read conditional formatting colors:
Selection.FormatConditions(1).BarColor.Color
However I've been unable to implement it in the above block of VBA. I tried replacing Interior.Color with different parts of it and none seem to work. Does anyone know a simple way to do this?
Thank you in advance!
Since you have 2010, you can use the DisplayFormat property:
For i = 1 To UBound(vntValues)
myseries.Points(i).Interior.Color = Range(s).Cells(i).DisplayFormat.Interior.Color
Next i

Unable to get named range in Excel

I have a worksheet where there is a chart on the first sheet, showing some data from a named range.
The named range looks like this:
=OFFSET(chart_data!$B$2,0,0,COUNTA(chart_data!$B:$B)-1)
where chart_data is a different sheet.
I also have a VBA script that is supposed to set colors of the chart same as background colors of corresponding cells. The script follows:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim cht As ChartObject
Dim i As Integer
Dim vntValues As Variant
Dim s As String
Dim myseries As Series
Dim nRange As Range
For Each cht In ActiveSheet.ChartObjects
For Each myseries In cht.Chart.SeriesCollection
If myseries.ChartType <> xlPie Then GoTo SkipNotPie
s = Split(myseries.Formula, ",")(2)
vntValues = myseries.Values
For i = 1 To UBound(vntValues)
If Range(s).Cells(i).Interior.Color <> 16777215 Then
myseries.Points(i).Interior.Color = Range(s).Cells(i).Interior.Color
End If
Next i
SkipNotPie:
Next myseries
Next cht
End Sub
My problem is that when I try to evaluate Range(s), where s = "report!values_list", I get
Run-time error '1004':
Method 'Range' of object '_Worksheet' failed
How can I solve this?
Try to do it on different Office. It works for me, some of Offices blocked the dynamic range. Try to make it on different PC with different type of MS Office and make them some simply task with dynamic range. If it will work, you just copy your code there and it will work even in your sheet.
You can get the range corresponding to a name like this:
ThisWorkbook.Names ("somename").RefersToRange