Related
In column C I have a starting balance, in column D I have the remaining balance. I can apply a 3-color scale to that cell and make the color gradually change from green to yellow to red. The problem I am facing is I need to apply these same rules to 200+ other cells, each with their own unique starting balance in column C. This prevents me from just copying the rule because Excel tells me I can not use relative cell references with these rules. To try and fix this so I do not need to click through the conditional formatting wizard 200+ times, I'm trying to make a macro that applies these rules to each cell in column D. so far this is what I have.
What I am running into is that the 3-Color Scale rule is being applied to each cell, but the formula used to determine the color thresholds is not being inserted. it leaves me with this
My background in VBA is about of week of google, so forgive me if its over complicated. I used the macro recorder then changed all of the .select and .selection stuff to reference the objects directly to learn how the conditional formatting rules are initially applied.
Dim wsT As Worksheet
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
Set wsT = ThisWorkbook.Worksheets("Tracking")
For X = 5 To LastRow
wsT.Range("D" & X).FormatConditions.AddColorScale ColorScaleType:=3
wsT.Range("D" & X).FormatConditions(wsT.Range("D" & X).FormatConditions.Count).SetFirstPriority
wsT.Range("D" & X).FormatConditions(1).ColorScaleCriteria(1).Type = _
xlConditionValueFormula
wsT.Range("D" & X).FormatConditions(1).ColorScaleCriteria(1).Value = _
wsT.Range("C" & X) * 0.1
With wsT.Range("D" & X).FormatConditions(1).ColorScaleCriteria(1).FormatColor
.Color = 7039480
.TintAndShade = 0
End With
wsT.Range("D" & X).FormatConditions(1).ColorScaleCriteria(2).Type = _
xlConditionValueFormula
wsT.Range("D" & X).FormatConditions(1).ColorScaleCriteria(2).Value = _
wsT.Range("C" & X) * 0.65
With wsT.Range("D" & X).FormatConditions(1).ColorScaleCriteria(2).FormatColor
.Color = 8711167
.TintAndShade = 0
End With
wsT.Range("D" & X).FormatConditions(1).ColorScaleCriteria(3).Type = _
xlConditionValueFormula
wsT.Range("D" & X).FormatConditions(1).ColorScaleCriteria(3).Value = _
wsT.Range("C" & X) * 0.85
With wsT.Range("D" & X).FormatConditions(1).ColorScaleCriteria(3).FormatColor
.Color = 8109667
.TintAndShade = 0
End With
Next X
End Sub
My previous answer was incorrect. Your problem is that formulas need to be strings that start with =, like "=0.1*$C$1".
I wrote the following:
Sub Test()
Dim ws As Worksheet, rg As Range, cs As ColorScale
Set ws = ActiveSheet
For Each rg In ws.Range("D1", ws.Cells(ws.Rows.Count, "D").End(xlUp).Address)
Set cs = rg.FormatConditions.AddColorScale(ColorScaleType:=3)
cs.ColorScaleCriteria(1).Type = xlConditionValueFormula
cs.ColorScaleCriteria(1).Value = "=0.1*$C$" & CStr(rg.Row)
cs.ColorScaleCriteria(1).FormatColor.Color = 7039480
cs.ColorScaleCriteria(1).FormatColor.TintAndShade = 0
cs.ColorScaleCriteria(2).Type = xlConditionValueFormula
cs.ColorScaleCriteria(2).Value = "=0.65*$C$" & CStr(rg.Row)
cs.ColorScaleCriteria(2).FormatColor.Color = 8711167
cs.ColorScaleCriteria(2).FormatColor.TintAndShade = 0
cs.ColorScaleCriteria(3).Type = xlConditionValueFormula
cs.ColorScaleCriteria(3).Value = "=0.85*$C$" & CStr(rg.Row)
cs.ColorScaleCriteria(3).FormatColor.Color = 8109667
cs.ColorScaleCriteria(3).FormatColor.TintAndShade = 0
Next rg
End Sub
Obviously, your worksheet should be set to ThisWorkbook.Worksheets("Tracking") and your beginning range should be "D5".
I wrote this code over the weekend and it was blazing fast, when I got to work on Monday I sent an email before testing the code while servers had a load and it is infinitely slower. We are talking from 30 seconds to 15 minutes.
For x = 3 To SRLastRow
If Left(shMacro.Range("D" & x), 3) = "625" Then
shMacro.Range("BW" & x) = WorksheetFunction.XLookup(Arg1:=shMacro.Range("A" & x), Arg2:=WIPFile.Worksheets("Customer Master").Range("B:B"), Arg3:=WIPFile.Worksheets("Customer Master").Range("AD:AD"))
Else
shMacro.Range("BW" & x) = WorksheetFunction.XLookup(Arg1:=shMacro.Range("A" & x), Arg2:=WIPFile.Worksheets("Customer Master").Range("B:B"), Arg3:=WIPFile.Worksheets("Customer Master").Range("AH:AH"))
End If
If shMacro.Range("BW" & x) <> shMacro.Range("BX" & x) Then
shMacro.Range("BX" & x).Interior.ColorIndex = 3
ErrorCount = ErrorCount + 1
End If
Next x
I essentially need to pull in a value, then compare that pulled in value with a value on my Macro worksheet. If the values match do nothing, otherwise color the cell red.
I came up with the following, but haven't tested it fully yet, but the problem remains having to cycle through to find mismatches to color them.
shMacro.Range("BW3").Formula = "=IF(LEFT(D3,3)=""625"",XLOOKUP(TEXT(A3,""000""),'[WORKBOOK]Customer Master'!$AD:$AD),XLOOKUP(TEXT(A3,""000""),'[WORKBOOK]Customer Master'!$B:$B,'[WORKBOOK]Customer Master'!$AH:$AH))"
Range("BW3").AutoFill Destination:=Range("BW3:BW" & SRLastRow)
I've also tried looking into Arrays but I can't seem to figure those out. I think the autofill would be the fastest way to pull in the data, then somehow assign the two arrays (which would be columns BW and BX) and if they match do nothing, wherever they are different color BX + row reference red, and count the number of times it colored something red.
Should be a little faster (reducing cell reads without going "full array mode" and coloring all mismatches in one shot)
Sub Tester()
Dim x As Long, SRLastRow As Long
Dim colReturn As String, v, rngRed As Range, rw As Range
'...
'...
'...
Application.ScreenUpdating = False
For x = 3 To SRLastRow
Set rw = shMacro.Rows(x)
colReturn = IIf(Left(rw.Columns("D").Value, 3) = "625", "AD:AD", "AH:AH")
v = Application.XLookup( _
Arg1:=rw.Columns("A").Value, _
Arg2:=WIPFile.Worksheets("Customer Master").Range("B:B"), _
Arg3:=WIPFile.Worksheets("Customer Master").Range(colReturn))
If Not IsError(v) Then
rw.Columns("BW").Value = v
With rw.Columns("BX")
If v <> .Value Then
BuildRange rngRed, .Cells(1)
ErrorCount = ErrorCount + 1
End If
End With
End If
Next x
'color the mismatches if any
If Not rngRed Is Nothing Then rngRed.Interior.ColorIndex = 3
End Sub
'utility - build a range using Union
Sub BuildRange(ByRef rngTot As Range, rngAdd As Range)
If rngTot Is Nothing Then
Set rngTot = rngAdd
Else
Set rngTot = Application.Union(rngTot, rngAdd)
End If
End Sub
I think the reason for the slow processing is in the location of the WIPFile workbook. Therefore my code below minimizes the need to access it. I couldn't test my code for lack of data but I hope you will try it.
Sub Snippet()
' 214
Dim LookUpRng As Range ' in "Customer Master"
Dim ReturnVals As Variant ' values from "Customer Master"
Dim C As Long ' Lookup column in ReturnRng
Dim Fnd As Range ' search result
Dim x As Long ' loop counter: rows (why "x" and not "R" ?)
Dim ErrorCount As Variant
Dim Spike As String ' collect failed lookups
ErrorCount = 0
With WIPFile.Worksheets("Customer Master")
Set LookUpRng = .Columns("BB")
ReturnVals = .Range(.Columns("AD"), .Columns("AH")).Value
End With
With shMacro
For x = 3 To .Cells(.Rows.Count, "A").End(xlUp).Row
Set Fnd = LookUpRng.Find(.Cells(x, "A").Value, LookIn:=xlValues, LookAt:=xlWhole)
If Fnd Is Nothing Then
If Len(Spike) Then Spike = Spike & vbCr
Spike = Spike & String(6, " ") & """" & .Cells(x, 1).Value & """ in row " & x
Else
C = IIf(Left(.Cells(x, "D").Value, 3) = "625", 1, 5)
With .Cells(x, "BW")
.Value = ReturnVals(Fnd.Row, C)
If .Value <> .Cells(x, "BX").Value Then
.Interior.ColorIndex = 3
ErrorCount = ErrorCount + 1
End If
End With
End If
Next x
End With
If Len(Spike) Then
Spike = "The following look-ups were not successful." & vbCr & _
Spike & IIf(ErrorCount, vbCr, "")
Else
Spike = "All look-ups were successful."
End If
If ErrorCount = 0 Then ErrorCount = "No"
Spike = Spike & vbCr & ErrorCount & " matching error" & _
IIf(ErrorCount = 1, "", "s") & " were highlighted."
MsgBox Spike, vbInformation, "Action report"
End Sub
If my approach shows promise more speed could be gained by reading column B:B into another array and use a MATCH function instead of Find. In that way "Customer Master" would need to be accessed only once. Of course, you could also gain a little time by suspending ScreenUpdating during execution.
No VBA required. Use Formula + Conditional formatting
Entering the formula
Put this formula in BW3 and copy it down. Change SAMPLE.xlsx to the relevant file.
=IF(LEFT(D3,3)=625,XLOOKUP(A3,'[SAMPLE.xlsx]Customer Master'!$B:$B,'[SAMPLE.xlsx]Customer Master'!$AD:$AD),XLOOKUP(A3,'[SAMPLE.xlsx]Customer Master'!$B:$B,'[SAMPLE.xlsx]Customer Master'!$AH:$AH))
Setting up Conditional Formatting
Select the relevant range, starting for row 3.
Click on Home | Conditional formatting | New Rule | Use formula to determine which cells to format
Enter the formula =BW3<>BX3 and set the relevant color.
And you are done.
If you still want VBA then also you do not need any kind of loop or Autofill. You can enter the formula via VBA in all the cells in 1 GO! Here is an example (UNTESTED)
With shMacro
lrow = .Range("D" & .Rows.Count).End(xlUp).Row
.Range("BW3:BW" & lrow).Formula = "=IF(LEFT(D3,3)=625,XLOOKUP(A3,'[SAMPLE.xlsx]Customer Master'!$B:$B,'[SAMPLE.xlsx]Customer Master'!$AD:$AD),XLOOKUP(A3,'[SAMPLE.xlsx]Customer Master'!$B:$B,'[SAMPLE.xlsx]Customer Master'!$AH:$AH))"
End With
For conditional formatting you can use this code
With shMacro.Range("BW3:BW" & lrow)
.FormatConditions.Add Type:=xlExpression, Formula1:="=BW3<>BX3"
.FormatConditions(.FormatConditions.Count).SetFirstPriority
With .FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.Color = 255
.TintAndShade = 0
End With
.FormatConditions(1).StopIfTrue = False
End With
So basically your entire code can be written as
With shMacro
lrow = .Range("D" & .Rows.Count).End(xlUp).Row
With .Range("BW3:BW" & lrow)
.Formula = "=IF(LEFT(D3,3)=625,XLOOKUP(A3,'[SAMPLE.xlsx]Customer Master'!$B:$B,'[SAMPLE.xlsx]Customer Master'!$AD:$AD),XLOOKUP(A3,'[SAMPLE.xlsx]Customer Master'!$B:$B,'[SAMPLE.xlsx]Customer Master'!$AH:$AH))"
DoEvents
.FormatConditions.Add Type:=xlExpression, Formula1:="=BW3<>BX3"
.FormatConditions(.FormatConditions.Count).SetFirstPriority
With .FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.Color = 255
.TintAndShade = 0
End With
.FormatConditions(1).StopIfTrue = False
End With
End With
I'm trying to copy the values and conditional formatting from a column in the sheet wsHR and paste them into wsHH.
With the code below the values are pasted, but the formatting is not.
I added formatting into wsHR that isn't conditional, and it works fine copying that over.
Is there a way to paste conditional formatting?
Private Sub CommandButton1_Click()
'Set variables
Dim LastRow As Long
Dim wsHR As Worksheet
Dim wsHH As Worksheet
Dim y As Integer
'Set row value
y = 4
'Set heavy chain raw data worksheet
Set wsHR = ThisWorkbook.Worksheets(4)
'Set heavy chain hits worksheet
Set wsHH = ThisWorkbook.Worksheets(6)
'Optimizes Speed
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
'Finds last row
With wsHR
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
'Iterates through rows in column A, and copies the row into proper sheet depending on "X" in PBS/KREBS
For i = 4 To LastRow
'Checks for "X" in PBS
If VarType(wsHR.Range("AD" & i)) = 8 Then
If wsHR.Range("AD" & i).Value = "X" Or wsHR.Range("AE" & i).Value = "X" Then
With wsHH
wsHR.Range("A" & i).Copy
.Range("A" & y).PasteSpecial Paste:=xlPasteFormats
.Range("A" & y).PasteSpecial Paste:=xlPasteValues
'Range before PBS/KREBS
.Range("B" & y & ":AC" & y).Value = wsHR.Range("B" & i & ":AC" & i).Value
'Adds space to keep formulas for PBS/KREBS
'Range after PBS/KREBS
.Range("AG" & y & ":AW" & y).Value = wsHR.Range("AG" & i & ":AW" & i).Value
End With
y = y + 1
End If
End If
Next i
'Message Box when tasks are completed
MsgBox "Complete"
'Reset Macro Optimization Settings
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
I cannot use the same conditional formatting rules in the second sheet, wsHH, because not all of the values from wsHR are pasted. The conditional formatting is based on duplicates.
Found a work-around to get the formatting. Previously, you were not able to access the interior color from conditional formatting in VBA without going through a lot of extra work (see here). However, I discovered as of Excel 2010, this was changed (see here). Since I'm using Excel 2013, I am able to use .DisplayFormat to find the interior color regardless of formatting (see here).
Using this, I changed:
With wsHH
wsHR.Range("A" & i).Copy
.Range("A" & y).PasteSpecial Paste:=xlPasteFormats
.Range("A" & y).PasteSpecial Paste:=xlPasteValues
'Range before PBS/KREBS
.Range("B" & y & ":AC" & y).Value = wsHR.Range("B" & i & ":AC" & i).Value
'Adds space to keep formulas for PBS/KREBS
'Range after PBS/KREBS
.Range("AG" & y & ":AW" & y).Value = wsHR.Range("AG" & i & ":AW" & i).Value
End With
to this:
With wsHH
'Range before PBS/KREBS
.Range("A" & y & ":AC" & y).Value = wsHR.Range("A" & i & ":AC" & i).Value
'Adds space to keep formulas for PBS/KREBS
'Applying background CF color to new sheet
If wsHR.Range("A" & i).DisplayFormat.Interior.ColorIndex > 0 Then
.Range("A" & y).Interior.ColorIndex = 3
End If
'Range after PBS/KREBS
.Range("AG" & y & ":AW" & y).Value = wsHR.Range("AG" & i & ":AW" & i).Value
End With
I am no longer copying and pasting values. Instead, I set the values using .Value like I had been for the other cells in the row, and then use the outcome of If wsHR.Range("A" & i).DisplayFormat.Interior.ColorIndex > 0 Then to determine if the second sheet's cell should be formatted.
I wrote some more complete and customizable/parameterized copy subs to complete this task in a quite performant way. So one can decide if things like the following should be copied or not:
border styles
font styles
background color (foreground is always copied)
text wrapping
horizontal and/or vertical alignment
normal paste operation with its XlPasteType and XlPasteSpecialOperation params
by default enabled and copying the values and number formats
which would not copy conditional formatting styles applied
general example usage of custom subs below
e.g. the following call:
EventsDisable
PasteWithDisplayFormat Range("B40"), Range("A1:Z30")
EventsEnable
OP query example
in the OP example it should be something like this:
With wsHH
PasteWithDisplayFormat .Range("A" & y), wsHR.Range("A" & i)
'...
End With
instead of:
With wsHH
wsHR.Range("A" & i).Copy
.Range("A" & y).PasteSpecial Paste:=xlPasteFormats
.Range("A" & y).PasteSpecial Paste:=xlPasteValues
'...
End With
custom subs
(please feel free to enhance/extend it here for others)
'including conditional formatting as fixed styles (DisplayFormat)
'based on Range.PasteSpecial
Public Sub PasteWithDisplayFormat( _
dst As Range, _
Optional src As Range, _
Optional pasteSpecialBefore As Boolean = True, _
Optional paste As XlPasteType = xlPasteValuesAndNumberFormats, _
Optional Operation As XlPasteSpecialOperation = xlNone, _
Optional SkipBlanks As Boolean = False, _
Optional Transpose As Boolean = False, _
Optional Borders As Boolean = True, _
Optional Font As Boolean = True, _
Optional InteriorColor As Boolean = True, _
Optional WrapText As Boolean = True, _
Optional HorizontalAlignment As Boolean = True, _
Optional VerticalAlignment As Boolean = True _
)
If src Is Nothing Then Set src = Selection
If pasteSpecialBefore Then dst.PasteSpecial paste:=paste, Operation:=Operation, SkipBlanks:=False, Transpose:=False
Dim x As Integer: For x = 1 To src.Rows.Count
For y = 1 To src.Columns.Count
Dim sf As DisplayFormat: Set sf = src.Cells(x, y).DisplayFormat 'source cells DisplayFormat
With dst.Cells(x, y)
If Borders Then CopyBorders .Borders, sf.Borders
If Font Then
.Font.ColorIndex = sf.Font.ColorIndex
.Font.Color = sf.Font.Color
.Font.Background = sf.Font.Background
.Font.FontStyle = sf.Font.FontStyle '=> bold + italic
'.Font.Bold = sf.Font.Bold
'.Font.Italic = sf.Font.Italic
.Font.Size = sf.Font.Size
.Font.Name = sf.Font.Name
End If
If InteriorColor Then .Interior.Color = sf.Interior.Color
If WrapText Then .WrapText = sf.WrapText
If HorizontalAlignment Then .HorizontalAlignment = sf.HorizontalAlignment
If VerticalAlignment Then .VerticalAlignment = sf.VerticalAlignment
End With
Next y
Next x
End Sub
Sub CopyBorders(dst As Borders, src As Borders)
If src.LineStyle <> xlLineStyleNone Then
dst.ColorIndex = src.ColorIndex
If src.ColorIndex <> 0 Then dst.Color = src.Color
dst.Weight = src.Weight
dst.LineStyle = src.LineStyle
dst.TintAndShade = src.TintAndShade
End If
Dim bi As Integer: For bi = 1 To src.Count 'border index
CopyBorder dst(bi), src(bi)
Next bi
End Sub
Sub CopyBorder(dst As Border, src As Border)
If src.LineStyle <> xlLineStyleNone Then
dst.ColorIndex = src.ColorIndex
If src.ColorIndex <> 0 Then dst.Color = src.Color
dst.Weight = src.Weight
dst.LineStyle = src.LineStyle
dst.TintAndShade = src.TintAndShade
End If
End Sub
'used with EventsEnable()
Sub EventsDisable()
With Application: .EnableEvents = False: .ScreenUpdating = False: .Calculation = xlCalculationManual: End With
End Sub
'used with EventsDisable()
Sub EventsEnable()
With Application: .EnableEvents = True: .ScreenUpdating = True: .Calculation = xlCalculationAutomatic: End With
End Sub
Other approaches found
temp MS Word doc approach
here is one example based on copying to a temp word file and pasting back, but (at least on more complex tables) results in the pasting of some OLE embedded object that is not really usable in excel anymore, but could suffice for other uses:
https://www.ozgrid.com/forum/forum/help-forums/excel-general/119606-copy-colors-but-not-conditional-formating?p=1059236#post1059236
xlPasteAllMergingConditionalFormats
using xlPasteAllMergingConditionalFormats as the XlPasteType seems to produce the same result like the temp MS Word doc approach above
I've got a Worksheet titled "Survey". I'm trying to attach checkboxes to all of the cells in column A that are next to answers, and for some reason I'm getting an "object required" error. The 4 lines near the beginning, starting with "Set rng =", are highlighted.
I'm pretty new to VBA, so I'm not sure if this is just a simple syntax issue that I'm not seeing. I've tried searching for the proper format, to no avail. Can anyone help? Here's the code that I've got:
Sub AddCheckBox()
Dim rng As Range
Dim rcell As Range
Set rng = Survey.Range("A7:A10,A13:A17,A21:A25,A28:A33" _
& "A36:A43, A48,A51:A56,A60:A66,A69:A73,A76:A80" _
& "A83:A87, A90:A94, A97:A102, A105:A113, A116:A122, A125:A131" _
& "A134:A141,A145:A149, A152:A158, A161:A165")
DelCheckBox
For Each rcell In rng
With ActiveSheet.CheckBoxes.Add(rcell.Left, _
rcell.Top, rcell.Width, rcell.Height)
.LinkedCell = rcell.Offset(, 0).Address(External:=True)
.Interior.ColorIndex = 14 'or xlNone or xlAutomatic
.Caption = ""
.Border.Weight = xlThin
End With
Next
With Range("A7:A10,A13:A17,A21:A25,A28:A33" _
& "A36:A43, A48,A51:A56,A60:A66,A69:A73,A76:A80" _
& "A83:A87, A90:A94, A97:A102, A105:A113, A116:A122, A125:A131" _
& "A134:A141,A145:A149, A152:A158, A161:A165")
.Rows.RowHeight = 15
End With
End Sub
Sub DelCheckBox()
For Each cell In Range("A1:A166")
Worksheets("Survey").CheckBoxes.Delete
Next
End Sub
You're missing the commas at the end of your lines. Try this:
Set rng = Survey.Range("A7:A10,A13:A17,A21:A25,A28:A33," _
& "A36:A43, A48,A51:A56,A60:A66,A69:A73,A76:A80," _
& "A83:A87, A90:A94, A97:A102, A105:A113, A116:A122, A125:A131," _
& "A134:A141,A145:A149, A152:A158, A161:A165")
Note, you'll have to make the same change where you have the With Range("....") block as well. Also, the above code does not reflect the validity of the rest of what you're trying to do...just that one error.
EDIT to fix issues down the road...
Try this all of this code and see if it does what you're after:
Sub test()
Dim rng As Range
Dim rcell As Range
Set rng = Sheets("Survey").Range("A7:A10,A13:A17,A21:A25,A28:A33," _
& "A36:A43, A48,A51:A56,A60:A66,A69:A73,A76:A80," _
& "A83:A87, A90:A94, A97:A102, A105:A113, A116:A122, A125:A131," _
& "A134:A141,A145:A149, A152:A158, A161:A165")
DelCheckBox
For Each rcell In rng
With Sheets("Survey").CheckBoxes.Add(rcell.Left, _
rcell.Top, rcell.Width, rcell.Height)
.LinkedCell = rcell.Offset(, 0).Address(External:=True)
.Interior.ColorIndex = 14 'or xlNone or xlAutomatic
.Caption = ""
.Border.Weight = xlThin
End With
Next
rng.Rows.RowHeight = 15
End Sub
Sub DelCheckBox()
Sheets("Survey").DrawingObjects.Delete
End Sub
I'm very new to VBA (and any sort of programming in general), so I'm not sure how to proceed here. I'm guessing my error has something to do with overlapping ranges for my conditional formats as I also got errors when the code was set up a different way that were resolved once the ranges no longer overlapped. That might not be the case here, but I figured it'd be helpful to know.
I get a 'Subscript out of range' error with the following code:
Sub test2()
Dim rngToFormat As Range
Set rngToFormat = ActiveSheet.Range("$a$1:$z$1000")
Dim rngToFormat2 As Range
Set rngToFormat2 = ActiveSheet.Range("$k$20:$k$1000")
Dim rngToFormat3 As Range
Set rngToFormat3 = ActiveSheet.Range("$j$22:$j$1000")
Dim rngToFormat4 As Range
Set rngToFormat4 = ActiveSheet.Range("$i$22:$i$1000")
Dim rngToFormat5 As Range
Set rngToFormat5 = ActiveSheet.Range("$g$20:$g$1000")
Dim rngToFormat6 As Range
Set rngToFormat6 = ActiveSheet.Range("$d$9, $f$9")
Dim rngToFormat7 As Range
Set rngToFormat7 = ActiveSheet.Range("$G$3:$G$7,$G$11:$G$15,$E$3:$E$7,$E$11:$E$15,$N$3:$N$7,$N$11:$N$15,$L$3:$L$7,$L$11:$L$15")
rngToFormat.FormatConditions.Delete
rngToFormat.FormatConditions.Add Type:=xlExpression, _
Formula1:="=if(R[]C20=1, true(), false())"
rngToFormat.FormatConditions(1).Font.Color = RGB(228, 109, 10)
rngToFormat2.FormatConditions.Add Type:=xlExpression, _
Formula1:="=and(R[]C7=""6. Negotiate"", R[]C11<25)"
rngToFormat2.FormatConditions(2).Font.ColorIndex = 3
rngToFormat2.FormatConditions.Add Type:=xlExpression, _
Formula1:="=and(R[]C7=""4. Develop"", R[]C11<15)"
rngToFormat2.FormatConditions(3).Font.ColorIndex = 3
rngToFormat2.FormatConditions.Add Type:=xlExpression, _
Formula1:="=and(R[]C7=""5. Prove"", R[]C11<20)"
rngToFormat2.FormatConditions(4).Font.ColorIndex = 3
rngToFormat2.FormatConditions.Add Type:=xlExpression, _
Formula1:="=and(R[]C7=""7. Committed"", R[]C11<30)"
rngToFormat2.FormatConditions(5).Font.ColorIndex = 3
rngToFormat2.FormatConditions.Add Type:=xlExpression, _
Formula1:="=and(R[]C7=""Closed Won"", R[]C11<35)"
rngToFormat2.FormatConditions(6).Font.ColorIndex = 3
rngToFormat3.FormatConditions.Add Type:=xlCellValue, _
Operator:=xlGreater, Formula1:=200
rngToFormat3.FormatConditions(7).Font.ColorIndex = 3
rngToFormat4.FormatConditions.Add Type:=xlCellValue, _
Operator:=xlGreater, Formula1:=60
rngToFormat4.FormatConditions(8).Font.ColorIndex = 3
rngToFormat5.FormatConditions.Add Type:=xlExpression, _
Formula1:="=or(R[]C7=""1. Plan"", R[]C7=""2. Create"", R[]C7=""3. Qualify"")"
rngToFormat5.FormatConditions(9).Font.ColorIndex = 3
rngToFormat6.FormatConditions.Add Type:=xlCellValue, _
Operator:=xlLess, Formula1:=0
rngToFormat6.FormatConditions(10).Font.ColorIndex = 3
rngToFormat6.FormatConditions(10).Interior.Color = RGB(204, 204, 255)
rngToFormat6.FormatConditions(10).Interior.Pattern = xlSolid
rngToFormat7.FormatConditions.Add Type:=xlCellValue, _
Operator:=xlLess, Formula1:=0
rngToFormat7.FormatConditions(11).Font.ColorIndex = 3
rngToFormat7.FormatConditions(11).Interior.Color = RGB(215, 228, 158)
rngToFormat7.FormatConditions(11).Interior.Pattern = xlSolid
End Sub
Any advice would be appreciated, thanks!
There are two problems with your code:
You only delete the conditional formats for the first range - but add conditions to all ranges - and later access a specific one that most likely is not the one you just created (FormatConditions(3))
The formulas you entered are the default english formulas - for some stange reason, FormatConditions.Add requires the local formulas though.
I reworked your code, take a look if it solves your problem:
Sub test2()
fctApply rng:=Range("$a$1:$z$1000"), strFormulaR1C1:="=(R[]C20=1)", dblRGB:=RGB(228, 109, 10), blnDeleteOldConditions:=True
fctApply rng:=Range("$k$20:$k$1000"), strFormulaR1C1:="=and(R[]C7=""6. Negotiate"",R[]C11<25)", intColorIndex:=3
fctApply rng:=Range("$k$20:$k$1000"), strFormulaR1C1:="=and(R[]C7=""4. Develop"", R[]C11<15)", intColorIndex:=3
fctApply rng:=Range("$k$20:$k$1000"), strFormulaR1C1:="=and(R[]C7=""5. Prove"", R[]C11<20)", intColorIndex:=3
fctApply rng:=Range("$k$20:$k$1000"), strFormulaR1C1:="=and(R[]C7=""7. Committed"", R[]C11<30)", intColorIndex:=3
fctApply rng:=Range("$k$20:$k$1000"), strFormulaR1C1:="=and(R[]C7=""Closed Won"", R[]C11<35)", intColorIndex:=3
fctApply rng:=Range("$j$22:$j$10000"), strFormulaR1C1:=200, intType:=xlCellValue, intOperator:=xlGreater, intColorIndex:=3
fctApply rng:=Range("$i$22:$i$1000"), strFormulaR1C1:=60, intType:=xlCellValue, intOperator:=xlGreater, intColorIndex:=3
With fctApply(rng:=Range("$g$20:$g$1000"), strFormulaR1C1:=0, intType:=xlCellValue, intOperator:=xlLess, intColorIndex:=3)
.Interior.Color = RGB(204, 204, 255)
.Interior.Pattern = xlSolid
End With
With fctApply(rng:=Range("$G$3:$G$7,$G$11:$G$15,$E$3:$E$7,$E$11:$E$15,$N$3:$N$7,$N$11:$N$15,$L$3:$L$7,$L$11:$L$15"), strFormulaR1C1:=0, intType:=xlCellValue, intOperator:=xlLess, intColorIndex:=3)
.Interior.Color = RGB(215, 228, 158)
.Interior.Pattern = xlSolid
End With
End Sub
Private Function fctApply(rng As Range, _
strFormulaR1C1 As Variant, _
Optional intType As XlFormatConditionType = xlExpression, _
Optional intOperator As XlFormatConditionOperator, _
Optional intColorIndex As Integer = -1, _
Optional dblRGB As Double = -1, _
Optional blnDeleteOldConditions As Boolean = False _
) As FormatCondition
Dim objCond As FormatCondition
Dim strFormula As String
If blnDeleteOldConditions Then rng.FormatConditions.Delete
strFormula = Application.ConvertFormula(strFormulaR1C1, xlR1C1, xlA1)
On Error GoTo ConvertLocal
If intOperator <> 0 Then
rng.FormatConditions.Add Type:=intType, _
Formula1:=strFormula, Operator:=intOperator
Else
rng.FormatConditions.Add Type:=intType, _
Formula1:=strFormula
End If
On Error GoTo 0
Set objCond = rng.FormatConditions(rng.FormatConditions.Count)
If intColorIndex <> -1 Then
objCond.Font.ColorIndex = intColorIndex
ElseIf dblRGB <> -1 Then
objCond.Font.Color = dblRGB
End If
Set fctApply = objCond
Exit Function
ConvertLocal:
With Range("A1") 'change this to an empty cell address - it is temporarily used to translate from local to normal formulas
.Formula = strFormula
strFormula = .FormulaLocal
.Formula = ""
End With
Resume
End Function