I would like to change the colour of waterfall chart based on chart value. For example, if the value negative, put red colour. If value is positive, put green colour.
I got below code from excel vba changing bar chart color for a data point based on point value
This code works with bar chart. However, I cannot use it with waterfall as it shown error "Object doesn't support this action"
Does anyone know how to config this to use with waterfall? Any suggestion would be highly appreciated!
Thanks,
Sub color_chart()
Dim chartIterator As Integer, pointIterator As Integer, _
seriesArray() As Variant
For chartIterator = 1 To ActiveSheet.ChartObjects.Count
seriesArray = ActiveWorkbook.Sheets("Sheet1").ChartObjects(chartIterator). _
chart.SeriesCollection(1).Values
For pointIterator = 1 To UBound(seriesArray)
If seriesArray(pointIterator) >= 0 Then
ActiveWorkbook.Sheets("Sheet1").ChartObjects(chartIterator). _
chart.SeriesCollection(1).Points(pointIterator).Interior.Color = _
RGB(146, 208, 80)
Else
ActiveWorkbook.Sheets("Sheet1").ChartObjects(chartIterator). _
chart.SeriesCollection(1).Points(pointIterator).Interior.Color = _
RGB(255, 0, 0)
End If
Next pointIterator
Next chartIterator
End Sub
Here is the code I used. It works with Waterfall
Sub cht_loop()
Dim i As Integer
Dim cht As Chart
Set cht = Sheets("sheet1").ChartObjects("Chart 10").Chart
For i = 1 To 5
If Sheets("Sheet1").Range("B" & i + 1).Value < 0 Then
With cht.SeriesCollection(1).Points(i).Format.Fill
.Visible = msoTrue
.ForeColor.RGB = RGB(192, 0, 0)
End With
Else
With cht.SeriesCollection(1).Points(i).Format.Fill
.Visible = msoTrue
.ForeColor.RGB = RGB(0, 176, 80)
End With
End If
Next i
End Sub
So, a quick example:
Just to show what I meant in my comment.
Related
Below code is giving me an error stating specified value is out of range.
Sub Green()
ThisWorkbook.Sheets(1).Activate
ActiveSheet.Shapes("Elbow Connector 62").Fill.ForeColor.RGB = vbGreen
End Sub
Here's two options - one with a variable and one without. You might need to change the 2 to a 62.
Sub Macro1()
ActiveSheet.shapes.Range(Array("Elbow Connector 2")).Select
With Selection.ShapeRange.Line
.Visible = msoTrue
.ForeColor.RGB = RGB(255, 0, 0)
.Transparency = 0
End With
End Sub
Sub shapes()
Dim s As ShapeRange
Set s = ActiveSheet.shapes.Range(Array("elbow connector 2"))
With s
.Line.ForeColor.RGB = RGB(255, 0, 0)
End With
End Sub
I have a VBA function in Excel (office 365 ProPlus) generating waterfall charts, see examples below. After generating them I want to resize the plot/legend/axis areas just to adjust the looks.
But Excel doesn't let me; the edges of the areas seem to be fixed (see blue dots/circles), I can't grab them.
I can change the axis ranges but not the area sizes. If I change the chart type e.g. to stacked bars it works.
The sheet is not protected.
Is this a known problem?
Is there a workaround?
Do I have something in my code (below) that causes this behaviour, or is something missing?
Dim rngChartValues As Range
Dim rngChartXValues As Range
Dim myChart As Chart
Dim myShape As Shape
Dim dStartValue As Double
Dim dEndValue As Double
Dim dDeltaSurplus As Double
Dim dDeltaPC As Double
Dim chartTitle As String
Dim rngToplace As Range
rngChartValues.Select
Set myShape = ActiveSheet.Shapes.AddChart2(395, xlWaterfall)
Set myChart = myShape.Chart 'ActiveChart
Application.CutCopyMode = False
rngToplace.Select
With myShape
.Left = rngToplace.Left
.Top = rngToplace.Top
.Placement = xlFreeFloating
.Height = 450
End With
With myChart
.Legend.Delete
.chartTitle.Text = chartTitle
.SeriesCollection.NewSeries
.Parent.name = chartTitle
With .FullSeriesCollection(1)
.name = chartTitle
.Values = rngChartValues
.XValues = rngChartXValues
dStartValue = shtCharts.Cells(rowCapSurplusEarlr, colCA).Value
dEndValue = shtCharts.Cells(rowCapSurplusLater, colCA).Value
dDeltaSurplus = shtCharts.Cells(rowDeltaSurplus, colCA).Value
dDeltaPC = Abs(dDeltaSurplus / dStartValue)
' handle the last bar as total bar
With .Points(.Points.Count)
.IsTotal = True
If dDeltaPC < 0.1 Then ' change is smaller than 10%
If dDeltaSurplus < 0 Then ' ...but still negative
.Format.Fill.ForeColor.RGB = RGB(255, 204, 0) ' => light orange
Else ' ... and positive
If dEndValue < 0 Then ' ... but the surplus is till negative
.Format.Fill.ForeColor.RGB = RGB(255, 204, 0) ' => light orange
Else ' ... and the surplus is positive
.Format.Fill.ForeColor.RGB = RGB(153, 204, 0) ' => light green
End If
End If
ElseIf dDeltaSurplus < 0 Then ' change is >10% and negative
.Format.Fill.ForeColor.RGB = RGB(255, 153, 0) ' => orange
Else ' cange is >10$ and positive
If dEndValue < 0 Then ' ... but the surplus is till negative
.Format.Fill.ForeColor.RGB = RGB(255, 255, 0) ' => yellow
Else ' ... and the surplus is positive
.Format.Fill.ForeColor.RGB = RGB(0, 160, 0) ' => green
End If
End If
End With
End With
End With
With myChart.Parent
intTmp = .Width
intTmp = .Height
End With
I have an Excel form whose borders are in black color. I would like to change it to other color. I tried the following code:
ActiveSheet.UsedRange.Borders.Color = RGB(255, 0, 0)
It changed the borders of all cells, including those cells which did not have borders, into red. This is not what I want. I want those borders in black to turn red and the invisible borders to stay invisible. Is there a way to do it?
Just another way of doing things making use of FindFormat and ReplaceFormat properties.
Sub BordersReplace()
With ThisWorkbook.Sheets(1)
For X = xlEdgeLeft To xlEdgeRight
With Application.FindFormat.Borders(X)
.Color = 0
End With
With Application.ReplaceFormat.Borders(X)
.Color = 255
End With
.Cells.Replace What:="", Replacement:="", searchformat:=True, ReplaceFormat:=True
Application.FindFormat.Clear
Application.ReplaceFormat.Clear
Next X
End With
End Sub
Small loop involved to go through the appropriate XLBordersIndex enumeration.
Note, not clearing FindFormat and ReplaceFormat will make Excel keep working with the first used format, hence why the .Clear is nesseccary.
I myself am a little bit puzzled on why it would't work on the cells with all edges on its borders applied. For that to work use Application.FindFormat.Borders()
Thanks for Mikku's input, I got the following code to work.
Sub change_border_color()
'change the color of existing borders
Dim cell As Range
Application.ScreenUpdating = False
For Each cell In ActiveSheet.UsedRange
If cell.Borders(xlEdgeLeft).LineStyle = 1 Then
cell.Borders(xlEdgeLeft).Color = RGB(0, 0, 255)
End If
If cell.Borders(xlEdgeTop).LineStyle = 1 Then
cell.Borders(xlEdgeTop).Color = RGB(0, 0, 255)
End If
If cell.Borders(xlEdgeBottom).LineStyle = 1 Then
cell.Borders(xlEdgeBottom).Color = RGB(0, 0, 255)
End If
If cell.Borders(xlEdgeRight).LineStyle = 1 Then
cell.Borders(xlEdgeRight).Color = RGB(0, 0, 255)
End If
Next
Application.ScreenUpdating = True
End Sub
Sub chgBorderColor_On_AllSheets()
'change the color of existing borders on all sheets
Dim Current As Worksheet
Dim cell As Range
Dim Red As Integer, Green As Integer, Blue As Integer
Dim NewColor As Long
Dim i As Integer
Red = Application.InputBox("Input R component of RGB", "Line color definition", Type:=1)
Green = Application.InputBox("Input G component of RGB", "Line color definition", Type:=1)
Blue = Application.InputBox("Input B component of RGB", "Line color definition", Type:=1)
NewColor = RGB(Red, Green, Blue)
Application.ScreenUpdating = False
For Each Current In Worksheets
For Each cell In Current.UsedRange
For i = xlEdgeLeft To xlEdgeRight '7 to 10
If cell.Borders(i).LineStyle = xlContinuous Or _
cell.Borders(i).LineStyle = xlDouble Or _
cell.Borders(i).LineStyle = xlDot Or _
cell.Borders(i).LineStyle = xlDash Or _
cell.Borders(i).LineStyle = xlDashDot Or _
cell.Borders(i).LineStyle = xlDashDotDot Or _
cell.Borders(i).LineStyle = xlSlantDashDot Then
cell.Borders(i).Color = NewColor
End If
Next
Next
Next
Application.ScreenUpdating = True
End Sub
Use this:
A Loop will work fine. Currently you are setting the complete Range and changing it's border, you only need to do that with cells having any Value.
This loop will colour the Border Red if cell currently have any border.
For Each cel In ActiveSheet.UsedRange
If Not cel.Borders(xlEdgeLeft).LineStyle = 0 Then
cel.Borders.Color = RGB(255, 0, 0)
End If
Next
This loop will color the Borders where the cel have some Value.
For Each cel In ActiveSheet.UsedRange
If Not cel.Value = "" Then
cel.Borders.Color = RGB(255, 0, 0)
End If
Next
How do I change the color of an arrow based on its label (converted to integer); say if the value of the arrow is <50; then change the color of the arrow to green?
I encountered run-time error 438:
Object doesn't support this property or method (Line 3).
Sub ArrowColour()
Dim nsize As Integer
nsize = CInt(ActiveSheet.Shapes.Range(Array("Left Arrow 1")).Value)
With ActiveSheet.Shapes.Range(Array("Left Arrow 1")).Fill
If nsize < 50 Then
.ForeColor.RGB = RGB(0, 176, 80)
Else
.ForeColor.RGB = RGB(255, 0, 0)
End If
End With
End Sub
Shapes don't have a Value property.
Try this:
Sub ArrowColour()
With ActiveSheet.Shapes("Left Arrow 1")
.ForeColor.RGB = IIf(CInt(.TextFrame.Characters.Text)<50, _
RGB(0, 176, 80), RGB(255, 0, 0))
End With
End Sub
I have found the answer:
Sub Test()
Dim shp As Shape
Dim sTemp As String
Set shp = ActiveSheet.Shapes("RightArrow")
sTemp = shp.TextFrame.Characters.Text
If CInt(sTemp) > 400 Then
shp.Fill.ForeColor.RGB = RGB(255, 0, 0)
End If
End Sub
I am trying to code using vba so that a series on a chart is formatted based on certain criteria. My coding is as follows
Sub CreateChart()
Dim NPOINTS As Integer
Dim NVAL(1000) As Range, XVAL(1000) As Range, YVAL(1000) As Range
Dim Score(1000) As Range
Sheets("Scenario").Select
Range("B4").Select
NPOINTS = Worksheets("Scenario").Range(Selection, Selection.End(xlDown)).Rows.Count
Set Scenario = Worksheets("Scenario")
ActiveSheet.Shapes.AddChart2(240, xlXYScatter).Select
NVAL0 = "B3"
XVAL0 = "C3"
YVAL0 = "D3"
SCORE0 = "E3"
For i = 1 To NPOINTS
Set Score(i) = Cells(Range(SCORE0).Offset(i, 0).Row, Range(SCORE0).Column)
Set NVAL(i) = Cells(Range(NVAL0).Offset(i, 0).Row, Range(NVAL0).Column)
Set XVAL(i) = Cells(Range(XVAL0).Offset(i, 0).Row, Range(XVAL0).Column)
Set YVAL(i) = Cells(Range(YVAL0).Offset(i, 0).Row, Range(YVAL0).Column)
Scorei = Score(i).Value
ActiveChart.SeriesCollection.NewSeries
ActiveChart.FullSeriesCollection(i).Name = NVAL(i)
ActiveChart.FullSeriesCollection(i).XValues = XVAL(i)
ActiveChart.FullSeriesCollection(i).Values = YVAL(i)
If Scorei <= 10 >= 0 Then
ActiveChart.SeriesCollection(i).Points.Interior.Colour = _
RGB(0, 255, 0) 'Green
ElseIf Scorei <= 30 >= 11 Then
ActiveChart.SeriesCollection(i).Points.Interior.Colour = _
RGB(0, 255, 0) 'Green
ElseIf Scorei <= 60 >= 31 Then
ActiveChart.SeriesCollection(i).Points.Interior.Colour = _
RGB(0, 255, 0) 'Green
ElseIf Scorei <= 100 >= 61 Then
ActiveChart.SeriesCollection(i).Points.Interior.Colour = _
RGB(0, 255, 0) 'Green
Else
MsgBox "ERROR :- Score out of range"
End If
Next
With ActiveChart
'chart name
.HasTitle = False
'X axis name
.Axes(xlCategory, xlPrimary).HasTitle = True
.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "INFLUENCE"
'y-axis name
.Axes(xlValue, xlPrimary).HasTitle = True
.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "IMPORTANCE"
.SetElement (msoElementLegendRight)
.Location Where:=xlLocationAsNewSheet, Name:="Priority Chart"
End With
End Sub
Unfortunately when I run it, it fails with "Object doesn't support this property or method and then when I press Debug it highlights the following line
ActiveChart.SeriesCollection(i).Points.Interior.Colour = _
RGB(0, 255, 0) 'Green
Where am I going wrong?
I appreciate any help.
just
ActiveChart.SeriesCollection(i).format.Fill.ForeColor.RGB =RGB(0, 255, 0)
The .Points() is a collection.
You will need to cycle through all its elements and change the color one by one.
The left most point is .Points(1), the right most point is .Points.count
as per: Change the Point Color in chart excel VBA
Also there is no such thing as interior colour for points.
There are 4 relevant options as per: https://msdn.microsoft.com/en-us/vba/excel-vba/articles/point-object-excel
MarkerBackgroundColor
MarkerBackgroundColorIndex
MarkerForegroundColor
MarkerForegroundColorIndex
As per comment from Jon Peltier it is not recommended to make use of the colorindex as this is a legacy from excel <2003