How can highlight in yellow a cell that have a specific word in it?
I have data in colum B and F with the word "No Game".
How can I have this in a vba in excel?
Thanks
Although this question has already been answered, I'd take my chance, showing how easy this is using conditional formatting (screenshots are minimised a bit):
Result looks like this:
Good luck
Highlight Matches (For Each...Next)
Copy the complete code into a standard module, e.g. Module1.
Adjust (play with) the values in the constants section.
Option Explicit
Sub HighlightColumns()
' Needs the 'RefColumn' and 'RefCombinedRange' functions.
Const ProcTitle As String = "Highlight Columns"
Const wsName As String = "Sheet1"
Const FirstCellsList As String = "B2,H2"
Const hCriteria As String = "No Game"
Const hColor As Long = vbYellow
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim ws As Worksheet: Set ws = wb.Worksheets(wsName)
' Write the list of the first cells' addresses to an array ('FirstCells').
Dim FirstCells() As String: FirstCells = Split(FirstCellsList, ",")
Dim scrg As Range ' Source Column Range
Dim sfCell As Range ' Source First Cell
Dim sCell As Range ' Source Cell
Dim hrg As Range ' Highlight Range
Dim n As Long ' Columns Counter
' Combine all matching cells into the Highlight Range.
For n = 0 To UBound(FirstCells)
Set sfCell = ws.Range(FirstCells(n))
Set scrg = RefColumn(sfCell)
If Not scrg Is Nothing Then ' found data in column range
For Each sCell In scrg.Cells
If StrComp(CStr(sCell.Value), hCriteria, vbTextCompare) = 0 Then
Set hrg = RefCombinedRange(hrg, sCell)
'Else ' not a match
End If
Next sCell
Set scrg = Nothing
'Else ' no data in current column range
End If
Next n
' Highlight and inform.
If Not hrg Is Nothing Then ' Highlight Criteria found
hrg.Interior.Color = hColor
MsgBox "Highlighted cells equal to '" & hCriteria & "'.", _
vbInformation, ProcTitle
Else ' no Highlight Criteria found
MsgBox "No occurrences of '" & hCriteria & "' found.", _
vbExclamation, ProcTitle
End If
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Creates a reference to the one-column range from the first cell
' of a range ('FirstCell') to the bottom-most non-empty cell
' of the first cell's worksheet column.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function RefColumn( _
ByVal FirstCell As Range) _
As Range
If FirstCell Is Nothing Then Exit Function
With FirstCell.Cells(1)
Dim lCell As Range
Set lCell = .Resize(.Worksheet.Rows.Count - .Row + 1) _
.Find("*", , xlFormulas, , , xlPrevious)
If lCell Is Nothing Then Exit Function
Set RefColumn = .Resize(lCell.Row - .Row + 1)
End With
End Function
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Creates a reference to a range combined from two ranges.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function RefCombinedRange( _
ByVal CombinedRange As Range, _
ByVal AddRange As Range) _
As Range
If CombinedRange Is Nothing Then
Set RefCombinedRange = AddRange
Else
Set RefCombinedRange = Union(CombinedRange, AddRange)
End If
End Function
Related
This question already has an answer here:
Can the Excel VBA Range.Find method be used to find multiple values?
(1 answer)
Closed 1 year ago.
I have a find function that search through a column, and there might be more than one result. Which I would like to store in a range (instead of a separate array for example).
This is what I have:
Dim searchRange As Range
Set searchRange = ActiveWorkbook.Sheets(SHEET).Range(SEARCHFOLDERCOLUMN & SEARCHSTARTROW & ":" & SEARCHFOLDERCOLUMN & lastRow)
'search for value
Dim searchResult As Range
Dim firstAddress As String
Set searchResult = searchRange.Find(what:=sSearchFolder, LookIn:=xlValues, LookAt:=xlWhole, MatchCase:=False)
If Not searchResult Is Nothing The
firstAddress = searchResult.Address
Do
'search for the next one
Debug.Print searchResult.Address
Set searchResult = searchRange.FindNext(searchResult)
'^^^^^ union instead of this ???
'avoid endless loop, when hitting back the first address
If firstAddress = searchResult.Address Then
'Set searchResult = tempSearchResult
Exit Do
End If
Loop While Not searchResult Is Nothing
End If
Debug.Print "out of loop"
My output:
$M$125
$M$148
$M$161
out of loop
How can I get a range like: "$M$125, $M$148, $M$161" ? Where the columns (or rows?) or 3 instead of 1 like I have now.
Thanks for your help.
Reference a 'FindNext Multi Range'
Option Explicit
Sub DebugPrintCCRGtest()
' Needs 'DebugPrintCCRG', 'RefColumn' and 'RefCriteriaColumnRange'.
DebugPrintCCRG ""
DebugPrintCCRG "Yes"
DebugPrintCCRG "No"
DebugPrintCCRG "2"
' Example Results:
' A4,A8:A9,A17
' A2:A3,A7,A12:A14,A21
' A6,A15:A16,A18:A19
' A5,A10:A11,A20
End Sub
Sub DebugPrintCCRG( _
ByVal Criteria As String)
' Needs 'RefColumn' and 'RefCriteriaColumnRange'.
Dim sFirst As String: sFirst = "A2"
Dim ws As Worksheet: Set ws = ActiveSheet ' be more specific
Dim crg As Range: Set crg = RefColumn(ws.Range(sFirst))
If crg Is Nothing Then Exit Sub
Dim ccrg As Range: Set ccrg = RefCriteriaColumnRange(crg, Criteria)
If ccrg Is Nothing Then Exit Sub
Debug.Print ccrg.Address(0, 0)
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Creates a reference to the one-column range from the first cell
' of a range ('FirstCell') to the bottom-most non-empty cell
' of the first cell's worksheet column.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function RefColumn( _
ByVal FirstCell As Range) _
As Range
If FirstCell Is Nothing Then Exit Function
With FirstCell.Cells(1)
Dim lCell As Range
Set lCell = .Resize(.Worksheet.Rows.Count - .Row + 1) _
.Find("*", , xlFormulas, , , xlPrevious)
If lCell Is Nothing Then Exit Function
Set RefColumn = .Resize(lCell.Row - .Row + 1)
End With
End Function
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Creates a reference to the range combined from all the cells
' of a one-column range ('crg'), whose values are equal
' to a string ('Criteria').
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function RefCriteriaColumnRange( _
ByVal crg As Range, _
ByVal Criteria As String) _
As Range
If crg Is Nothing Then Exit Function
Dim cCell As Range: Set cCell = crg.Find(Criteria, _
crg.Cells(crg.Cells.Count), xlFormulas, xlWhole)
If cCell Is Nothing Then Exit Function
Dim drg As Range: Set drg = cCell
Dim FirstAddress As String: FirstAddress = cCell.Address
Do
Set drg = Union(drg, cCell)
Set cCell = crg.FindNext(cCell)
Loop Until cCell.Address = FirstAddress
If drg Is Nothing Then Exit Function
Set RefCriteriaColumnRange = drg
End Function
I'd like to know how to write this range changing "G" to a string variable strColumn.
This is the code I want to change:
Dim lastRowElemento As Integer
lastRowElemento = Cells(Rows.Count, "G").End(xlUp).Row
Set rngElemento = ws.Range("G2:G" & lastRowElemento)
Applying OP's method, try this:
Sub TEST()
Dim ws As Worksheet, Rng As Range, sCol As String
sCol = "G"
Set ws = ThisWorkbook.Sheets("TEST") 'change as required
With ws.Columns(sCol)
Set Rng = Range(.Cells(2), .Cells(.Rows.Count).End(xlUp))
End With
End Sub
Reference a 'Non-Empty' Column Range
There are actually two requirements:
ColumnString = G (I prefer string since e.g. XFD are letters)
FirstRow = 2
If you put them together, you get G2 (think one, instead of two variables).
Since using the Find method is more reliable than using the End property in finding the bottom-most (last) non-empty cell in a column, I used it to write the RefColumn function which in your case can be utilized in the following way:
Set rngElemento = RefColumn(ws.Range("G2"))
I'll leave it up to you if you're going to test if there is data (usually you know there is), but I prefer to keep at least a 'simplified' test in the code:
If rngElemento is Nothing Then Exit Sub ' no data
' Continue...
The Code
Option Explicit
Sub RefColumnTEST()
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim ws As Worksheet: Set ws = wb.Worksheets("Sheet1")
Dim rg As Range: Set rg = RefColumn(ws.Range("G2"))
If rg Is Nothing Then ' the range 'G2:G1048576' is empty
MsgBox "No data.", vbCritical
Else
MsgBox rg.Address(0, 0), vbInformation
End If
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Creates a reference to the one-column range from the first cell
' of a range ('FirstCell') to the bottom-most non-empty cell
' of the first cell's worksheet column.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function RefColumn( _
ByVal FirstCell As Range) _
As Range
If FirstCell Is Nothing Then Exit Function
With FirstCell.Cells(1)
Dim lCell As Range
Set lCell = .Resize(.Worksheet.Rows.Count - .Row + 1) _
.Find("*", , xlFormulas, , , xlPrevious)
If lCell Is Nothing Then Exit Function
Set RefColumn = .Resize(lCell.Row - .Row + 1)
End With
End Function
Meeting Your Requirements
Similarly to my preferred way, you could use the RefData function:
Function RefData( _
ByVal ws As Worksheet, _
ByVal ColumnIndex As Variant) _
As Range
On Error GoTo ClearError
With ws.Columns(ColumnIndex).Resize(ws.Rows.Count - 1).Offset(1)
Set RefData = _
.Resize(.Find("*", , xlFormulas, , , xlPrevious).Row - 1)
End With
ProcExit:
Exit Function
ClearError:
Resume ProcExit
End Function
which you can utilize in the following way:
Set rngElemento = RefData(ws, "G")
Set rngElemento = RefData(ws, 7)
' or:
Const strColumn As String = "G"
Set rngElemento = RefData(ws, strColumn)
The task I'm trying to accomplish is if Cells G21 to G27 have any text in them, then a vlookup formula will be pasted into the respective cell to the left of it
eg. Cell G31 has text so the formula =VLOOKUP(G31,Data!$P$2:$Q$110,2,FALSE) is in cell F31
This is the code I have so far, but I'm a beginner and I can't figure out how to insert the vlookup to automatically reference the cell next to it.
Private Sub Worksheet_Caps()
Dim SrchRng As Range, cel As Range
Set SrchRng = Range("G31:G27")
For Each cel In SrchRng
If cel.Value <> "" Then
cel.Offset(0, -1).Value= VLOOKUP(cel,Data!P2:Q110,2,FALSE)
End If
End Sub
VLookup vs Match
Both solutions will write values (not formulas) since you wrote "I originally wanted it to calculate in the VBA, but I couldn't figure that out!" in the comments.
A Quick Fix (Not Recommended)
Option Explicit
Sub Worksheet_Caps()
Dim SrchRng As Range: Set SrchRng = Range("G21:G27")
Dim LkpRng As Range: Set LkpRng = Worksheets("Data").Range("P2:Q110")
Dim SrchCell As Range
Dim MatchValue As Variant
For Each SrchCell In SrchRng.Cells
If Len(CStr(SrchCell.Value)) > 0 Then
MatchValue = Application.VLookup(SrchCell.Value, LkpRng, 2, False)
If Not IsError(MatchValue) Then
SrchCell.Offset(, -1).Value = MatchValue
'Else
'SrchCell.Offset(, -1).Value = Empty
End If
End If
Next SrchCell
End Sub
An Improvement
The following uses the more flexible Application.Match instead of any 'flavor' of VLookup.
Adjust (play with) the values in the constants section.
Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Performs a 'VLookup' using 'Application.Match'.
' Remarks: Uses the 'RefColumn' and 'GetRange' functions.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub WorksheetCaps()
On Error GoTo ClearError
' Source
Const sName As String = "Data" ' Worksheet Name
Const slFirst As String = "P2" ' First Lookup Cell Address
Const svCol As String = "Q" ' Value Column
' Destination
Const dName As String = "Sheet1" ' Worksheet Name
Const dlFirst As String = "G21" ' First Lookup Cell Address
Const dvCol As String = "F" ' Value Column
' Workbook
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
' Create a reference to the Source Lookup Range ('slrg').
Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
Dim slfCell As Range: Set slfCell = sws.Range(slFirst)
Dim slrg As Range: Set slrg = RefColumn(slfCell)
If slrg Is Nothing Then Exit Sub ' no data in source
' You can always use a static range instead of the previous 3 lines:
'Dim slrg As Range: Set slrg = sws.Range("P2:P110")
' Create a reference to the Destination Lookup Range ('dlrg').
Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
Dim dlfCell As Range: Set dlfCell = dws.Range(dlFirst)
Dim dlrg As Range: Set dlrg = RefColumn(dlfCell)
If dlrg Is Nothing Then Exit Sub ' no data in destination
' You can always use a static range instead of the previous 3 lines:
'Dim dlrg As Range: Set dlrg = dws.Range("G21:G27")
' Create a reference to the Source Value Range ('svrg').
Dim svrg As Range: Set svrg = slrg.EntireRow.Columns(svCol)
' Write the values from the Source Value Range
' to the Source Value Array ('svData').
Dim svData As Variant: svData = GetRange(svrg)
' Write the values from the Destination Lookup Range
' to the Destination Array ('dData').
Dim dData As Variant: dData = GetRange(dlrg)
' Declare additional variables.
Dim smrIndex As Variant ' Source Match Row Index
Dim dlValue As Variant ' Destination Lookup Value
Dim dr As Long ' Destination Row Counter
' Loop through the elements (rows) of the Destination Array.
For dr = 1 To UBound(dData, 1)
' Write the (lookup) value of the current element
' in the Destination Array to a variable ('dlValue').
dlValue = dData(dr, 1)
' Replace the (lookup) value of the current element
' in the Destination Array with 'Empty'.
dData(dr, 1) = Empty
If Not IsError(dlValue) Then ' not an error value
If Len(dlValue) > 0 Then ' not a blank
' Attempt to find a match of the current
' Destination Lookup value in the Source Lookup Range.
smrIndex = Application.Match(dlValue, slrg, 0)
If IsNumeric(smrIndex) Then ' a match (the first occurrence)
' Write the corresponding value (in the same row)
' of the Source Lookup Range in the Source Value Array
' to the current element in the Destination Array.
dData(dr, 1) = svData(smrIndex, 1)
'Else ' not a match (resulting in an error value)
End If
' Else ' a blank: Empty, ="", ',...
End If
' Else ' any error value
End If
Next dr
' Create a reference to the Destination Value Range ('dvrg').
Dim dvrg As Range: Set dvrg = dlrg.EntireRow.Columns(dvCol)
' Write the (modified) values from the Destination Array
' to the Destination Value Range (in one go).
dvrg.Value = dData
' Save the workbook.
wb.Save
' Inform the user.
MsgBox "The lookup has finished successfully.", _
vbInformation, "Worksheet Caps"
ProcExit:
Exit Sub
ClearError:
Debug.Print "Run-time error '" & Err.Number & "': " & Err.Description
Resume ProcExit
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Creates a reference to the one-column range from the first cell
' of a range ('FirstCell') to the bottom-most non-empty cell
' of the first cell's worksheet column.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function RefColumn( _
ByVal FirstCell As Range) _
As Range
If FirstCell Is Nothing Then Exit Function
With FirstCell.Cells(1)
Dim lCell As Range
Set lCell = .Resize(.Worksheet.Rows.Count - .Row + 1) _
.Find("*", , xlFormulas, , , xlPrevious)
If lCell Is Nothing Then Exit Function
Set RefColumn = .Resize(lCell.Row - .Row + 1)
End With
End Function
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Returns the values of a range ('rg') in a 2D one-based array.
' Remarks: If ˙rg` refers to a multi-range, only its first area
' is considered.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function GetRange( _
ByVal rg As Range) _
As Variant
If rg Is Nothing Then Exit Function
If rg.Rows.Count + rg.Columns.Count = 2 Then ' one cell
Dim Data As Variant: ReDim Data(1 To 1, 1 To 1): Data(1, 1) = rg.Value
GetRange = Data
Else ' multiple cells
GetRange = rg.Value
End If
End Function
Please, try the next way:
If you need to place a formula to calculate Vlookup, use the next way:
cel.Offset(0, -1).Formula2 = "=Vlookup(" & cel.Address & ",Data!P2:Q110,2,False)"
You you need to calculate Vlookup in VBA, use the next alternative:
cel.Offset(0, -1).Value = WorksheetFunction.VLookup(cel.Value, Sheets("Data").Range("P2:Q110"), 2, False)
Edited:
Your whole code should should be adapted, in order to also deal with the case of no any match of VLookup function:
Private Sub Worksheet_Caps()
Dim SrchRng As Range, cel As Range, VLKresult
On Error Resume Next 'for the case of no any matched cells
Set SrchRng = Range("G31:G27").SpecialCells(xlCellTypeConstants) 'the range without empty cells
On Error GoTo 0
If Not SrchRng Is Nothing Then
For Each cel In SrchRng
VLKresult = Application.VLookup(cel.Value, Sheets("Data").Range("P$2:Q$110"), 2, False)
If Not IsError(VLKresult) Then
cel.Offset(0, -1).Value = VLKresult
Else
cel.Offset(0, -1).Value = "N/A"
End If
Next
End If
End Sub
I want to find, and highlight cells that have a particular value.
In this example I'm searching for the number 2.
The code finds and highlights the cells with the number 2, but it also highlights cells with the number 22, and 23 because they contain the number 2.
'Find Search Values on Sheet and Highlight
Sub Find_And_Highlight()
Dim Searchfor As String
Dim FirstFound As String
Dim Lastcell As Range
Dim FoundCell As Range
Dim rng As Range
Dim myRange As Range
Set myRange = ActiveSheet.UsedRange
Set Lastcell = myRange.Cells(myRange.Cells.Count)
Searchfor = "2"
Set FoundCell = myRange.Find(what:=Searchfor, after:=Lastcell)
'Test to see if anything was found
If Not FoundCell Is Nothing Then
FirstFound = FoundCell.Address
Else
GoTo NothingFound
End If
Set rng = FoundCell
'Loop until cycled through all finds
Do Until FoundCell Is Nothing
'Find next cell with Searchfor value
Set FoundCell = myRange.FindNext(after:=FoundCell)
'Add found cell to rng range variable
Set rng = Union(rng, FoundCell)
'Test to see if cycled through to first found cell
If FoundCell.Address = FirstFound Then Exit Do
Loop
'Highlight cells that contain searchfor value
rng.Interior.ColorIndex = 34
Exit Sub
'Error Handler
NothingFound:
MsgBox "No values were found in this worksheet"
End Sub
Please look at the comment provided by #Craig which you need to implement. i.e. you need to modify the Foundcell line like below:
Set FoundCell = myRange.Find(what:=Searchfor, after:=Lastcell, lookat:=xlWhole)
Caution: This option modifies the user's search settings in Excel so in future make sure to uncheck below option in the Find box.
However, since you are changing the background color of the cells, you really do not need VBA for this purpose. You can use Conditional Formatting | Highlight Cells Rules | Equal To as shown below:
And then fill in the value as appropriate:
Outcome will appear like this:
Highlight Found Cells
Uncomment the Debug.Print lines in the FindAndHighlight procedure to better understand its behavior.
Option Explicit
Sub FindAndHighlight()
' You could use these constants ('ByVal') as arguments of this procedure,
' when you could call it with 'FindAndHighlight "2", 34' from yet another
' procedure.
Const SearchString As String = "2"
Const cIndex As Long = 34
If ActiveSheet Is Nothing Then Exit Sub ' if run from add-in
If TypeName(ActiveSheet) <> "Worksheet" Then Exit Sub ' if e.g. chart
'Debug.Print "Worksheet Name: " & ActiveSheet.Name
Dim srg As Range: Set srg = ActiveSheet.UsedRange
'Debug.Print "Source Range Address: " & srg.Address(0, 0)
Dim frg As Range: Set frg = refFindStringInRange(srg, SearchString)
If frg Is Nothing Then
MsgBox "No occurrence of '" & SearchString & "' found in range '" _
& srg.Address(0, 0) & "' of worksheet '" & srg.Worksheet.Name _
& "'.", vbCritical, "Nothing Found"
Exit Sub
End If
'Debug.Print "Found Range Address: " & frg.Address(0, 0)
HighLightRangeUsingColorIndex frg, cIndex
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Creates a reference to a range combined of all cells
' whose contents are equal to a string.
' Remarks: The search is case-insensitive ('MatchCase') and is performed
' by rows ('SearchOrder') ascending ('SearchDirection',
' ('FindNext')), starting with the first cell ('After')
' of each area of the range.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function refFindStringInRange( _
ByVal SearchRange As Range, _
ByVal SearchString As String) _
As Range
If SearchRange Is Nothing Then Exit Function
Dim frg As Range
Dim arg As Range
Dim lCell As Range
Dim fCell As Range
Dim FirstAddress As String
For Each arg In SearchRange.Areas
Set lCell = arg.Cells(arg.Rows.Count, arg.Columns.Count)
Set fCell = Nothing
' By modifying the parameters of the arguments of the 'Find' method
' you can change the behavior of the function in many ways.
Set fCell = arg.Find(SearchString, lCell, xlFormulas, xlWhole, xlByRows)
If Not fCell Is Nothing Then
FirstAddress = fCell.Address
Do
If frg Is Nothing Then
Set frg = fCell
Else
Set frg = Union(frg, fCell)
End If
Set fCell = arg.FindNext(After:=fCell)
Loop Until fCell.Address = FirstAddress
End If
Next arg
If Not frg Is Nothing Then
Set refFindStringInRange = frg
End If
End Function
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Highlights the cells of a range using a color index.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub HighLightRangeUsingColorIndex( _
ByVal rg As Range, _
ByVal cIndex As Long)
If rg Is Nothing Then Exit Sub
If cIndex < 1 Or cIndex > 56 Then Exit Sub
rg.Interior.ColorIndex = cIndex
End Sub
I am attempting to build a loop that searches through headers and finds a contained value, In this case, "Avg". If the value is found it will work down the column and apply a format based on a comparison to another column. I am trying to convert my cell variable in the For loop (Z) into a column address so I can use to control my ws.Cells() value in the next loop.
Any help is greatly appreciated, thanks!!!!
Sub foo()
Dim ws As Worksheet: Set ws = Sheets("Sheet1")
Dim Z As Range
lastRow = ws.Cells(ws.Rows.Count, "I").End(xlUp).Row
For Each Z In Range("I1:BM1").Cells
If InStr(1, Z.Value, "Avg") Then
For i = 2 To lastRow 'loop from row 2 to last
If ws.Cells(i, 8) - ws.Cells(i, Z) < 0 Then
ws.Cells(i, Z).Interior.ColorIndex = 4
End If
Next i
End If
Next Z
End Sub
It's not exactly clear to me what you want - but from the title it appears you want to get the column number based on the header text? If so, this will do that:
Private Function GetColumn(headerName As String) As Integer
Dim col As Integer
GetColumn = 0
For col = 1 To ActiveSheet.UsedRange.Columns.Count
If ActiveSheet.Cells(1, col).Value = headerName Then
GetColumn = col
Exit For
End If
Next col
End Function
Find Header and Format Cells
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: In a column range specified by its header,
' highlights the cells matching a condition.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub HighlightBelowAverages()
' Define constants.
Const PROC_TITLE As String = "Highlight Below-Averages"
Const COMPARE_COLUMN As String = "H"
Const AVG_SEARCH_COLUMNS As String = "I:BM"
Const AVG_COLUMN_HEADER As String = "Avg"
Const AVG_COLOR_INDEX As Long = 4 ' Bright Green
' Reference the Search range.
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim ws As Worksheet: Set ws = wb.Sheets("Sheet1")
Dim srg As Range
' It is NOT assumed that the used range starts in row '1'.
Set srg = Intersect(ws.UsedRange, ws.Range(AVG_SEARCH_COLUMNS))
If srg Is Nothing Then
MsgBox "The Average search columns '" & AVG_SEARCH_COLUMNS _
& "' are not part of the used range.", vbCritical, PROC_TITLE
Exit Sub
End If
' Find the Average header cell.
Dim ahCell As Range
With srg
Set ahCell = .Find(AVG_COLUMN_HEADER, _
.Cells(.Rows.Count, .Columns.Count), xlFormulas, xlWhole, xlByRows)
End With
If ahCell Is Nothing Then
MsgBox "Header '" & AVG_COLUMN_HEADER & "' not found.", _
vbCritical, PROC_TITLE
Exit Sub
End If
' Reference the Average (single-column) range.
Dim afCell As Range: Set afCell = ahCell.Offset(1)
Dim alCell As Range
Set alCell = Intersect(srg.Rows(srg.Rows.Count), ws.Columns(ahCell.Column))
' It IS assumed that the data has one row of headers.
If afCell.Row > alCell.Row Then
MsgBox "No data found.", vbCritical, PROC_TITLE
Exit Sub
End If
Dim arg As Range: Set arg = ws.Range(afCell, alCell)
' Reference the Compare (single-column) range.
Dim crg As Range
' It is NOT assumed that the used range starts in column 'A'.
Set crg = Intersect(arg.EntireRow, ws.Columns(COMPARE_COLUMN))
' Highlight the cells.
Application.ScreenUpdating = False
arg.Interior.ColorIndex = xlNone
Dim aCell As Range, cCell As Range, r As Long
For Each aCell In arg.Cells
r = r + 1
Set cCell = crg.Cells(r)
If cCell.Value < aCell.Value Then ' Compare is less than Average
aCell.Interior.ColorIndex = AVG_COLOR_INDEX
End If
Next aCell
Application.ScreenUpdating = True
' Inform.
MsgBox "Below-averages highlighted.", vbInformation, PROC_TITLE
End Sub