Changing Colors for a clustered bar graph based on axis label - vba

Well I am trying to change the colors for my graph based on label conditions.
First of all, this is how the graph looks like.
I was trying to change the values based on three conditions. Warning, Critical and Emergency. Basically having three different colors for each of the conditions. For example all Emergencies be red, all critical be orange and all warning be yellow. "Title" is x-axis in my case and "criticality" happens to be the cluster.
I tried following the thread
excel vba changing bar chart color for a data point based on point value
I also looked at this thread Changing Bar colors using VBA based on category label
I havent had any luck trying to use the code from both the threads.
This code from the second thread actually made sense for me to use in my case.
Dim c As Chart
Dim s As Series
Dim iPoint As Long
Dim nPoint As Long
Set c = ActiveChart
Set s = c.SeriesCollection(1)
nPoint = s.Points.Count
For iPoint = 1 To nPoint
If s.XValues(iPoint) = "avg" Then
s.Points(iPoint).Interior.Color = RGB(255, 0, 0)
End If
Next iPoint
But not sure what variables should I be changing. Any help is welcomed!
Thanks.

the s.XValues(iPoint) will contain Title and Criticality concatenated.
Try to change:
If s.XValues(iPoint) = "avg"
to:
If right(s.XValues(iPoint), 9) = "Emergency"
In this way you will check if the last 9 letters of the label are exactly "Emergency".
You should be able to modify your code to add another condition for Critical or Warning.
Hope this help,
The Macro Guru

Related

Word VBA shape forecolor wdThemeColorAccent2 shows as ThemeColor 1 in the menu

I wrote some macro code in Word (Office 365) to set the color of a shape outline to one of the theme colors. The code for doing that to a shape looks like this:
shape.line.foreColor.ObjectThemeColor = wdThemeColorAccent2
By assigning a 'wdXX' color to the ObjectThemeColor field, the color of the line around the shape will automatically change when the document ColorTheme is changed.
My problem (or the first weirdness) is that when I assign Accent2 with the code above and then do: select the shape, Menu, Format, Shape Outline, and hover over the color box with a red outline (which marks the active line color), the tooltip says "Turquoise, Accent 1" not "Accent 2."
I would have expected the wdThemeColorAccent2 color to be called Accent 2 in the tooltip, but it is not.
The second problem is that there is apparently no way for me to assign the last color shown in the menu using macro code. Because of the offset (Accent 2 in code = Accent 1 in the menu), I would need to use wdThemeColorAccent7 in code to assign the last color shown in the menu (labeled Accent 6 in the tooltip).
I'm wondering if this is a bug in Word (it sure looks like it to me), or if I am doing something wrong. To reproduce the situation, I created a simple empty rectangle, selected it, and ran the line of code above to change the outline color of the shape. Here's a little subroutine that illustrates the problem (select your shape before running the subroutine).
Sub TestAccent()
Dim shp As Shape
Set shp = selection.ShapeRange(1)
shp.line.foreColor.ObjectThemeColor = wdThemeColorAccent4
shp.line.Weight = 0.5
shp.line.Visible = True
End Sub
I believe the colors in the "theme scale" (see image below) don't correspond to the names of the WdThemeColorIndex, but rather to the underlying numerical value. If you look in the VBA Editor's Object Browser (F2), and search wdThemeColorAccent you'll get the full list. Click on a member in the list and at the bottom you'll see the numerical value.
The value 0 is assigned to MainDark1 and isn't recognized by VBA. Values 1, 2 and 3 are assigned to MainLight1, MainDark2 and MainLight2 which are black, white and the first entry in the image (These colors repeat in the last four enumerations for background and text). Values 4 (wdThemeColorAccent4) through 9 (wdThemeColorAccent6) correspond to the remainder of the colors in the image below. (Note: more discussion after image!)
So, no, I don't think it's a bug, just your expectations don't match what the developers were thinking when they assigned the numerical enumeration to the enumeration names. Or maybe the people who designed the color schemes changed their minds after the VBA code was locked down... And I imagine the names you see in the tooltips are another step removed from the VBA. You might find the information in this article helpful.
If you use the values, rather than the names, things could be less confusing. Or, define your own Enum:
Public Enum ColorSchemeAccents
Accent1 = 3
Accent2 = 4
Accent3 = 5
Accent4 = 6
Accent5 = 7
Accent6 = 8
Accent7 = 9
Accent8 = 10
End Enum
Sub TestAccent()
Dim shp As Shape
Set shp = Selection.ShapeRange(1)
shp.Line.ForeColor.ObjectThemeColor = ColorSchemeAccents.Accent8
shp.Fill.ForeColor = RGB(250, 250, 250)
shp.Line.Weight = 2
shp.Line.Visible = True
End Sub
Although the ColorFormat object's .ObjectThemeColor is defined as a wdThemeColorIndex in fact the value depends on context.
If it is a Word object - such as text, then you should use the wdThemeColorIndex constants, but if it is an Office object - such as shape, then you have to use the msoThemeColorIndex constants. These are weirdly NOT the same - mostly the mso constants are one more than the wd constants, but not for the Background1&2 and Text1&2 cases - Text1&2 are the same in both cases, but for Background1&2 mso is two more than wd.
A side effect of this is that it appears impossible in VBA to set the Background2 colour, as its mso value is 16 and so out-of-range BUT if you use the native GUI to set it, it can be set to 16!
Looks really poor design/implementation that needs cleaning up!

Excel Histogram - Distribution Line

I want to make a histogram in excel which is easy using data analytics toolbox. If I wanna make it automatic in vba I can use this post to get the bins automatically and then set the reference ranges.
Problem arises when I want to have the smoothed distribution line. If I change the chart type to scatterplot smooth line, it will connect the columns height to each other which will be like the blue line in this picture:
But what I really want is something like the purple line (i.e. a normal distribution overlaid on top of the histogram). This is not be desired if the data is skewed or generally have a different distribution. Is there anyway to make this overlay automatic in reference to distribution of the data? (Something like what R does) Preferably using macro, but any input would be great.
I added a Trendline to my chart (in red) and then formatted the Trendline as "Polynomial" and it achieved an effect similar to what you have.
Here's some code to achieve this programatically:
Sub AddPolynomialTrendline()
Dim chrt As Chart
Dim chrt_obj As ChartObject
Dim trend As Trendline
For Each chrt_obj In ActiveSheet.ChartObjects
If chrt_obj.Name = "Chart1" Then
With chrt_obj.Chart
'the number after xlPolynomial is the order, which can be from 2 to 6
Set trend = .SeriesCollection(1).Trendlines.Add(xlPolynomial, 6)
End With
End If
Next chrt_obj
End Sub
Hope this helps!

Excel graph legend doesn't match markers

I've formatted the markers of a chart using VBA:
Dim sc As SeriesCollection
Set sc = MySheet.ChartObjects("MyChart").Chart.SeriesCollection
Dim p As Point, s As Series
For Each s In sc
For Each p In s.Points
p.Format.Fill.ForeColor.RGB = s.Format.Line.ForeColor.RGB
p.Format.Fill.BackColor.RGB = s.Format.Line.ForeColor.RGB
p.MarkerSize = 3
Next p
Next s
However, the markers in the chart area don't match up with the markers in the legend (the border colour is the same, but the fill colour in the legend is different). Note the colour inside the boxes on the right (the legend):
I've looked around at a few different properties of the Chart family, but can't find what controls this. The Point properties MarkerBackgroundColor and MarkerForegroundColor seemed likely, but don't fix it. How can I fix this?
Since you were looping the seriescollection, you could simply do all the markers in one go:
For Each s In sc
s.MarkerBackgroundColor = s.Border.Color
s.MarkerSize = 3
Next s
Found with a bit more digging:
Worksheet.ChartObjects(Index).Chart.Item(Index).Format.Fill.ForeColor.RGB
Pretty lengthy!

Attaching a Textbox to a point or line on a chart in Excel/VBA

I was wondering how to attach a textbox to a point or line in an Excel chart for the macro I am working on. I have been using the .AddTextbox method such as
.Shapes.AddTextbox(msoTextOrientationHorizontal, 150, 250, 100, 15) _
.TextFrame.Characters.Text = "Temperature"
But I have to then manually drag the textbox over the line on the chart it is representing as the orientation is of the chart not the line. Is there a way to convert the line/point to a chart orientation which I could use as a variable? or another way? Possibly using the datalabel function, though I want to be able to customize one of the axis locations. Thanks
To solve your question you need to get the left & top position of two objects:
chart itself, which position is set in relation to top-left corner of sheet range area
point in series which position is set in relation to top-left corner of chart
Combination of both result with the following code (fixed parameters-required changes to your situation, could be more dynamic with loop)
Sub Add_Text_to_point()
Dim tmpCHR As ChartObject
Set tmpCHR = Sheet1.ChartObjects(1) 'put index of your chartobject here
'for first serie, for point 2nd here
'(change accordingly to what you need)
With tmpCHR.Chart.SeriesCollection(1).Points(2)
Sheet1.Shapes.AddTextbox(msoTextOrientationHorizontal, _
.Left + tmpCHR.Left, _
.Top + tmpCHR.Top, _
100, 15) _
.TextFrame.Characters.Text = "Temperature"
End With
End Sub
After result presenting the picture below.
Another option would be to use the data labels of Excel. I see two more elegant options:
Make a new data series with just one entry in your chart, give the series the coordinates and the name of the label you want to see. Now activate the marker option for the series (if not done already), right-click on the data point, click "add data labels". Now you'll see the y-Value of the point. By right-clicking again and choosing "Format Data Labels" you can change the text to the series name, also the position, the border, etc. are modifiable. Below an example with two data points. You could delete the second point, the line and the marker but like this you see how it works.
Similarly to the solution from KazJaw you can use the actual data points of your series for attaching custom data labels. This requires some coding, I used this for the chart named "Topview" and wrote percentages next to the data point
Sub Add_Text_to_data_points()
percentages(1) = 0.1
percentages(2) = 0.23
'.... further entries
chartNumber = findChartNumber("Topview")
collNumber = 12 ' index of the "points" series
Set tmpCHR = ActiveSheet.ChartObjects(chartNumber)
For i = 1 To tmpCHR.Chart.SeriesCollection(collNumber).Points.count
With tmpCHR.Chart.SeriesCollection(collNumber).Points(i)
If percentages(i) <> 0 Then
.DataLabel.Text = format(percentages(i), "0%")
End If
End With
Next
End Sub

Color Points (Bars) in Pivot Chart based on Row Labels (Axis Fields)

I'm trying to automate a process that so far I have been doing manually in Excel 2010. I create Pivot Charts often. One of the series on these charts is displayed as bars. I change the fill color of each bar based on one of the row labels of the pivot chart. For instance, if the row label = "GEO", I change the fill color of the bar to green.
I'm sure that it's possible to automate this process through VBA. Here's my code so far. When I run this macro, it stops at the first line of the If statement and gives this error. Compile error: Expected array. Can anyone give me some advice as to how to make this code work?
Sub By_Rig_PC_Coloring()
For i = 1 To ActiveChart.SeriesCollection(2).Points.Count
ActiveChart.SeriesCollection(2).Points(i).Select
If xlRowField("MFR") = "GEO" Then
Selection.Format.Fill.Forcolor.RGB = RGB(0, 176, 80)
End If
Next i
End Sub
As far as I know, you cannot access X axis labels associated with current Point. But this is a PIVOT chart, so you can use your pivot table to get the info you need.
Points are DataField's PivotItems, Series are ColumnFields and X labels are RowFields.
So SeriesCollection(2).Points(10) will be pvtYourPivotTable.ColumnFields(2).DataRange.Cells(10) (assuming that you have only one DataField, otherwise DataRange will be multi-column, and you'll have to adjust for that).
So once you have a cell in pivot table assosacietd with Point, the label will be located at Intersect(pvtYourPivotTable.RowFields("MFR").DataRange, pvtYourPivotTable.ColumnFields(2).DataRange.Cells(10).EntireRow. You can also use Offset or other method.
Here is another method of colouring chart bars based on X labels: Peltier Tech Blog without VBA.
Hope this helps.