On an active range selection, how to find only the cells that contains "0" and "#N/A" - and replace it by text "NA" and change the font color to "red".
Here is the macro I am using to "convert formulas to absolute values " and "to find empty cells to put text "NA".
sub XConvertToValues()
Dim MyRange As Range
Dim MyCell As Range
Set MyRange = Selection
For Each MyCell In MyRange
If MyCell.HasFormula Then
MyCell.Formula = MyCell.Value
End If
If IsEmpty(MyCell.Value) = True Then
MyCell.Value = "NA"
End If
Next MyCell
End Sub
edited after OP's clarification about data format
use Replace() and AutoFilter() method of Range object
Sub XConvertToValues()
With Selection
.Value = .Value '<--| convert all formulas to their values
.Replace What:="#N/A", replacement:="NA", LookAt:=xlWhole
.Replace What:="0", replacement:="NA", LookAt:=xlWhole
If WorksheetFunction.CountIf(.Cells, "NA") > 0 Then
.AutoFilter field:=1, Criteria1:="NA"
.Resize(IIf(.Cells(1) = "NA", .Rows.count, .Rows.count - 1)).Offset(IIf(.Cells(1) = "NA", 0, 1)).SpecialCells(xlCellTypeVisible).Font.ColorIndex = 3
.Parent.AutoFilterMode = False
End If
End With
End Sub
i'm beginner too , this what can i make and maybe it will help you , you can just put number of cells you want to change or rewrite the code with FOR EACH
Dim i As Integer
On Error Resume Next
For i = 1 To 20
cells.Find(What:="0", MatchCase:=False_, SearchFormat:=False).Activate
ActiveCell.FormulaR1C1 = "NA"
With Selection.Font
.Color = -16776961
.TintAndShade = 0
End With
cells.Find(What:="#N/A", MatchCase:=False_, SearchFormat:=False).Activate
ActiveCell.FormulaR1C1 = "NA"
With Selection.Font
.Color = -16776961
.TintAndShade = 0
End With
Next i
edit
Now as you have provided more info, this can be done like:
Try this
Sub ConvertToValues()
Dim R As Long
k = Sheet1.Range("A1048576").End(xlUp).Row '-> total rows in column A
For R = 1 To k
If IsEmpty(Sheet1.Cells(R, 2)) = True Or Sheet1.Cells(R, 2) = "#NA" Or Sheet1.Cells(R, 2) = "0" Then
Sheet1.Cells(R, 2).Value = "NA"
Sheet1.Cells(R, 2).Font.Color = RGB(255, 0, 0)
End If
Next R
End Sub
Related
I have a script that changes the cell color and a script to hide the cells that are not colored. The hide script works, but it hides ALL the cells, even the colored ones. I noticed that when I use the script that changes the cell color, it does not detect the changes in the excel interface(in the 'Fill Color' settings in 'Home' tab, under the 'font size' selection). I also noticed that when try to change the color of the cells (using the excel interface) that are colored from using the script, it does not change (the color seems to be fixed to whatever is set from the script).
Therefore, it seems like the interface does not detect the changes that are being made using the coloring script.
Also, I noticed the script below takes a while to check/hide all the cells. If there is a way to speed up the process, that would be great!
Any help will be greatly appreciated!
Thank you!
The script to hide uncolored cells:
Public Sub HideUncoloredRows()
Dim startColumn As Integer
Dim startRow As Integer
Dim totalRows As Integer
Dim totalColumns As Integer
Dim currentColumn As Integer
Dim currentRow As Integer
Dim shouldHideRow As Integer
startColumn = 1 'column A
startRow = 1 'row 1
totalRows = Sheet1.Cells(Rows.Count, startColumn).End(xlUp).Row
For currentRow = totalRows To startRow Step -1
shouldHideRow = True
totalColumns = Sheet2.Cells(currentRow, Columns.Count).End(xlToLeft).Column
'for each column in the current row, check the cell color
For currentColumn = startColumn To totalColumns
'if any colored cell is found, don't hide the row and move on to next row
If Not Sheet1.Cells(currentRow, currentColumn).Interior.ColorIndex = -4142 Then
shouldHideRow = False
Exit For
End If
Next
If shouldHideRow Then
'drop into here if all cells in a row were white
Sheet2.Cells(currentRow, currentColumn).EntireRow.Hidden = True
End If
Next
End Sub
The script that changes the color certain cells:
Range("A8").Select
Application.CutCopyMode = False
Range("A8").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.FormatConditions.Add Type:=xlExpression, Formula1:= _
"=COUNTIF(Name_Preps,A8)=1"
Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
With Selection.FormatConditions(1).Font
.Bold = True
.Italic = False
.TintAndShade = 0
End With
With Selection.FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorAccent3 'Changes the cell to green
.TintAndShade = 0.4
End With
Selection.FormatConditions(1).StopIfTrue = False
End Sub
Try to change your condition to follow
For currentColumn = startColumn To totalColumns
'if any colored cell is found, don't hide the row and move on to next row
If Sheet1.Cells(currentRow, currentColumn).Interior.ThemeColor = xlThemeColorAccent3 Then
shouldHideRow = False
Exit For
End If
Next
conditional formatting is not detected by Interior.ColorIndex and the likes
if you want to go on that way you can see here or here for relevant code
but I'd abandon conditional formatting as well as Select/Selection/Activate/ActiveXXX pattern and go simply this way:
Option Explicit
Sub HandleRowsColorAndVisibility()
Dim iRow As Long
With Range("A8", Cells(Rows.count, 1).End(xlUp)) '<--| reference cells from A8 down to column A last not empty cell
ResetRange .Cells '<--| first, bring range formatting and visibility back to a "default" state
For iRow = .Rows.count To 1 Step -1 '<--| then start looping through range
If WorksheetFunction.CountIf(Range("Name_Preps"), .Cells(iRow, 1)) = 1 Then '<-- if current cell matches your criteria ...
FormatRange .Cells(iRow, 1), True, False, 0, xlColorIndexAutomatic, xlThemeColorAccent3, 0.4 '<--| then format it
Else '<--| otherwise...
.Rows(iRow).Hidden = True '<--| hide it!
End If
Next
End With
End Sub
Sub ResetRange(rng As Range)
rng.EntireRow.Hidden = False
FormatRange rng, False, False, 0, xlColorIndexAutomatic, -4142, 0
End Sub
Sub FormatRange(rng As Range, okBold As Boolean, okItalic As Boolean, myFontTintAndShade As Single, myPatternColorIndex As XlColorIndex, myInteriorThemeColor As Variant, myInteriorTintAndShade As Single)
With rng
With .Font
.Bold = okBold
.Italic = okItalic
.TintAndShade = myFontTintAndShade
End With
With .Interior
.PatternColorIndex = myPatternColorIndex
.ThemeColor = myInteriorThemeColor
.TintAndShade = myInteriorTintAndShade
End With
End With
End Sub
I'd like to know if there's a way to do the following thing using VBA:
If the macro finds the word "Total" in the column B, then interior.color of the line where total is would be colored in Blue, and do it for all the "Total" words in the column B.
Note: I have different Totals... it's not only the word "Total"
LIKE THIS (i.e coloring from col A to F)
I tried with this but it's not working properly and the code is bad...
Sub forme_couleur()
Dim myRow As Integer
myRow = 1
While Not IsEmpty(Cells(myRow, 2))
If Cells(myRow, 2).Find(What:="Total") Is Nothing Then
myRow = myRow + 1
Else
Cells(myRow, 2).Find(What:="Total").Interior.Color = RGB(174, 240, 194)
End If
myRow = myRow + 1
Wend
End Sub
Consider:
Sub ColorMeBlue()
Dim i As Long, N As Long, s As String
N = Cells(Rows.Count, "B").End(xlUp).Row
s = "Total"
For i = 1 To N
If InStr(1, Cells(i, 2).Value, s) > 0 Then
Range("A" & i & ":F" & i).Interior.Color = RGB(174, 240, 194)
End If
Next i
End Sub
EDIT#1:
To refer to a range using columns by number, use:
Sub ColorMeBlue2()
Dim i As Long, N As Long, s As String
N = Cells(Rows.Count, "B").End(xlUp).Row
s = "Total"
Firstcol = 1
LastCol = 6
For i = 1 To N
If InStr(1, Cells(i, 2).Value, s) > 0 Then
Range(Cells(i, Firstcol), Cells(i, LastCol)).Interior.Color = RGB(174, 240, 194)
End If
Next i
End Sub
You can achieve this with conditional formatting, but if you must do it with VBA use something like the following:
Sub test()
For i = 1 To Cells(ActiveSheet.Rows.Count, "B").End(xlUp).Row
If InStr(1, Cells(i, 2), "Total") Then
With Cells(i, 2).EntireRow.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorLight2
.TintAndShade = 0.399975585192419
.PatternTintAndShade = 0
End With
End If
Next i
End Sub
Another Concept: You can go with the AutoFilter method. Using this method doesn't require any For loops, or any Ifs, just use all the cells that passes the AutoFilter criteria of ="*Total*" inside your Range.
Sub ColorMeBlue_Filter()
Dim i As Long, N As Long, s As String
Dim FirstCol As Long, LastCol As Long
Dim FiltRng As Range
N = Cells(Rows.Count, "B").End(xlUp).Row
s = "Total"
' (just for my testing)
'FirstCol = 1
'LastCol = 6
Range("A1").AutoFilter
Range(Cells(1, FirstCol), Cells(N, LastCol)).AutoFilter Field:=2, Criteria1:="=*Total*", _
Operator:=xlAnd
' set FiltRng to only visible cells (that passed the "Total" filter)
Set FiltRng = Range(Cells(2, FirstCol), Cells(N, LastCol)).SpecialCells(xlCellTypeVisible)
' modify interior color of all cells at once (one code line)
FiltRng.Interior.Color = RGB(174, 240, 194)
End Sub
You can do with a formula based conditional formatting, using the COUNTIF(a1:f1,"Total") function being >0
Using Range.Find avoids: looping through each row and the need to get the last row.
Instead of applying Range.Find to each row, just apply it to the entire column, no need to check if the cell is empty (see Range.Find Method (Excel) for additional details)
Voici votre code révisé:
Assuming your data is located at `A:F'
Sub forme_couleur()
Const kCriteria As String = "Total"
Dim rTrg As Range, s1stFound As String
With ThisWorkbook.Sheets("DATA").Columns(2) 'change as required
Set rTrg = .Cells.Find(What:=kCriteria, After:=.Cells(1), LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext)
If Not (rTrg Is Nothing) Then
s1stFound = rTrg.Address
Do
rTrg.EntireRow.Cells(1).Resize(1, 6).Interior.Color = RGB(224, 240, 248) 'RGB(174, 240, 194) give me a green color - changed as required
Set rTrg = .Cells.FindNext(After:=rTrg)
Loop Until rTrg.Address = s1stFound
End If: End With
End Sub
I've been trying to add the entire row that meets the highlight criteria to an array but I've been struggling getting it to work.
The code loops through multiple identifiers and highlight them in red based off of the preconditions. I would like to add the entire row to an array for all rows meeting the precondition criteria.
Sub SWAPS101()
'red color
' If "Security Type" = SW
' If "New Position Ind" = N
' If "Prior Price" = 100
' If "Current Price" does not equal 100
Dim rng As Range, lCount As Long, LastRow As Long
Dim cell As Object
'Sheets("Output").Activate
With ActiveSheet
LastRow = .Cells(Rows.Count, 1).End(xlUp).Row
For Each cell In .Range("E2:E" & LastRow) 'new position
If cell = "N" And cell.Offset(, 16) = "SW" And cell.Offset(, 5) = 100 _
And cell.Offset(, 4) <> 100 Then
With cell.EntireRow.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 6382079
.TintAndShade = 0
.PatternTintAndShade = 0
End With
' LastRow = Range("b65000").End(xlUp).Row
' For r = 2 To LastRow
Row = Row + 1
TempArray(Row, 1) = Cells(r, cell))
Next r
End If
Next cell
End With
End Sub
Using the Range.CurrentRegion property to isolate the 'island' of data radiating out from A1 is an easy method to restrict the 'scope' of the operation. You do not want to be copying thousands of blank cells into an array.
Sub SWAPS101()
'red color
' If "Security Type" = SW
' If "New Position Ind" = N
' If "Prior Price" = 100
' If "Current Price" does not equal 100
Dim a As Long, r As Long, c As Long, vVALs As Variant
With Sheets("Output")
'reset the environment
If .AutoFilterMode Then .AutoFilterMode = False
.Columns(5).Interior.Pattern = xlNone
With .Cells(1, 1).CurrentRegion
ReDim vVALs(1 To .Columns.Count, 1 To 1)
.AutoFilter field:=Application.Match("security type", .Rows(1), 0), Criteria1:="SW"
.AutoFilter field:=Application.Match("new position ind", .Rows(1), 0), Criteria1:="N"
.AutoFilter field:=Application.Match("prior price", .Rows(1), 0), Criteria1:=100
.AutoFilter field:=Application.Match("current price", .Rows(1), 0), Criteria1:="<>" & 100
With .Resize(.Rows.Count - 1, .Columns.Count).Offset(1, 0)
'check to ensure that there is something to work with
If CBool(Application.Subtotal(103, .Cells)) Then
With Intersect(.Columns(5), .SpecialCells(xlCellTypeVisible))
.Cells.Interior.Color = vbRed
End With
Debug.Print .SpecialCells(xlCellTypeVisible).Areas.Count
With .SpecialCells(xlCellTypeVisible)
For a = 1 To .Areas.Count
Debug.Print .Areas(a).Rows.Count
For r = 1 To .Areas(a).Rows.Count
Debug.Print .Areas(a).Rows(r).Address(0, 0)
ReDim Preserve vVALs(1 To UBound(vVALs, 1), 1 To UBound(vVALs, 2) + 1)
For c = 1 To .Columns.Count
vVALs(c, UBound(vVALs, 2)) = _
.Areas(a).Rows(r).Cells(1, c).Value
Next c
Next r
Next a
vVALs = Application.Transpose(vVALs)
End With
'array is populated - do something with it
Debug.Print LBound(vVALs, 1) & ":" & UBound(vVALs, 1)
Debug.Print LBound(vVALs, 2) & ":" & UBound(vVALs, 2)
'this dumps the values starting a couple of rows down
With .Cells(.Rows.Count, 1).Offset(3, 0)
.Resize(UBound(vVALs, 1), UBound(vVALs, 2)) = vVALs
End With
End If
End With
End With
If .AutoFilterMode Then .AutoFilterMode = False
End With
End Sub
I've left a lot of the debug.print statements in so you can watch how the process loops through the rows of each Range.Areas property within the Range.SpecialCells method's xlCellTypeVisible set. Use F8 to step through the code while keeping an eye on the VBE's Immediate window ([Ctrl]+G).
Post-processing results
You can add ranges to an array, such as:
Dim myArray() As Variant 'declare an unallocated array.
myArray = Range("E2:E" & LastRow) 'myArray is now an allocated array, range being your row
My idea is to create union range uRng but I couldn't fill it in array so create temp sheet and past this range in it then fill the selection (the copied range) in array then delete this temp sheet.
this will work but I don't know if it is good way so this is just an idea because Jeeped answer seems the full answer for this question
Sub SWAPS101()
'red color
' If "Security Type" = SW
' If "New Position Ind" = N
' If "Prior Price" = 100
' If "Current Price" does not equal 100
Dim rng As Range, lCount As Long, LastRow As Long
Dim cell As Range
Dim TempArray As Variant, uRng As Range, tempSH As Worksheet
'Sheets("Output").Activate
With ActiveSheet
LastRow = .Cells(Rows.Count, 1).End(xlUp).Row
For Each cell In .Range("E2:E" & LastRow) 'new position
If cell = "N" And cell.Offset(, 16) = "SW" And cell.Offset(, 5) = 100 _
And cell.Offset(, 4) <> 100 Then
With cell.EntireRow.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 6382079
.TintAndShade = 0
.PatternTintAndShade = 0
End With
If uRng Is Nothing Then
Set uRng = cell.EntireRow
Else
Set uRng = Union(uRng, cell.EntireRow)
End If
End If
Next cell
End With
If Not uRng Is Nothing Then
Application.ScreenUpdating = False
Set tempSH = Sheets.Add
uRng.Copy
tempSH.Paste
TempArray = Selection.Value
Application.DisplayAlerts = False
tempSH.Delete
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End If
End Sub
I think I have an issue with the order of my For IF and Next statements, I am trying to only highlight the row where all conditions are meet, instead when my code makes it to the highlighting part all rows are individually highlighted and the code seems to run quite slow, I believe I am performing too many iterations?
Sub SWAPS100()
Dim rng As Range, lCount As Long, LastRow As Long
Dim cell As Object
Sheets("Output").Activate
With ActiveSheet
LastRow = .Cells(Rows.Count, 1).End(xlUp).Row
For Each cell In .Range("E2:E" & LastRow) 'new position
If cell = "N" Then
Debug.Print
For Each cell1 In .Range("U2:U" & LastRow) 'Secuirty type
If cell1 = "SW" Then
For Each cell2 In .Range("J2:J" & LastRow) 'prior px
If cell2 = 100 Then
For Each cell3 In .Range("I2:I" & LastRow) 'current px
If cell3 <> 100 Then
'With cell.Interior
With cell.EntireRow.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 6382079
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End If
Next cell3
End If
Next cell2
End If
Next cell1
End If
Next cell
End With
As #Raystafarian commented as I was typing, use And in your if statment instead of all the loops:
Sub SWAPS100()
Dim rng As Range, lCount As Long, LastRow As Long
Dim cell As Object
Sheets("Output").Activate
With ActiveSheet
LastRow = .Cells(Rows.Count, 1).End(xlUp).Row
For Each cell In .Range("E2:E" & LastRow) 'new position
If cell = "N" And cell.Offset(, 16) = "SW" And cell.Offset(, 5) = 100 _
And cell.Offset(, 4) = 100 Then
With cell.EntireRow.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 6382079
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End If
Next cell
End With
With looping each row individually it will go slow and will most likely always justify. As long as you have one cell in each column that justifies the if statement then it will color all rows.
Also this can be done with Conditional Formatting with the following formula:
=AND($E2="N",$U2="SW",$J2=100,$I2=100)
While the aforementioned Conditional Formatting with a native worksheet formula is a better solution for 'on-the-fly' updates, a series of AutoFilter methods applied to the columns would be much faster than any procedure involving looping through the cells.
Sub SWAPS100()
Application.ScreenUpdating = False
With Sheets("Output")
If .AutoFilterMode Then .AutoFilterMode = False
With .Cells(1, 1).CurrentRegion
.AutoFilter Field:=5, Criteria1:="N"
.AutoFilter Field:=9, Criteria1:=100
.AutoFilter Field:=10, Criteria1:=100
.AutoFilter Field:=21, Criteria1:="SW"
With .Resize(.Rows.Count - 1, 1).Offset(1, 4)
If CBool(Application.Subtotal(103, .Cells)) Then
.Cells.EntireRow.Interior.Color = 6382079
End If
End With
End With
If .AutoFilterMode Then .AutoFilterMode = False
End With
Application.ScreenUpdating = True
End Sub
Hi, my sheet has 103 columns and 18550 rows of data which is coming from database. Based on B column cells value i have to apply formatting for the respective row like [if B2 value is 1 then for that row interior color should be Orange in color else if it is -1 then it should be in Blue else if it is 0 then the columns F & G should be Green in color and these green coloured cells should not be locked. And every 1 valued row and the immediate -1 valued rows should be grouped. Currently i have the following code which is almost taking 8 minutes of time to apply formattings.
With ThisWorkBook.Sheets("RoAe").Range("A1:A" & rowLen)
'=================For 1 valued Rows==========
Set C = .Find("1", LookIn:=xlValues)
x=0
If Not C Is Nothing Then
firstAddress = C.Address
Do
valR = Split(C.Address, "$")
actVal = valR(2)
ReDim Preserve HArray(x)
HArray(x) = actVal + 1
x = x + 1
With ThisWorkBook.Sheets("RoAe").Range("D" & actVal & ":FN" & actVal)
.Rows.AutoFit
.WrapText = True
.Font.Bold = True
.Interior.Color = RGB(252,213,180)
.Borders.Color = RGB(0, 0, 0)
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
End With
Set C = .FindNext(C)
Loop While Not C Is Nothing And C.Address <> firstAddress
End If
'=================For -1 valued Rows==========
Set C = .Find("-1", LookIn:=xlValues)
y=0
If Not C Is Nothing Then
firstAddress = C.Address
Do
valR = Split(C.Address, "$")
actVal = valR(2)
ReDim Preserve HArray(y)
FArray(y) = actVal + 1
y = y + 1
With ThisWorkBook.Sheets("RoAe").Range("D" & actVal & ":FN" & actVal)
.Rows.AutoFit
.WrapText = True
.Font.Bold = True
.Interior.Color = RGB(141,180,226)
.Borders.Color = RGB(0, 0, 0)
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
End With
Set C = .FindNext(C)
Loop While Not C Is Nothing And C.Address <> firstAddress
End If
'===================For 0(Zero) Valued Rows============
For p = 0 To UBound(HArray)
groupRange = "A" & HArray(p) & ":A" & FArray(p)
For i = 0 To UBound(arrUnlockMonthStart)
unlockRange = F & (HArray(p) + 1) & ":" & G & FArray(p)
ThisWorkBook.Sheets("RoAe").Range(unlockRange).Locked = False
ThisWorkBook.Sheets("RoAe").Range(unlockRange).Interior.Color = RGB(216,228,188)
Next
next
end with
ThisWorkBook.Sheets("RoAe").protect "12345"
Can we do the same with Conditional Formatting. Applying format & locking/unlocking for the rows based on cell value. Any help would be appreciated greatly.
As i mentioned that you cannot lock/unlock a cell in conditional formatting. You will have to first apply the conditional formatting and then lock/unlock the cells. Also you do not need to loop to apply conditional formatting. You can do that in one go.
Try this
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim lRow As Long, i As Long
Dim Rng As Range, unlockRng As Range
'~~> Set this to the relevant worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
'~~> Find the last row in Col B
lRow = .Range("B" & .Rows.Count).End(xlUp).Row
'~~> Set your range where CF will be applied for -1/1
Set Rng = .Range("D2:H" & lRow)
With Rng
.FormatConditions.Add Type:=xlExpression, Formula1:="=$B2=1"
.FormatConditions(1).SetFirstPriority
With .FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorAccent6
.TintAndShade = 0.399945066682943 '<~~ Orange
End With
.FormatConditions(1).StopIfTrue = True
.FormatConditions.Add Type:=xlExpression, Formula1:="=$B2=-1"
.FormatConditions(2).SetFirstPriority
With .FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorLight2
.TintAndShade = 0.599993896298105 '<~~ Blue
End With
.FormatConditions(1).StopIfTrue = True
End With
'~~> Set your range where CF will be applied for 0
Set Rng = .Range("F2:G" & lRow)
With Rng
.FormatConditions.Add Type:=xlExpression, Formula1:="=$B2=0"
.FormatConditions(3).SetFirstPriority
With .FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorAccent3
.TintAndShade = 0.399975585192419 '<~~ Green
End With
.FormatConditions(1).StopIfTrue = True
End With
'~~> Loop through cells in Col B to checl for 0 and store
'~~> relevant Col F and G in a range
For i = 2 To lRow
If .Range("B" & i).Value = 0 Then
If unlockRng Is Nothing Then
Set unlockRng = .Range("F" & i & ":G" & i)
Else
Set unlockRng = Union(unlockRng, .Range("F" & i & ":G" & i))
End If
End If
Next i
End With
'~~> unlock the range in one go
If Not unlockRng Is Nothing Then unlockRng.Locked = False
End Sub
ScreenShot
EDIT
For 103 Columns and 18550 Rows use this method. This is much faster than the above
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim lRow As Long, i As Long
Dim Rng As Range, unlockRng As Range
'~~> Set this to the relevant worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
Application.ScreenUpdating = False
With ws
'~~> Find the last row in Col B
lRow = .Range("B" & .Rows.Count).End(xlUp).Row
'~~> Set your range where CF will be applied for -1/1
'~~> Taking 103 Columns into account
Set Rng = .Range("D2:DB" & lRow)
With Rng
.Locked = True
.FormatConditions.Delete
.FormatConditions.Add Type:=xlExpression, Formula1:="=$B2=1"
.FormatConditions(1).SetFirstPriority
With .FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorAccent6
.TintAndShade = 0.399945066682943 '<~~ Orange
End With
.FormatConditions(1).StopIfTrue = True
.FormatConditions.Add Type:=xlExpression, Formula1:="=$B2=-1"
.FormatConditions(2).SetFirstPriority
With .FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorLight2
.TintAndShade = 0.599993896298105 '<~~ Blue
End With
.FormatConditions(1).StopIfTrue = True
End With
'~~> Set your range where CF will be applied for 0
Set Rng = .Range("F2:G" & lRow)
With Rng
.FormatConditions.Add Type:=xlExpression, Formula1:="=$B2=0"
.FormatConditions(3).SetFirstPriority
With .FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorAccent3
.TintAndShade = 0.399975585192419 '<~~ Green
End With
.FormatConditions(1).StopIfTrue = True
End With
'~~> Loop through cells in Col B to check for 0 and
'~~> unlock the relevant range
For i = 2 To lRow
If .Range("B" & i).Value = 0 Then
.Range("F" & i & ":G" & i).Locked = False
End If
Next i
End With
Application.ScreenUpdating = True
End Sub
As far as I know, the locking and grouping cannot be done with Conditional Formatting, the coloring however can be done.
You can color a cell based o a formula entered in conditional formatting dialog and this formula can contain relative, semi-relative and absolute references to other cells (using the $ notation as in any other formulas).
For example the "make row orange if column B = 1" can be done by setting condition formatting in cell D2 to formula =if($B1=1;TRUE;FALSE). If you put the $ in front of B as in this example, than you can apply the conditional formatting to the whole range columns D:H and it should color the lines as your script does.
Doing all the colors is just repeating the process and setting more conditional formating rules with different formulas.