I'm creating an Excel document at runtime that has a bunch of values I'd like to have conditionally formatted. In going through various attempts from scratch as well as using/modifying code outputted from the Excel's macro recorder, I'm having a consistent issue related to formatting overwrites.
I've posted a snippet of the code below and can say that I've tested to ensure my selection ranges are valid and appropriate for what I want conditionally formatted. There is some overlap but what's bizarre is that the first conditional format takes on just one property of the second conditional format. Meaning D5:End of the worksheet ends up having a green color font as opposed to the red it should be. Commenting each section of the code does allow them to work independently but I'm guessing this is an issue with specifying conditional formats further somehow? I've tried a few different case scenarios and below is the code with modifications:
EDIT (Updated Code):
'First conditional format, check sheet for values > 50 and make text red.
With xl.range("D5:" & theLastColumn & lastRow)
.FormatConditions.add Type:=xlCellValue, Operator:=xlGreater, Formula1:="=50"
With .FormatConditions(1).Font
.Color = -16383844
.TintAndShade = 0
End With
.FormatConditions(1).StopIfTrue = False
End With
'Second conditional format, check specific row (row 5 in the example)
'for values > 40, and fill interior with green in addition to dark green text.
With xl.range("D" & Infectivity & ":" & theLastColumn & Infectivity)
.FormatConditions.add Type:=xlCellValue, Operator:=xlGreater, Formula1:="=40"
With .FormatConditions(2).Font
.Color = -16752384
.TintAndShade = 0
End With
With .FormatConditions(2).Interior
.PatternColorIndex = xlAutomatic
.Color = 13561798
.TintAndShade = 0
End With
End With
So what's the best way to have multiple conditional formats (that may overlap ranges) and still have them all function as intended? I've tried debugging this so much I'm certain there's something easy I'm overlooking. I've also tried a few different methods to specify separate formatconditions(1) and formatconditions(2) but still receive strange issues.
EDIT:
VBA Code where I continue to have the same issue.
Sub conditionalFormat()
With Range("D5:BA9")
.FormatConditions.Add Type:=xlCellValue, Operator:=xlGreater, Formula1:="=50"
.FormatConditions(.FormatConditions.Count).SetFirstPriority
With .FormatConditions(1).Font
.Color = -16383844
.TintAndShade = 0
End With
.FormatConditions(1).StopIfTrue = False
End With
With Range("D9:BA9")
.FormatConditions.Add Type:=xlCellValue, Operator:=xlGreater, Formula1:="=40"
With .FormatConditions(2).Font
.Color = -16752384
.TintAndShade = 0
End With
With .FormatConditions(2).Interior
.PatternColorIndex = xlAutomatic
.Color = 13561798
.TintAndShade = 0
End With
.FormatConditions(2).StopIfTrue = False
End With
End Sub
Even with the SetFirstPriority on the appropriate (red text) conditional format, it just gets overwritten somehow. Am I missing something here?
Sorry. I don't have Excel 2007. Tested this in Excel 2010.
When it comes to conditional formatting, you have to be really careful of what the macro recorder spits out. This is one particular case where it makes a mess of the code.
Also you are setting then 2nd rule as .SetFirstPriority which is incorrect besides letting the 2nd rule run in spite of rule 1 get getting satisfied :)
Here is a very basic example. Let's say my range looks like this D5:G7
Now this is the VBA code that I tested
Sub Sample()
Dim ws As Worksheet
Dim rng As Range
Set ws = ThisWorkbook.Sheets("Sheet1")
Set rng = ws.Range("D5:G7")
With rng
.FormatConditions.Add Type:=xlCellValue, _
Operator:=xlGreater, Formula1:="=50"
.FormatConditions(.FormatConditions.Count).SetFirstPriority
With .FormatConditions(1).Font
.Color = -16776961
.TintAndShade = 0
End With
.FormatConditions(1).StopIfTrue = True
.FormatConditions.Add Type:=xlCellValue, _
Operator:=xlGreater, Formula1:="=40"
With .FormatConditions(2).Font
.Color = -11489280
.TintAndShade = 0
End With
With .FormatConditions(2).Interior
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorAccent3
.TintAndShade = 0.599963377788629
End With
End With
End Sub
And this is the result that I got.
I am sure it will be very easy for you to port the above code to vb6.
FOLOWUP (From Comments)
Using latebinding... would earlybinding be better suited for doing this type of conditional formatting? – Bernard 2 mins ago
If you are using LateBinding then declare this code at the top of your code
Const xlCellValue as Long = 1
Const xlGreater as Long = 5
Const xlAutomatic as Long = -4105
Const xlThemeColorAccent3 as Long = 7
After much thought and reworking the code we came to the conclusion that what I was doing (multiple conditions overlapping) was the cause of the mixed results. At the simplest level, I was able to add .FormatConditions.Delete to my additional conditional formats to ensure only one format was applied.
The corrected final code is shown below:
Dim Infectivity As Long
Infectivity = Application.WorksheetFunction.match("Infectivity", range("A1:" & "A" & lastRow), 0)
With xl.range("D5:" & theLastColumn & lastRow)
.FormatConditions.add Type:=xlCellValue, Operator:=xlGreater, _
Formula1:="=50"
.FormatConditions(.FormatConditions.count).SetFirstPriority
With .FormatConditions(1).Font
.Color = -16383844
.TintAndShade = 0
End With
.FormatConditions(1).StopIfTrue = False
End With
If Infectivity > 0 Then
With xl.range("D" & Infectivity & ":" & theLastColumn & Infectivity)
.FormatConditions.Delete
.FormatConditions.add Type:=xlCellValue, Operator:=xlGreater, _
Formula1:="=40"
With .FormatConditions(1).Font
.Color = -16752384
.TintAndShade = 0
End With
With .FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.Color = 13561798
.TintAndShade = 0
End With
.FormatConditions(1).StopIfTrue = False
End With
End If
My downfall was related to the macro recorder giving me a false of the ideal method of formatting these cells. It's always best to simplify before moving forward.
Major thanks to Siddharth Rout for all the help.
Related
I have the following code that I use to apply conditional formatting to a worksheet. The problem is, if I vary the value in Formula1:=Cells(11,7) [for example], the formatted data does not reflect the updated change. When I open the Excel's Conditional Formatting Rules Manager, the rules do not show a reference to the actual cell, but the value of the cell at the time that I ran the macro. Any thoughts?
Dim i As Integer
For i = 7 To 13
Range(Cells(21, i), Cells(118, i)).Select
Selection.FormatConditions.Add Type:=xlCellValue, Operator:=xlGreater, _
Formula1:=Cells(11, i)
With Selection.FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.Color = 255
.TintAndShade = 0
End With
Selection.FormatConditions.Add Type:=xlCellValue, Operator:=xlLess, _
Formula1:=Cells(13, i)
Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
With Selection.FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.ColorIndex = 6
.TintAndShade = 0
End With
Next
What you want is something more like Formula1:="=$G$11" so:
Selection.FormatConditions.Add Type:=xlCellValue, Operator:=xlLess, _
Formula1:="=" & Cells(11, i).Address()
Use code like this to set the Formula1 property.
Formula1:="=Cells(11, " & i & ")"
I am trying to have my macro sort my data based on the result of an IFERROR function in column A and the cell color in column B.
In column A, the IFERROR is performing a VLOOKUP on another workbook to check for matching values. Column A is highlighted Red by default, along with a bunch of other previously highlighted cells in the master workbook.
So basically, this is what I'm trying to make happen:
If column A passes IFERROR function AND is highlighted Red AND column B has No Fill, then select the entire row. I would like this to check the entire workbook.
Please forgive me if I am not making much sense, I'm having a difficult time putting this into words.
I figured it out.
`
Range("A2:AH2").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.FormatConditions.Add Type:=xlExpression, Formula1:="=ISERROR(A2)"
Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
With Selection.FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
End With
Selection.FormatConditions(1).StopIfTrue = False
Selection.FormatConditions.Add Type:=xlExpression, Formula1:= _
"=ISNUMBER($A2)"
Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
With Selection.FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.Color = 5287936
.TintAndShade = 0
End With
Selection.FormatConditions(1).StopIfTrue = False`
Since each row has to be evaluated individually, you are going to have each two cell combination.
For i = 2 to lastrow
If Range("A" & i).Interior.ColorIndex = RGB(255, 0, 0) And Range("B" & i).Interior.ColorIndex = xlNone And Not Application.WorksheetFunction.IsError(Range("A" & i)) Then
'do your code if all are true
end if
Next i
Here's what I've got at the moment:
'Highlight If N=19 & R=OR
Range("G4:R1000").Select
Selection.FormatConditions.Add Type:=xlExpression, Formula1:="=$N4=19"
Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
With Selection.FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.Color = 255
.TintAndShade = 0
End With
Selection.FormatConditions(1).StopIfTrue = True
I am trying to highlight a few cells based on multiple criteria. If N=19 and if R=OR. I can only get the N=19 portion to work.
I believe the formula adjustment I made in comments above should solve your problem but here is how I clean up recorded Conditional Formatting code.
With Worksheets("Sheet1")
With .Range("G4:R1000")
With .FormatConditions.Add(Type:=xlExpression, Formula1:="=AND($N4=19, $R4=""OR"")")
With .Interior
.PatternColorIndex = xlAutomatic
.Color = 255
.TintAndShade = 0
End With
.SetFirstPriority
End With
.FormatConditions(1).StopIfTrue = True
End With
End With
Removing the verbose qualifying code (e.g. Selection.FormatConditions(Selection.FormatConditions.Count)...) makes it much more readable.
I am extremely new to VBA world and need some assistance with the VBA side of conditional formatting.
1) I need conditional formatting to be applied to column (M)
green under 7
yellow from 7-20
red greater than 20
With the overriding condition that if column (N) if it states NOPO, I do not want conditional formatting to be applied.
I have worked out a formula to use that indicates what colour is required but unable to turn that into VBA conditional formatting (this formula shows what colour and if the conditional formatting should be applied.
=IF(N2="osno",IF(M2<=7,"green",IF(M2<7,IF(M2>20,"red","less than 20"),IF(M2>20,IF(M2>20,"red","less than 20"),"yellow"))),"no format")
This is my current VBA script, as you can no doubt see it's very messy and was from a recorded script.
Sub Conditional()
'
' Notification_05 Macro
' Conditional Formatting
'
'
Sheets("Final").Select
Columns("M:M").Select
Selection.FormatConditions.Add Type:=xlCellValue, Operator:=xlLess, _
Formula1:="=8"
Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
With Selection.FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.Color = 5296274
.TintAndShade = 0
End With
Selection.FormatConditions(1).StopIfTrue = False
Selection.FormatConditions.Add Type:=xlCellValue, Operator:=xlBetween, _
Formula1:="=8", Formula2:="=20"
Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
With Selection.FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.Color = 49407
.TintAndShade = 0
End With
Selection.FormatConditions(1).StopIfTrue = False
Selection.FormatConditions.Add Type:=xlCellValue, Operator:=xlGreater, _
Formula1:="=20"
Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
With Selection.FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.Color = 470000
.TintAndShade = 0
ActiveWindow.SmallScroll Down:=-27
Range("M2").Select
With Range("M:M")
.FormatConditions.Add Type:=xlExpression, Formula1:= _
"=LEN(TRIM(M1))=0"
With .FormatConditions(.FormatConditions.Count)
.SetFirstPriority
End With
End With
End With
End Sub
Thanks,
Blake
A CF formula needs to return either true or false: you can't use a single formula to assign one of multiple colors, only to decide if a color should be applied or not. You will need three rules, each with a slightly different formula.
Sub Tester()
Dim rng As Range
Set rng = Selection
rng.FormatConditions.Delete 'clear any existing rules
AddRule rng, "=AND(M2=""osno"", N2<7)", vbGreen
AddRule rng, "=AND(M2=""osno"", N2>=7,N2<=20)", vbYellow
AddRule rng, "=AND(M2=""osno"", N2>20)", vbRed
End Sub
'utility sub: add a CF rule given the formula and a fill color
Sub AddRule(rng, sFormula, lColor)
With Selection.FormatConditions
With .Add(Type:=xlExpression, Formula1:=sFormula)
.Interior.Color = lColor
.StopIfTrue = True
End With
End With
End Sub
So I've set up a conditional formatting VBA macro to highlight two cells: The one with the given string, and the one next to it.
The data set is:
A1 B1
------------------------
PluginID NUM
Host ADDRESS
Severity High
Port PORT
Description DESCRIPTION
Solution SOLUTION
References CVE
The VBA code is:
Sub High2()
'
' High2 Macro
'
'
Columns("A:B").Select
Selection.FormatConditions.Add Type:=xlExpression, Formula1:= _
"=AND($B1=""High"",A1)"
Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
With Selection.FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.Color = 255
.TintAndShade = 0
End With
Selection.FormatConditions(1).StopIfTrue = False
End Sub
This highlights the cell with 'High' in it, and the cell to the left, 'Severity'.
If I change the "=AND($B1=""High"",A1)" line to "=AND($B2=""High"",A1)" then excel will highlight the 2 cells above it in red instead, i.e. Host.
Can anyone help me with highlighting the 4 cells above and 8 cells below the string search-term as well (i.e. the Port, Description, Solution and References cells)?
What you are actual doing if you "change the "=AND($B1=""High"",A1)" line to "=AND($B2=""High"",A1)"" is simply add a new rule. So this will be really the best approach. Adding as much rules as necessary.
Sub High2()
With Columns("A:B").Cells
.Range("A1").Activate
.FormatConditions.Delete
For i = 1 To 3 ' 3 above
.FormatConditions.Add Type:=xlExpression, Formula1:="=($B" & i & "=""High"")"
.FormatConditions(.FormatConditions.Count).SetFirstPriority
With .FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.Color = 255
.TintAndShade = 0
End With
.FormatConditions(1).StopIfTrue = False
Next
For i = 0 To 3 ' 4 below
.FormatConditions.Add Type:=xlExpression, Formula1:="=($B" & .Rows.Count - i & "=""High"")"
.FormatConditions(.FormatConditions.Count).SetFirstPriority
With .FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.Color = 255
.TintAndShade = 0
End With
.FormatConditions(1).StopIfTrue = False
Next
End With
End Sub
This could also be reached with only one rule:
=OR($B1048573:$B1048576="High", $B1:$B3="High")
But this will lead to bad performance since it is working as an array formula.