Find string, change color across all Excel Worksheets - excel

search entire Excel workbook for text string and highlight cell appears to be exactly what I need but I can't get it to work on my Excel workbook. I have hundreds of rows across 10 worksheets. All searched-for Strings (Packet 01, Packet 02, Packet 03, etc) would be in B:8 to row-end on worksheet(1) and B:7 to row-end on the other 9 worksheets (Worksheets are named and the InputBox result for the string would need to be case-sensitive). 45547221 indicates interior color change, but there would be too much color with all strings having cells in different colors, thus changing the string color would be better using font.color.index. Trying the 45547221 code as-is finds it skipping the Do/Loop While code when in step mode.
I would modify the code in 45547221 by adding at a minimum:
Dim myColor As Integer
myColor = InputBox("Enter Color Number (1-56)")
(Configured so I can enter up to 5 FindStrings and 5 ColorIndex numbers as Dim with InputBox(es))
In the Do/Loop While I would change .ColorIndex = myColor
I would like to get this code working as it seems to fit my needs - modified to find string instances across workbook and re-color string instead of cell interior colors and (2) get it to recognize the Do/Loop While code which it isn't now but would apply the ColorIndex number to each string.
Public Sub find_highlight()
'Put Option Explicit at the top of the module and
'Declare your variables.
Dim FindString As String
Dim wrkSht As Worksheet
Dim FoundCell As Range
Dim FirstAddress As String
Dim MyColor As Integer 'Added this
FindString = InputBox("Enter Search Word or Phrase")
MyColor = InputBox("Enter Color Number")
'Use For...Each to cycle through the Worksheets collection.
For Each wrkSht In ThisWorkbook.Worksheets
'Find the first instance on the sheet.
Set FoundCell = wrkSht.Cells.Find( _
What:=FindString, _
After:=wrkSht.Range("B1"), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
'Check it found something.
If Not FoundCell Is Nothing Then
'Save the first address as FIND loops around to the start
'when it can't find any more.
FirstAddress = FoundCell.Address
Do
With FoundCell.Font 'Changed this from Interior to Font
.ColorIndex = MyColor
'.Pattern = xlSolid
'.PatternColorIndex = xlAutomatic 'Deactivated this
End With
'Look for the next instance on the same sheet.
Set FoundCell = wrkSht.Cells.FindNext(FoundCell)
Loop While FoundCell.Address <> FirstAddress
End If
Next wrkSht
End Sub

EDIT: This worked for me on your sample data, using a partial match so you can enter (eg) "Packet 03" and still match.
I like to split out the "find all" function into a separate function: it makes the rest of the logic easier to follow.
Public Sub FindAndHighlight()
Dim FindString As String
Dim wrkSht As Worksheet
Dim FoundCells As Range, FoundCell As Range
Dim MyColor As Integer 'Added this
Dim rngSearch As Range, i As Long, rw As Long
FindString = InputBox("Enter Search Word or Phrase")
MyColor = InputBox("Enter Color Number")
'Cycle through the Worksheets
For i = 1 To ThisWorkbook.Worksheets.Count
Set wrkSht = ThisWorkbook.Worksheets(i)
rw = IIf(i = 1, 8, 7) '<<< Row to search on
' row 8 for sheet 1, then 7
'set the range to search
Set rngSearch = wrkSht.Range(wrkSht.Cells(rw, "B"), _
wrkSht.Cells(Rows.Count, "B").End(xlUp))
Set FoundCells = FindAll(rngSearch, FindString) '<< find all matches
If Not FoundCells Is Nothing Then
'got at least one match, cycle though and color
For Each FoundCell In FoundCells.Cells
FoundCell.Font.ColorIndex = CInt(MyColor)
Next FoundCell
End If
Next i
End Sub
'return a range containing all matching cells from rng
Public Function FindAll(rng As Range, val As String) As Range
Dim rv As Range, f As Range
Dim addr As String
'partial match...
Set f = rng.Find(what:=val, after:=rng.Cells(rng.Cells.CountLarge), _
LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=True) 'case-sensitive
If Not f Is Nothing Then addr = f.Address()
Do Until f Is Nothing
If rv Is Nothing Then
Set rv = f
Else
Set rv = Application.Union(rv, f)
End If
Set f = rng.FindNext(after:=f)
If f.Address() = addr Then Exit Do
Loop
Set FindAll = rv
End Function

Related

Finding a cell with a specific string in it and replacing the cell 2 columns to the right with a specific value

As the title states, I need to find all cells in a worksheet with a specific string in them and replace the cell 2 columns to the right with a specific value
Edit: this is what I have so far but no idea where to go from here
Sub t()
Dim searchCell As Range
Dim replaceCell As Range
With Sheets("Chainwire")
Set searchCell = .Cells.Find(what:="UFFT50")
Set replaceCell = searchCell.Offset(0, 2)
End With
End Sub
Any help is much appreciated
Try this:
Sub ReplaceItems()
Dim col, c, dest As Range
Set col = FindAll(Sheets("Chainwire").UsedRange, "UFFT50") 'get all matches
'loop matches and replace value 2 cells over
For Each c In col
c.Offset(0, 2).Value = "a specific value"
Next
End Sub
'search a Range for `val` and return all matches as a Collection
' of cells
Public Function FindAll(rng As Range, val As String) As Collection
Dim rv As New Collection, f As Range
Dim addr As String
'adjust Find() arguments to suit your need...
Set f = rng.Find(what:=val, after:=rng.Cells(rng.Cells.CountLarge), _
LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=True)
If Not f Is Nothing Then addr = f.Address() 'remember first cell found
Do Until f Is Nothing
rv.Add f
Set f = rng.FindNext(after:=f)
If f.Address() = addr Then Exit Do 'exit if we looped back to the first hit
Loop
Set FindAll = rv
End Function

Trying to reach address of cell with find method

I have 2 different sheet file on excel. I will try to find the equivalent of the date value I entered on the first page on the second page. I want to paste a block from the first cell, two cells to the right of the address of the value I found.
So I wrote a code block as below
Dim aranan As Date
Dim firstAddress As String
Dim adres As Range
Dim c As Range
Private Sub CommandButton2_Click()
aranan = Range("B1").Value
Range("B2:G6").Select
Selection.Copy
With Worksheets(3).Range("A1:A500")
Set adres = Range("A1:A100").Find(aranan, LookAt:=xlWhole, MatchCase:=True)
If Not adres Is Nothing Then
firstAddress = adres.Address
Do
ActiveSheet.Paste Destination:=Worksheets(2).Range("C1:H5")
Loop While Not adres Is Nothing
End If
End With
End Sub
But when debugging, I see that the value of my variable named "adres" is empty.
The variable with the name "aranan" holds the date name.
What is my mistakes?
The "find all matches" logic is complex enough that it should be placed in a separate method - that makes your core logic simpler to manage.
For example:
Private Sub CommandButton2_Click()
Dim dt As Date, col As Collection, c As Range
dt = Me.Range("B1").Value 'Me = the worksheet for this code module
Set col = FindAll(Worksheets(3).Range("A1:A500"), dt)
If col.Count > 0 Then
For Each c In col
Me.Range("B2:G6").Copy c.Offset(0, 2) 'two columns over
Next c
Else
MsgBox "No matches found"
End If
End Sub
'find all matches for `val` in a range, and return as a collection
Public Function FindAll(rng As Range, val) As Collection
Dim rv As New Collection, f As Range, addr As String
Set f = rng.Find(what:=val, after:=rng.Cells(rng.Cells.CountLarge), _
LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False)
If Not f Is Nothing Then addr = f.Address() 'first cell found
Do Until f Is Nothing
rv.Add f
Set f = rng.FindNext(after:=f)
If f.Address() = addr Then Exit Do 'exit if we've wrapped back to the start
Loop
Set FindAll = rv
End Function

How to locate the last row of cells in a range which matches using VBA?

There is one column in a table where names of factories are shown but I only need the data for a specific factory name(let's say factory "Australia").
My idea is to locate the first and last rows which match because the data for the same factory are always presented in a consecutive manner. In this way, I can get the range of cells which match up to my search.
Locating the first matched row position is quite easy but I get stuck in getting the last matched row position.
Here is the code regarding this section:
Sub Search()
Dim sh As Worksheet
Dim searchStr As String
Dim lastRow As Long, firstRow as Long
Dim tableRange As range
Set sh = Worksheets("Total order")
searchStr = "Australia"
Set tableRange = sh.range("B:B").Find(what:=searchStr, LookIn:=xlValues, lookat:=xlWhole)
firstRow = tableRange.Row
End Sub
An example of the table dealt with:
Refer to the Range from the Cell of the First to the Cell of the Last Occurrence of a String in a Column
A Side Note
The Range.Find method is kind of tricky. For example, you may not be aware that in your code the search starts from cell B2 (which is even preferable in this case), and using xlValues may result in undesired results if rows are hidden (probably not important).
Usage
Using the function, according to the screenshot, you could (after searchStr = "Australia") use:
Set tableRange = refRangeFirstLast(sh.Columns("B"), searchStr)
to refer to the range B4:B7, or use:
Set tableRange = refRangeFirstLast(sh.Columns("B"), searchStr).Offset(, -1).Resize(, 4)
to refer to the range A4:D7.
The Code
Function refRangeFirstLast( _
ByVal ColumnRange As Range, _
ByVal SearchString As String) _
As Range
If Not ColumnRange Is Nothing Then
With ColumnRange
Dim FirstCell As Range: Set FirstCell = _
.Find(SearchString, .Cells(.Cells.Count), xlFormulas, xlWhole)
If Not FirstCell Is Nothing Then
Dim LastCell As Range: Set LastCell = _
.Find(SearchString, , xlFormulas, xlWhole, , xlPrevious)
Set refRangeFirstLast = .Worksheet.Range(FirstCell, LastCell)
End If
End With
End If
End Function
Sub refRangeFirstLastTEST()
Const SearchString As String = "Australia"
Dim ColumnRange As Range
Set ColumnRange = ThisWorkbook.Worksheets("Total order").Columns("B")
Dim rg As Range: Set rg = refRangeFirstLast(ColumnRange, SearchString)
If Not rg Is Nothing Then
Debug.Print rg.Address
Else
MsgBox "The reference could not be created.", vbExclamation, "Fail?"
End If
End Sub

VBA Trying to check for a value in column and if there copy another cells value to a new column

I have a table of data in a sheet that i am looking to make some adjustments to. I have a single column called "S/R" which will have one of two values in it [Serving OR Returning]. If the value is serving i want to copy the value from a column called "1stServeX" to a new column i have added i called "Server 1st Serve X".
I have written the code below but am beginning to trip myself up and also cannot finish the last part. I am a novice and so have been using other pieces of code i have gained previously to try and piece it together, which is why i need some help.
If i can get this going then i can simply repeat it for all the "Returner" option and all the other columns i need to split too.
Thanks in advance for any help offered.
Public Sub splitServerCoordinates()
'Set a constant for the title of the Server Column
Const HEADER_SR As String = "S/R"
Dim ws As Worksheet
Set ws = Sheets("transition")
Dim strSearch As String
Dim aCell As Range
Dim COL_SR As Long
Dim COL_TARGET As Long
Dim COL_CURRENT As Long
'Find the Column Numbers of the columns we are looking for
strSearch = "S/R"
Set aCell = ws.Rows(1).Find(What:=strSearch, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
COL_SR = aCell.Column
End If
strSearch = "1stServeX"
Set aCell = ws.Rows(1).Find(What:=strSearch, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
COL_CURRENT = aCell.Column
End If
strSearch = "Server 1st Serve X"
Set aCell = ws.Rows(1).Find(What:=strSearch, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
COL_TARGET = aCell.Column
End If
Dim theUsedRange As Range
Dim SRRange As Range
Dim aPlayer As Range
Dim serving As String
Dim returning As String
Dim theCounter As Long
Dim theSequence As Long
ws.Select
' clear out the Target column and add the header again
Set theUsedRange = ActiveSheet.UsedRange
Intersect(theUsedRange, Range(Columns(COL_TARGET), Columns(COL_TARGET))).ClearContents
Columns(COL_SR).Range("A1").Value = HEADER_SR
' reset the used range just in case
Set theUsedRange = ActiveSheet.UsedRange
' Get the used range for the S/R column
Set SRRange = Intersect(theUsedRange, Columns(COL_SR))
'Set value to compare to
serving = "Serving"
' Loop through the S/R column
For Each aPlayer In SRRange
' ignore the header row
If aPlayer <> HEADER_SR Then
' if we are serving then copy the value from COL_CURRENT to COL_TARGET
If aPlayer = serving Then
aPlayer.Offset(-1, COL_TARGET - COL_).Value = STUCK - HERE
End If
End If
Next aPlayer
End Sub
Some refactoring to pull out the column header location parts, and a few other tweaks. Untested, but should get you there.
Public Sub splitServerCoordinates()
Dim ws As Worksheet, c As Range
Dim COL_SR As Long
Dim COL_TARGET As Long
Dim COL_CURRENT As Long
Set ws = Sheets("transition")
'Find the Column Numbers of the columns we are looking for
COL_SR = HeaderColumnNumber(ws.Rows(1), "S/R")
COL_CURRENT = HeaderColumnNumber(ws.Rows(1), "1stServeX")
COL_TARGET = HeaderColumnNumber(ws.Rows(1), "Server 1st Serve X", True) 'add if not found
'exit if missing any required columns
If COL_SR = 0 Or COL_CURRENT = 0 Then
MsgBox "Missing 'S/R' and/or '1stServeX' !"
Exit Sub
End If
'reset target column
ws.Columns(COL_TARGET).ClearContents
ws.Cells(1, COL_TARGET).Value = "Server 1st Serve X"
'loop rows
For Each c In ws.Range(ws.Cells(2, COL_SR), ws.Cells(ws.Rows.Count, COL_SR).End(xlUp)).Cells
If c.Value = "Serving" Then
ws.Cells(c.Row, COL_TARGET).Value = ws.Cells(c.Row, COL_CURRENT).Value
End If
Next c
End Sub
'Find a header position on a row, with option to add it if not found
' Returns zero if header is not found and option to add was not set
Function HeaderColumnNumber(rng As Range, hdr As String, _
Optional AddIfMissing As Boolean = False) As Long
Dim f As Range
Set rng = rng.Cells(1).EntireRow 'only want a full row to look in
Set f = rng.Find(What:=hdr, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
If Not f Is Nothing Then
HeaderColumnNumber = f.Column 'found: return column
Else
'not found: do we add it, or return zero?
If AddIfMissing Then
With rng.Cells(rng.Cells.Count).End(xlToLeft).Offset(0, 1)
.Value = hdr
HeaderColumnNumber = .Column
End With
Else
HeaderColumnNumber = 0
End If
End If
End Function

Find cell(s) with certain text and add hyperlinks in a loop

tldr: Find cell(s) with part number xxxxx and add hyperlink to drawing on server.
We have a spreadsheet containing part numbers across multiple columns & rows. Our requirement is to add a hyperlink to parts' drawing, stored on our server. We have tried highlighting them as a group, but get the error
this can't be done on multiple range selection
We also want to keep the comment information intact, just to complicate it further.
Is there code we can use to search for part number xxxxx & add a hyperlink, then find the next cell and repeat the process?
We have found a "find all" code which highlights the cells, just need some help with the hyperlink issue.
Sub FindAll()
Dim fnd As String, FirstFound As String
Dim FoundCell As Range, rng As Range
Dim myRange As Range, LastCell As Range
'What value do you want to find (must be in string form)?
fnd = "70005"
Set myRange = ActiveSheet.UsedRange
Set LastCell = myRange.Cells(myRange.Cells.Count)
Set FoundCell = myRange.Find(what:=fnd, 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 unique finds
Do Until FoundCell Is Nothing
'Find next cell with fnd 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
'Select Cells Containing Find Value
rng.Select
Exit Sub
'Error Handler
NothingFound:
MsgBox "No values were found in this worksheet"
End Sub
Your method can be simplified a bit. My suggestion is to create a function that will add your hyperlinks to any given area.
My test data is
Option Explicit
Sub test()
Dim linkCount As Long
linkCount = AddHyperLinkTo(FindArea:=Sheet1.UsedRange, _
FindThis:="red", _
Link:="https://google.com")
Debug.Print "found: " & linkCount
End Sub
Function AddHyperLinkTo(ByRef FindArea As Range, _
ByVal FindThis As Variant, _
ByVal Link As String) As Long
Dim numberFound As Long
Dim parentWS As Worksheet
Set parentWS = FindArea.Parent
Dim firstFind As Range
Dim findResult As Range
Set findResult = FindArea.Find(What:=FindThis, LookIn:=xlValues)
Set firstFind = findResult
Do Until findResult Is Nothing
parentWS.Hyperlinks.Add Anchor:=findResult, Address:=Link
numberFound = numberFound + 1
Set findResult = FindArea.Find(What:=FindThis, LookIn:=xlValues, After:=findResult)
If findResult.Address = firstFind.Address Then
Exit Do
End If
Loop
AddHyperLinkTo = numberFound
End Function

Resources