Excel macro search ends in error when nothing found - excel

My Case 1 excel macro code runs as long as data is being found by the search but bombs with the stated error when there is nothing in the search result. So I tried putting in a "set" see Case 2... but that Case bombs on any search.
CASE 1: Run-time error '91': Object variable or With block variable not set
Cells.Find(What:=sCurrentISOtext & "_", After:=ActiveCell, _
LookIn:=xlFormulas, LookAt :=xlWhole , _
SearchOrder:=xlByColumns, SearchDirection:=xlNext, _
MatchCase:= False, SearchFormat:=False).Activate
CASE 2: Run-time error '424': Object required
Dim c As Range
Set c = Cells.Find(What:=sCurrentISOtext & "_", After:=ActiveCell, _
LookIn:=xlFormulas, LookAt :=xlWhole, _
SearchOrder:=xlByColumns, SearchDirection:=xlNext, _
MatchCase:= False, SearchFormat:=False).Activate
You mean like this?? It still fails.
CASE 3: Run-time error '91': Object variable or With block variable not set
Dim c As Range
c = Cells.Find(What:=sCurrentISOtext & "_", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlWhole = 0, SearchOrder:=xlByColumns, SearchDirection:=xlNext, MatchCase _
:=False, SearchFormat:=False)
If Not c Is Nothing Then
c.Activate
' and do something here < >
End If

This would naturally fail, you are calling "activate" on a null (failed) result - so there's nothing to activate at runtime. You have to wrap in an If statement -
Dim c As Range
Set c = Cells.Find(What:=sCurrentISOtext & "_", _
After:=ActiveCell, _
LookIn:=xlFormulas, _
LookAt:=xlWhole = 0, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlNext, _
MatchCase:= False, _
SearchFormat:=False)
If c Is Nothing Then
'do something
Else
c.Activate
End If

Here's an ugly work around that I use when I'm in a hurry -- there are more elegant error traps, but this gets it done.
On Error GoTo notFound
Dim c As Range
Set c = Cells.Find(What:=sCurrentISOtext & "_", _
After:=ActiveCell, _
LookIn:=xlFormulas, _
LookAt:=xlWhole = 0, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False)
c.Activate
Exit Sub
notFound:
Application.InputBox "Could not find the range you wanted."
' >> You can put in whatever action you want here -- for example, <<
' >> if you're using this as a module, then "Exit Sub" or "Goto nextOne" <<
' >> could be used go to the next step in your process. <<

Related

How to get resolve Run time error 13 in my code for find and delete entire row in excel

I am trying to write a VBA Script to delete a row which is selected from a dropdown list.
My code is
Sub delete_md_entry()
Dim LR As Long
Dim str As Range, rfnd As Range
'LR = Sheets("MASTER_DATA").Range("C2000").End(xlUp).Row
str = Sheets("MASTER_DATA").Range("I2").Value
If Len(str) <> 0 Then
Set rfnd = Selection.Find(str, After:=Range("C5"), LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByColumns, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not rfnd Is Nothing Then
yes = MsgBox("Do you want to delete" & rfnd.Value & " row?", vbYesNo, "Alert!")
If yes = vbYes Then
rfnd.EntireRow.Delete
Else
Exit Sub
End If
Else
MsgBox "NO ROW FOUND"
End If
Else
MsgBox "Kindly select a name!"
End If
End Sub
Unfortunately it is not working and throw an error Run time error 13: Type mismatch.
However there is not with selection.
Where I made the mistake? Please help me to find out the error!
Find works on a Range and not on a single cell Selection.
You need to change
Set rfnd = Selection.Find(str, After:=Range("C5"), LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByColumns, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
To:
Set rfnd = Range("A2:C10").Find(str, After:=Range("C5"), LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByColumns, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
Of course you need to change Range("A2:C10") above to whatever the range it is you are looking in.

Catch .find errors in Excel when 'What' is not found

I've got a Excel VBA function that's been working for quite some time. However I found that when i doesn't exist in this code:
Dim rowNum as Integer
for i = 1 to 20
rowNum = Columns(SiteNumCol).Find(What:=i, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).row
<other stuff>
Next i
An error is returned. I tried refactoring the code to include a check:
rowNum = Columns(SiteNumCol).Find(What:=i, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).row
If Not rowNum = 0 Then
<other stuff>
End If
Next i
However it still errored out at the rownum = line. I thought it might be as I'm calling the row number of nothing, so tried this test:
test = Columns(NumCol).Find(What:=i, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not test Is Nothing Then
rowNum = Columns(NumCol).Find(What:=i, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).row
It now errors out at the If statement with a 424 "Object required" error; I think this is because 'test' is currently a double as it errors out on the first iteration. If I change the test to = "0" it goes through iterations until the one that isn't found and then it fails because at test = because of good ol' 91 "Object Variable not set"
How can I successfully catch .find errors when the What is not found?
Like so. You were pretty close, just missing the Set I think.
Dim r As Range
Dim rowNum As Long
For i = 1 To 20
Set r = Columns(SiteNumCol).Find(What:=i, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not r Is Nothing Then rowNum = r.Row
<other stuff>
Next i

searching for multiple occurrence of a text and changing another text in vba

I am pretty new at vba. I am searching for a string in excel can also be multiple occurrence and then for each occurrence changing another text if this string is found. but my code is going into infinite loop. How can i achieve that? Here is my code:
Private Sub PRODA_Replace_IfNDM_Click()
Dim FindWord As String, Found As Range
Dim firstAddress As String
Dim rslt As Range
FindWord = "/*_NDM*"
Set Found = Sheets("PRODA").Cells.Find(What:=FindWord, _
LookIn:=xlValues, _
lookAt:=xlPart, _
searchOrder:=xlByRows, _
searchDirection:=xlNext, _
MatchCase:=False)
If Not Found Is Nothing Then
firstAddress = Found.Address
Do
Set rslt = Sheets("PRODA").Cells.Find(What:="OWNER:*", _
After:=Found, _
LookIn:=xlValues, _
lookAt:=xlPart, _
searchOrder:=xlByRows, _
searchDirection:=xlNext, _
MatchCase:=False)
Sheets("PRODA").Cells.Replace What:=rslt, _
Replacement:="OWNER:chrndm", _
lookAt:=xlPart, _
searchOrder:=xlByRows, _
MatchCase:=False, _
searchFormat:=False, _
ReplaceFormat:=False
MsgBox Found
If Found Is Nothing Then
GoTo endFinding
End If
Set Found = Cells.FindNext(After:=Found)
Loop While Not Found Is Nothing And firstAddress <> Found.Address
End If
endFinding:
MsgBox "changed successfully"
End Sub
Assuming that, for every occurrence of the findword string, the next occurrence of "OWNER:*" is the one to be changed, the following code will hopefully work:
Private Sub PRODA_Replace_IfNDM_Click()
Dim FindWord As String, Found As Range
Dim ownerCell As Range
Dim firstAddress As String
Dim rslt As Range
FindWord = "/*_NDM*"
With Sheets("PRODA")
Set Found = .Cells.Find(What:=FindWord, _
LookIn:=xlValues, _
lookAt:=xlPart, _
searchOrder:=xlByRows, _
searchDirection:=xlNext, _
MatchCase:=False)
If Not Found Is Nothing Then
firstAddress = Found.Address
Do
Set ownerCell = .Cells.Find(What:="OWNER:*", _
After:=Found, _
LookIn:=xlValues, _
lookAt:=xlPart, _
searchOrder:=xlByRows, _
searchDirection:=xlNext, _
MatchCase:=False)
If ownerCell Is Nothing Then
MsgBox "No corresponding owner for word found at " & Found.Address
Exit Sub
End If
ownerCell.Value = "OWNER:chrndm"
'Can't do FindNext, because we did a different Find
Set Found = .Cells.Find(What:=FindWord, _
After:=Found, _
LookIn:=xlValues, _
lookAt:=xlPart, _
searchOrder:=xlByRows, _
searchDirection:=xlNext, _
MatchCase:=False)
If Found.Address = firstAddress Then
Exit Do
End If
Loop
MsgBox "changed successfully"
End If
End With
End Sub
I've tested with some dummy data which hopefully replicates what you are doing.

Excel VBA Return the found row

Right now I have this:
Range("B20:B60000").Select
Selection.Find(What:=currentPerson, After:=ActiveCell, LookIn:= _
xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:= _
xlNext, MatchCase:=False, SearchFormat:=False).Activate
Which selects a certain range of cells and finds for currentPerson (variable containing a person's name). How do I make it so that I can now use his cell as a reference and get the row above him?
You can use following code:
Dim res As Range
Set res = Range("B20:B60000").Find(What:=currentPerson, LookIn:= _
xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:= _
xlNext, MatchCase:=False, SearchFormat:=False)
If Not res Is Nothing Then
MsgBox "Address: " & res.Address
MsgBox "Row: " & res.Row
MsgBox "Cell above: " & Cells(res.Row - 1, res.Column).Address
MsgBox "Entire row above: " & Cells(res.Row - 1, res.Column).EntireRow.Address
Else
MsgBox "Nothing found"
End If

Selecting the second result of a "Find" with VBA

I am trying to make it so that I can find the second result for "lights", in case of having various occurrences for this term. The code below finds the first occurrence in the range under consideration.
Dim ws As Worksheet
Dim rng1 As Range
Dim y As Range
Columns("B:B").Select
Selection.Find(What:="1", After:=ActiveCell, LookIn:=xlValues, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False _
, SearchFormat:=False).Select
Set x = Range(Selection, Selection.End(xlDown)).Offset(0, 3)
Range(x.Address(0, 0)).Select
Selection.Find(What:="Lights", After:=ActiveCell, LookIn:=xlValues, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False _
, SearchFormat:=False).Activate
Selection.FindNext(After:=ActiveCell).Activate
Selection.FindNext(After:=ActiveCell).Select
FindNext delivers what you want. Using it is easy: perform the first search as you are doing it right now (although by assigning the result to a Range) and take the resulting range as starting point for FindNext. Here you have a sample code adapted to your specific requirements (secondAddress is the Address of the second occurrence of "Light", if any):
Dim foundRange As Range
Dim rangeToSearch As Range
Set rangeToSearch = Selection
Set foundRange = rangeToSearch.Find(What:="Lights", After:=ActiveCell, LookIn:=xlValues, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False _
, SearchFormat:=False) 'First Occurrence
Dim secondAddress As String
If (Not foundRange Is Nothing) Then
foundRange.Activate
Dim count As Integer: count = 0
Dim targetOccurrence As Integer: targetOccurrence = 2
Dim found As Boolean
Do While Not found
Set foundRange = rangeToSearch.FindNext(foundRange)
If Not foundRange Is Nothing Then
count = count + 1
If (count >= targetOccurrence - 1) Then
secondAddress = foundRange.Address
Exit Do
End If
Else
Exit Do
End If
Loop
End If
I found an even easier way as it sounds like I had a similar problem.
If you simplified your search function:
Cells.Find(What:="xxxx", After:=Cells(1, 1), LookIn:=xlValues, _
LookAt:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Select
Then add another line beneath:
Cells.Find(What:="xxxx", After:=ActiveCell, _
LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByColumns, _
SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False).Select
All this does is find the first occurrence of "xxxx", then the second code finds "xxxx", but begins searching from the result of the first find code (which was the ActiveCell).

Resources