Excel-VBA Range.Find method error handling - vba

I'm using the range.find method to locate a cell with specific value in the first row. When there's a match, the code works fine. When there's no match, the code throws error as shown in screenshot below.
Is it normal that we need error handling for this method? I thought it'd just return Null or Nothing. Thank you for your help!

Use this. if you directly wanted to return column number of an empty range, it will show error.
Sub findtest()
dim c as long
dim rng as range
Set rng = ActiveSheet.Rows("1:1").Find(What:="John Smith", _
After:=ActiveCell, LookIn:=xlValues, _
LookAt:=xlPart, SearchOrder:=xlByColumns, _
SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not rng Is Nothing Then c = rng.column : Debug.Print c
end sub

Related

Need explanation: vba find method troubleshooting

I am using Find method to bring the cell value from another workbook.
The code below brings the value. But I wanted to erase Activate methods, so just using Block Statements with Find method to bring values from another workbook.
'Windows(wb_name).Activate
'Sheets("SheetA").Select
'Set rg =Worksheets("SheetA").Range("C:C")
'With rg
'value1 = Cells.Find(What:="11693", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False,
SearchFormat:=False).Value
'End With
For clarifying, what exactly I want; in values1 = Cells.Find ...I changed Cells to rg but it doesnt work. I want to know why? Also I see it unnecessary to use activate . I want to write a code where I will get rid of Activate another workbook. So, just by giving source wb and ws names and range to look for the value
Try the next way, please:
Sub FindInOtherSheet()
Dim Value1 As String, rg As Range
Set rg = Workbooks("W1.xlsx").Worksheets("SheetA").Range("C:C")
With rg
Value1 = .cells.Find(What:="11693", After:=.cells(1, 1), LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, _
SearchFormat:=False).value
End With
End Sub
It starts searching after the first cell of the range. ActiveCell does not have sense in a not activated sheet...
Edited:
As an example to clarify your question about the Find "problem" of not returning any error in case of no any match, I would state that this should be considered an advantage.
You can simple check if the function returned a range in this simple way (I will use the above code to exemplify):
Sub FindInOtherSheet()
Dim Value1 As String, rg As Range, fndCell as Range
Set rg = Workbooks("W1.xlsx").Worksheets("SheetA").Range("C:C")
With rg
set fndCell = .cells.Find(What:="11693", After:=.cells(1, 1), LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, _
SearchFormat:=False)
'check if Find returned a range:
If not fndCell is Nothing Then 'if a match has been found
Value1 = fndCell.value
Else
MsgBox "No match has been found...": Exit Sub
End If
End With
End Sub

Trying to select a cell with a variable as a column number

I'm trying to set up a code that will find a cell using the find function and then select a different cell in that column. I store the column number as a variable, and then try to move to a cell in the same column using the variable, but its not working.
I've tried changing it so that the column is stored as a string instead of an integer and tried using the .Cells method instead, neither have worked.
Dim numCol As String
Cells.Find(what:="e", After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=
_
False, SearchFormat:=False).Activate
numCol = ActiveCell.Column
Range(numCol & "4").Select
Getting a 1004 "method range of object global failed" error from that last line of code.
Here's some modified code from your query that might be useful. You want to try to use the properties of the range. In the below example I've defined a range that is the found cell fcell. A couple examples of what you can do ar there.
Dim numCol As Long
Dim fcell As Range
'this will find the cell and set it as a variable of fcell
Set fcell = Cells.Find(what:="e", After:=ActiveCell, LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
'you can select it
fcell.Select
'you can select the whole column
fcell.EntireColumn.Select
'you can select the column number (if one column)
numCol = fcell.Column
'you can return the address
MsgBox "the address is " & fcell.Address
Good luck.

VBA Do (delete column where find is true) Until Find is False then exit do

I have an excel file that has the text "Income from Trans" where I will need to delete the entire column.
This is my current code in VBA 2010 that works until there are no more cells with "Income from Trans"; I can't get it to break out of the loop.
Any idea why?
Dim rng1 As Range
Dim target1 As String
target1 = "Income From Trans"
Set rng1 = Cells.Find(What:=target1, _
After:=ActiveCell, _
LookIn:=xlFormulas, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
Do Until rng1 Is Nothing
Cells.Find(What:=target1, After:=ActiveCell, _
LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows,
SearchDirection _
:=xlNext, MatchCase:=False, SearchFormat:=False).Activate
ActiveCell.EntireColumn.Delete
Loop
Your code Set rng1 = Cells.Find... will set rng1 to be a range object, assuming it finds your value. Next is your loop which will ultimately cause rng1 to be deleted. It continues to loop because even though rng1 is deleted it still was assigned and therefore isn't Nothing. It ends with an run time error message of 91 because rng1 was set but deleted. You can see in the locals window View>Locals Window that its type is still Range\Range even though it's actually been deleted.
You have implicit cell references from the unqualified Cells usage. That means this code will run on whatever worksheet happens to be the ActiveSheet. Implicit references can have unintended side effects when you don't realize this. It's best to fully qualify them so there's no ambiguity as to which sheet they reside on. I'm assuming ActiveCell falls into this category too since you want it to wrap delete until there "Income from Trans" is no longer found.
The code .Activate followed by ActiveCell. isn't needed and can be shortened by removing both so it ends up as SearchFormat:=False).EntireColum.... Selecting a range object isn't usually necessary. Joining the two makes it apparent what you're doing.
Below you'll find a simpler version that uses .Find is in your original to find the first instance. After that it uses .FindNext() to continue looping until all are found. This eventually exits because it is setting the range variable found after every deletion, ultimately leaving found as Nothing after it's deleted the last. The RemoveColumns has parameters which allow you to use this on more than just a single sheet.
Sub Test()
RemoveColumns Sheet1, "Income From Trans"
End Sub
Sub RemoveColumns(ByVal sheetToSearch As Worksheet, ByVal value As String)
Dim found As Range
Set found = sheetToSearch.Cells.Find(What:=value, After:=sheetToSearch.Range("A1"), LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False)
Do Until found Is Nothing
found.EntireColumn.Delete
Set found = sheetToSearch.Cells.FindNext
Loop
End Sub
Check the search result inside the loop as well
Dim rng1 As Range, target1 As String, firstFound As String
target1 = "Income From Trans"
Set rng1 = Cells.Find(What:=target1, After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False)
If Not rng1 Is Nothing Then
Do
firstFound = rng1.Address
Set rng1 = Cells.Find(What:=target1, After:=ActiveCell, LookIn:=xlValues, _
LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False, _
SearchFormat:=False)
If Not rng1 Is Nothing Then rng1.EntireColumn.Delete
Loop While Not rng1 Is Nothing And rng1.Address <> firstFound
End If

Find all matched cell value in a range

I created a macro which finds all matched values of a cell in a range. The user enter for example numb in the cell A2 Then every time he clicks on Find button it will show him the matched cell for example Order Number then purchase number then part number ...
Here is my code
Sub find_matched_cells()
w = ActiveWorkbook.Sheets("Sheet4").Range("A2")
ActiveWorkbook.Sheets("Sheet4").Range("A4:A104").Find(What:=(w), After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False).Activate
End Sub
It works fine but when the user for example press on a cell not in my range then on the button find will not work. The issue is in
After:=ActiveCell
For example if by mistake you selected a cell in a range not in A4:A104 then the ActiveCell will not be in my range and it will give an error.
I need to add condition for example the first ActiveCell Starts from A4 and if I find the first matched cell then ActiveCell will take that value.
Any other suggestions please? Thank you very much.
One approach is this...
Sub find_matched_cells()
Dim Rng As Range
Set Rng = ActiveWorkbook.Sheets("Sheet4").Range("A4:A104")
w = ActiveWorkbook.Sheets("Sheet4").Range("A2")
If Intersect(ActiveCell, Rng) Is Nothing Then Range("A4").Select
Rng.Find(What:=(w), After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False).Activate
End Sub
You could check the intersection. I would re-write the code slightly depending on what you need to actually do to each of these found cells - is it just select them? I have amended code below to avoid error if the value is not found.
Sub x()
Dim rFind As Range, sAddr As String, w
w = ActiveWorkbook.Sheets("Sheet4").Range("A2")
With ActiveWorkbook.Sheets("Sheet4").Range("A4:A104")
Set rFind = .Find(What:=w, LookIn:=xlFormulas, LookAt:=xlPart, MatchCase:=False, SearchFormat:=False)
If Not rFind Is Nothing Then
sAddr = rFind.Address
Do
rFind.Select
MsgBox w & " found at " & rFind.Address
Set rFind = .FindNext(rFind)
Loop While rFind.Address <> sAddr
End If
End With
End Sub

Excel macro "type mismatch" error while looping through a column

Every call of this Function results in a Runtime Error '13' Type Mismatch. Why does this happen?
Public Function VersionExists(versionId As String)
VersionExists = False
For Each cell In Tabelle2.Columns(1)
If cell.Value = versionId Then
VersionExists = True
End If
Next
End Function
You can't access cell.value from .Columns(1) as it returns a range encompassing the entire column, instead;
For Each cell In Sheet1.Columns(1).Rows '//or .cells
Probably a good idea to exit the for loop after a match too.
Here is an alternative as I suggested in the comment
Public Function VersionExists(versionId As String) As Boolean
Dim aCell As Range, rng As Range
Set rng = Tabelle2.Columns(1)
Set aCell = rng.Find(What:=versionId, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then VersionExists = True
End Function