Color code the columns - vba

In an excel file, I need to color code a column cell depending upon the number of "Yes" in that Column. If there are no "Yes" : Red color; one "Yes": Yellow color: 2 or more than 2 "Yes": Green color.
Can this be done by some macro ?
Update:
Have made this macro but i am not able to run or debug it as it gives an error of Overflow;
The variable N is taking a value of 32676 even after I have assigned it zero value .
Sub testcolor()
Dim i As Integer
Dim j As Integer
Dim N As Integer
Dim z As Integer
Dim val As String
i = 7
j = 5
N = 0
MsgBox (N)
For j = 5 To 15
Do While i < 13
val = ActiveSheet.Cells(i, j).Value
If val = "Yes" Then N = N + 1
Loop
If N = 0 Then
Range(i + 2, j).Select
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 255
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End If
If N = 1 Then
Range(i + 2, j).Select
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End If
If N > 1 Then
Range(i + 2, j).Select
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 5296274
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End If
Next j
End Sub

Another way to solve this is by using Conditional Formatting.
Select the area you wish to format. Looks like it's range E14:K14 in your book.
Click Home > Conditional Formatting > New Rule.
In the New Formatting Rule dialog box, click "Use a formula to determine which cells to format".
Under "Format values where this formula is true", type the following formula:
=AND(E14="Yes",COUNTIF(E:E,"Yes")>=2,ROW()>=7,ROW()<=13)
Next, click the "Format" button.
Now, simply choose the design you wish. Perhaps a colored background is enough.
The GREEN formula is done, but you have to repeat these steps for the yellow and red formulas.
The yellow formula:
=AND(E14="Yes",COUNTIF(E:E,"Yes")<2;COUNTIF(E:E,"Yes")>0,ROW()>=7,ROW()<=13)
And the red formula:
=AND(E14="Yes",COUNTIF(E:E,"Yes")=0,ROW()>=7,ROW()<=13)
Don't forget to apply your format conditions (green/yellow/red background).
Let me break the GREEN formula down for you:
AND() - All of the conditions in between these () brackets need to be met.
E14="Yes" - The cell has to contain the word "Yes".
COUNTIF(E:E,"Yes")>=2 - The column must have 2 or more "Yes".
ROW()>=7,ROW()<=13) - The cell has to be somewhere in between rows 7 to 13.
It's quite easy to change these parameters whenever you need to. And perhaps it's easier than jumping into a big chunk of code. It may look quite difficult using Conditional Formatting with multiple conditions, but once you get a hang of it you won't stop using it.

Try this (set RGB and ColorIndex accordingly, did not get if you want cell text color or fill color):
Sub ConditionalColorColumn()
count = Application.WorksheetFunction.CountIf(arg1:=Range("D:D"), arg2:="yes")
'MsgBox count
If count = 1 Then
ActiveSheet.Range("D:D").Font.Color = RGB(255, 255, 0)
ActiveSheet.Range("D:D").Interior.ColorIndex = 6
ElseIf count >= 2 Then
ActiveSheet.Range("D:D").Font.Color = RGB(255, 255, 0)
ActiveSheet.Range("D:D").Interior.ColorIndex = 6
Else
ActiveSheet.Range("D:D").Font.Color = RGB(255, 255, 0)
ActiveSheet.Range("D:D").Interior.ColorIndex = 6
End If
End Sub
APPENDED: you can try this for multiple columns
Sub ConditionalColorMultiColumn()
'Dim arr As Variant
'Dim desCell As Range
arr = Array("E", "F", "G", "H", "I","J","K")
For i = 0 To UBound(arr)
Set rngg = Range(arr(i) & 7 & ":" & arr(i) & 12)
'rngg.Select
Set desCell = Cells(14, arr(i))
Count = Application.WorksheetFunction.CountIf(arg1:=rngg, arg2:="yes")
'MsgBox count
If Count = 1 Then
desCell.Interior.ColorIndex = 6
ElseIf Count >= 2 Then
desCell.Interior.ColorIndex = 4
Else: desCell.Interior.ColorIndex = 3
End If
Set desCell = Nothing
Set rngg = Nothing
Next
End Sub

Related

Excel conditional formatting highlighting rows when 3 to 10 most recent values in a row are above a limit

I have created a large spreadsheet with around 80,000 cells with an array of conditional formatting highlighting different points of interest. Two of these conditional formats involve large arrays that cause slowdown on the file. I'm looking for a way to make this more efficient.
The table reads left to right with the dates Jan 1st to Dec 31st along the top and down with various items and the limits identified in their respective row on the far right after Dec 31st. The date ordering prevents sorting of the data beforehand.
Below is the initial root for the formula. This is then replicated to both solve the problem and cause the problem. It looks through the unsorted row for non-blank cells, picks the top X number of values and compares them to the limit in Col $NG. It ignores the description columns with the -5 row reference and provides a 0 to avoid a #NUM error for insufficient values for LARGE().
IF(ISERROR(INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),1)))-5)>$NG2),0,INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),1)))-5)>$NG2)
This is the first of 2 conditional formatting formulas that aims to highlight the row when 2 out of 3 of the most recent (furthest right) values are above the limit in $NG2.
=IF(COUNT($F2:$NF2)<2,"",SUM(IF(ISERROR(INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),1)))-5)>$NG2),0,INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),1)))-5)>$NG2),IF(ISERROR(INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),2)))-5)>$NG2),0,INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),2)))-5)>$NG2),IF(ISERROR(INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),3)))-5)>$NG2),0,INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),3)))-5)>$NG2))>=2)
Again, a replication of the root formula 10 times to catch 3 out of 10 of the furthest right values being above the limit.
=IF(COUNT($F2:$NF2)<2,"",SUM(IF(ISERROR(INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),1)))-5)>$NG2),0,INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),1)))-5)>$NG2),IF(ISERROR(INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),2)))-5)>$NG2),0,INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),2)))-5)>$NG2),IF(ISERROR(INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),3)))-5)>$NG2),0,INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),3)))-5)>$NG2),IF(ISERROR(INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),4)))-5)>$NG2),0,INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),4)))-5)>$NG2),IF(ISERROR(INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),5)))-5)>$NG2),0,INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),5)))-5)>$NG2),IF(ISERROR(INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),6)))-5)>$NG2),0,INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),6)))-5)>$NG2),IF(ISERROR(INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),7)))-5)>$NG2),0,INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),7)))-5)>$NG2),IF(ISERROR(INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),8)))-5)>$NG2),0,INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),8)))-5)>$NG2),IF(ISERROR(INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),9)))-5)>$NG2),0,INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),9)))-5)>$NG2),IF(ISERROR(INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),10)))-5)>$NG2),0,INDEX($F2:$NF2,SUMPRODUCT((LARGE(($F2:$NF2<>"")*COLUMN($F2:$NF2),10)))-5)>$NG2))>=3)
I considered an xlToLeft VBA Function with a Do Until 2 Or 3, but struggled to replicate the variable column ID within the Index Match.
In case it's useful to anyone else as a reference:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim a, w, x, y, z As Integer
Dim b As Range
w = 0
x = Target.Row()
'Bypass limits column
y = Range("NG" & x).Column()
'Set column value while bypassing blanks
If Cells(x, y - 1) <> "" Then
y = y - 1
Else
y = Cells(x, y).End(xlToLeft).Column
End If
z = 0
a = ActiveSheet.Cells(ActiveSheet.Rows.Count, "A").End(xlUp).Row
Set b = Range("F2:NF" & a)
If Not Target.Cells.Count > 1 Then
If Not Application.Intersect(b, Range(Target.Address)) Is Nothing Then
Do Until y = 5 Or z = 2 Or w >= 3
If Cells(x, y) >= 0 Then
If Cells(x, y) > Range("NG" & x) Then
z = z + 1
End If
End If
w = w + 1
If Cells(x, y - 1) <> "" Then
y = y - 1
Else
y = Cells(x, y).End(xlToLeft).Column
End If
Loop
If z < 2 And y > 5 Then
Do Until y = 5 Or z = 3 Or w >= 10
If Cells(x, y) >= 0 Then
If Cells(x, y) > Range("NG" & x) Then
z = z + 1
End If
End If
w = w + 1
If Cells(x, y - 1) <> "" Then
y = y - 1
Else
y = Cells(x, y).End(xlToLeft).Column
End If
Loop
End If
If z = 2 And w <= 3 Then
With Range("A" & x, "E" & x).Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 12874308
.TintAndShade = 0
.PatternTintAndShade = 0
End With
With Range("A" & x, "E" & x).Font
.Color = -2
.TintAndShade = 0
End With
Range("A" & x, "E" & x).Font.Bold = True
End If
If z = 3 And w >= 3 Then
With Range("A" & x, "E" & x).Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 7434613
.TintAndShade = 0
.PatternTintAndShade = 0
End With
With Range("A" & x, "E" & x).Font
.Color = -13533715
.TintAndShade = 0
End With
Range("A" & x, "E" & x).Font.Bold = True
End If
If z <= 2 And w > 3 Then
If Range("A" & x).Font.Bold = True Then
With Range("A" & x, "E" & x).Font
.ColorIndex = xlAutomatic
.TintAndShade = 0
End With
With Range("A" & x, "E" & x).Interior
.Pattern = xlNone
.TintAndShade = 0
.PatternTintAndShade = 0
End With
Range("A" & x, "E" & x).Font.Bold = False
End If
End If
End If
End If
End Sub

Conditional formatting for highlighting top 2 values for each row for visibile cells only

I am trying to highlight top 2 values for each row for visible cells only using conditional formatting in Excel macro. My range is dynamic, hence I am running a loop to arrive at the last cell of the range.
Here is my code:
With Sheets("pcSupplyChainAnalysis").Select
For i = 2 To ctr
Set rng = Range("C" & i & ":" & "I" & i).SpecialCells(xlCellTypeVisible)
rng.FormatConditions.AddTop10
rng.FormatConditions(rng.FormatConditions.Count).SetFirstPriority
With rng.FormatConditions(1)
.TopBottom = xlTop10Top
.Rank = 2
.Percent = False
End With
With rng.FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.Color = 255
.TintAndShade = 0
End With
rng.FormatConditions(1).StopIfTrue = False
Next
End With
Ctr is a counter I am running to find the position of the last non blank cell, as my data has blank values too and I am copying it from another sheet using macro.
ctr = 2
Do While (ActiveSheet.Range("A" & ctr).Value <> "")
ctr = ctr + 1
Loop
ctr = ctr - 1
ActiveSheet.Range("B2:I" & ctr).Select
Selection.Cut
Range("C2:J" & ctr).Select
ActiveSheet.Paste
Attached is the image of the format of my data. I want to highlight top 2 numbers for each row and ONLY FOR VISIBLE CELLS (as I am using some filters also in the range).
Try this:
Option Explicit
Public Sub ShowTop2()
Dim rng As Range, visibleRow As Range
Application.ScreenUpdating = False
With ThisWorkbook.Worksheets("pcSupplyChainAnalysis")
.Columns.FormatConditions.Delete
Set rng = .UsedRange.SpecialCells(xlCellTypeVisible)
End With
For Each visibleRow In rng.Rows
If visibleRow.Row > 1 Then
With visibleRow.FormatConditions
.AddTop10
.Item(.Count).SetFirstPriority
With .Item(1)
.TopBottom = xlTop10Top
.Rank = 2
.Interior.Color = 255
End With
End With
End If
Next
Application.ScreenUpdating = True
End Sub
An easier way to determine the last used row in column A:
ctr = Worksheets("pcSupplyChainAnalysis").Cells(Rows.Count, "A").End(xlUp).Row
You don't need to Select anything for any of your actions

VBA For loop with If loop

I have an issue with my VBA code. I try to compare 2 columns, both A and B columns. If some data match, for example let's say that A2 contains text in B3, then I need to compare the cell C2 with the column D. I don't understand why but I get the error "End If without block If". Thanks a lot for you help guys.
Here is my code :
Sub Compare()
For i = 1 To 100
For j = 1 To 50
If InStr(1, ActiveSheet.Cells(i, 1).Value, ActiveSheet.Cells(j, 2).Value, vbTextCompare) <> 0 _
Then For k = 1 To 20
If InStr(1, ActiveSheet.Cells(i, 3).Value, ActiveSheet.Cells(k, 4).Value, vbTextCompare) <> 0 Then MsgBox i
End If
Next k
End If
Next j
Next i
End Sub
I found the structure of your if statements a bit confusing and I'm not entirely sure you can do a for loop as a one-liner like that to get rid of all the end ifs. For what it's worth, I think this code is a bit easier to follow:
Sub Compare()
For i = 1 To 100
For j = 1 To 50
If InStr(1, ActiveSheet.Cells(i, 1).Value, ActiveSheet.Cells(j, 2).Value, vbTextCompare) <> 0 Then
For k = 1 To 20
If InStr(1, ActiveSheet.Cells(i, 3).Value, ActiveSheet.Cells(k, 4).Value, vbTextCompare) <> 0 Then MsgBox i
Next k
End If
Next j
Next i
End Sub
This runs w/o a compile error, but can't comment if it does what you want it to do.
sous2817 raised an interesting question in their answer about whether or not a 1-line statement works if the body of the if statement is itself a for-loop. The answer appears to be "no" -- unless the for-loop itself is squeezed onto one line by using the colon statement separator:
Sub test1() 'compile error
Dim i As Long, s As Long
If i = 0 _
Then For i = 1 To 10
s = s + i
Next i
MsgBox s
End Sub
Sub test2() 'compiles okay
Dim i As Long, s As Long
If i = 0 _
Then For i = 1 To 10: s = s + i: Next i
MsgBox s
End Sub
If statements on one line don't need the End If statement.
End If without block If
Sub comparison()
For i = 2 To 1000
For j = 2 To 1000
If Worksheets(Worksheet).Range("A" & i).Value = Worksheets(Worksheet).Range("L" & j).Value Then
Worksheets(worksheet).Range("N" & j).Select
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End If
Next j
Next i
End Sub

Convert VBA code to run in vbscript [duplicate]

This question already has an answer here:
VBA Conditional Formatting if Cell Not Between
(1 answer)
Closed 7 years ago.
I have this VBA code for conditional formatting.
Selection.FormatConditions.Add Type:=xlCellValue, Operator:=xlNotBetween, _
Formula1:="=$I$10", Formula2:="=$J$10"
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
I have a vbscript that creates an Excel sheet and I need to apply that VBA code to a cell in the Excel sheet as it is created. Having issues getting it to run. I know I need to sub the actual values for the excel constants but there's more to it I just don't get
What I've done so far
priceRange = "K"&rowNum + 2
objWorkSheet.Range(priceRange).FormatConditions.Add Type:=1, Operator:=2, Formula1:="=$I$"&finalRowNum + 1&"", Formula2:="=$J$"&finalRowNum + 1&""
objWorkSheet.Range(priceRange).FormatConditions(objExcel.Selection.FormatConditions.Count).SetFirstPriority
objWorkSheet.Range(priceRange).FormatConditions(1).Interior.PatternColorIndex = -4105
objWorkSheet.Range(priceRange).FormatConditions(1).Interior.Color = 255
objWorkSheet.Range(priceRange).FormatConditions(1).Interior.TintAndShade = 0
objWorkSheet.Range(priceRange).FormatConditions(1).StopIfTrue = False
I need it to apply the conditional formatting to the a specific cell (the one I defined as priceRange)
Untested:
Dim rng, fc, rowNum, finalRowNum, objWorkSheet
'...
'...
Set rng = objWorkSheet.Range("K" & rowNum + 2)
'vbscript doesn't support named arguments, only positional
Set fc = rng.FormatConditions.Add(1, 2, _
"=$I$" & finalRowNum, _
"=$J$" & finalRowNum)
fc.SetFirstPriority
With fc.Interior
.PatternColorIndex = -4105
.Color = 255
.TintAndShade = 0
End With
fc.StopIfTrue = False

How to Loop Through 5 Cells in a Row Using Excel VBA

I want to loop through 5 cells, Q5 - U5.
With each cell I want to check if the value is equal to "Y", and if yes, highlight the cell to make it green.
How may I do so? Can't seem to figure it out.
For Each c In Range("Q5:U5").Cells
c.Select
If c.Value = Y Then
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 5287936
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End If
Next
You should try to avoid selecting/activating ranges: in 99% of cases there is no need (although the macro recorder always suggests otherwise)
For Each c In ActiveSheet.Range("Q5:U5").Cells
If c.Value = "Y" Then
With c.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 5287936
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End If
Next
When you don't define c as a range, the statement
For Each c in ActiveSheet.Range("Q5:U5").Cells
while valid, will actually result in c having the value of each of the cells. To solve this problem, declare the type explicitly:
Dim c as Range
Next, when you do the comparison (as already pointed out), use
If c.Value = "Y"
Note - if you declare
Option Compare Text
right at the top of your module, the comparison will be case-insensitive; otherwise, a "Y" will not match a "y".
The whole module would look like this, then:
Option Explicit
Option Compare Text
Sub colorMe()
Dim c as Range
For Each c In Range("Q5:U5").Cells
c.Select
If c.Value = "Y" Then
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 5287936
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End If
Next
End Sub
I am sure it doesn't need to be pointed out that you could achieve the same thing with conditional formatting...
In your code, Y appears to be an undefined variable. To check for the value, put it in double quotes:
If c.Value = "Y" Then