Select all cells matching my find criteria - vba

I´m writing a simple macro for searching my value in table. I know that searched value is in the document many times. But my macro finds just first value in table. I want select all rows with the value I´m looking for. Then I want copy selected rows and copy them to "sheet2". Can somebody help me adjust my macro? Thx
Sub Vyhladat()
Sheets("Sheet1").Columns(24).Find(What:=InputBox("Please enter your LR number", "Search")).Select
ActiveCells.EntireRow.Select
Selection.Copy
Sheets("Sheet2").Select
Range("A2").Select
Do
If IsEmpty(ActiveCell.Value) Then
ActiveCell.PasteSpecial xlPasteValues
End
Else
ActiveCell.Offset(1, 0).Select
End If
Loop
End Sub

Here is how to do it (find the first match and then loop with the FindNext() method) :
Sub test_Jean()
Dim FirstAddress As String, _
cF As Range, _
RowsToCopy As String
ActiveSheet.Cells(1, 24).Activate
With ActiveSheet.Columns(24)
'First, define properly the Find method
Set cF = .Find(What:=InputBox("Please enter your LR number", "Search"), _
After:=ActiveCell, _
LookIn:=xlFormulas, _
LookAt:=xlPart, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False)
'If there is a result, keep looking with FindNext method
If Not cF Is Nothing Then
FirstAddress = cF.Address
Do
cF.EntireRow.Copy
Sheets("Sheet2").Range("A" & Sheets("Sheet2").Range("A" & Rows.Count).End(xlUp).Row + 1).PasteSpecial xlPasteValues
Set cF = .FindNext(cF)
'Look until you find again the first result
Loop While Not cF Is Nothing And cF.Address <> FirstAddress
End If
End With
End Sub

Related

VBA Excel - ".Find" Search from top to bottom in order for column K

My goal is to search for a specific value in column "K" and to return a specific result. But an obstacle I'm facing is that it is not going in order from top to bottom when searching the column but rather just executing "find" for "add" even though there is "term" before it. Is there a way to make it read in order cell by cell for the column?
Sub Find_Stuff()
Dim s As String
Dim rCell As Range
Dim lReply As Long
Dim firstaddress As String
Dim rngOriginal As Range
Dim Cell As Range
Dim n As Long
Set Cell = Columns("K:K").Find(What:="Add", LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not Cell Is Nothing Then
firstaddress = Cell.Address
Cell.Offset(0, -9).Resize(, 4).Insert shift:=xlDown
Cell.Offset(0, 1).Value = "add "
n = Range("K" & Rows.Count).End(xlUp).Row
Range("K9").AutoFill Destination:=Range("K9:K" & n), Type:=xlFillDefault
Cell.Select
Else
Set Cell = Columns("K:K").Find(What:="Term", LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not Cell Is Nothing Then
firstaddress = Cell.Address
Cell.Offset(0, -4).Resize(, 4).Insert shift:=xlDown
Cell.Offset(0, 1).Value = "term "
n = Range("K" & Rows.Count).End(xlUp).Row
Range("K9").AutoFill Destination:=Range("K9:K" & n), Type:=xlFillDefault
Cell.Select
Else
Set Cell = Columns("K:K").Find(What:="Remove", LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not Cell Is Nothing Then
firstaddress = Cell.Address
Cell.Offset(0, -4).Resize(, 4).Insert shift:=xlDown
Cell.Offset(0, 1).Value = "Remove"
n = Range("K" & Rows.Count).End(xlUp).Row
Range("K9").AutoFill Destination:=Range("K9:K" & n), Type:=xlFillDefault
Cell.Select
Else
Columns("K:K").Select
Set Cell = Selection.Find(What:="New", After:=ActiveCell, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not Cell Is Nothing Then
Cell.Offset(0, 1).Select
ActiveCell.FormulaR1C1 = _
"New"
Cell.Select
End If
On Error GoTo 0
End If
On Error GoTo 0
End If
On Error GoTo 0
End If
On Error GoTo 0
End Sub
But an obstacle I'm facing is that it is not going in order from top to bottom when searching the column but rather just executing "find" for "add" even though there is "term" before it. Is there a way to make it read in order cell by cell for the column?
This is the standard behaviour of .Find(). This is the description of the After parameter in MSDN:
The cell after which you want the search to begin. This corresponds to the position of the active cell when a search is done from the user interface. Notice that After must be a single cell in the range. Remember that the search begins after this cell; the specified cell isn't searched until the method wraps back around to this cell. If you do no specify this argument, the search starts after the cell in the upper-left corner of the range.
To make sure that the .Find() starts searching from the first cell, you have to pass as a parameter the last cell:
Sub TestMe()
Dim myR As Range
Dim myS As Range: Set myS = Range("B1:B5")
With myS
Set myR = .Find(1)
Debug.Print myR.Row
Set myR = .Find(1, after:=.Cells(.Cells.Count))
Debug.Print myR.Row
End With
End Sub

VBA-Excel CTRL Find

I am currently trying to find a certain word within an excel spreadsheet, copy the cell on the right and then paste it a further 3 cells to the right and 3 cells down, before dragging this down.
I have compiled the following which does the job.
Cells.Find(What:="N/C:", After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).Activate
Selection.Offset(0, 1).Select
Selection.Copy
Selection.Offset(3, 3).Select
ActiveSheet.Paste
Range(Selection, Selection.End(xlDown)).Select
Selection.FillDown
My question is:
How can I extend this code so it searches for all "N/C:" and does the above
Feel free to provide updates to my initial code if it can be improved
Lightly tested:
Sub Tester()
Dim col As Collection, c, sht As Worksheet
Set sht = ActiveSheet
Set col = FindAll(sht.UsedRange, "N/C:")
Debug.Print "Found " & col.Count & " matches"
For Each c In col
c.Copy c.Offset(3, 3)
sht.Range(c.Offset(3, 3), c.Offset(3, 3).End(xlDown)).FillDown
Next c
End Sub
Public Function FindAll(rng As Range, val As String) As Collection
Dim rv As New Collection, f As Range
Dim addr As String
Set f = rng.Find(what:=val, after:=rng.Cells(rng.Cells.Count), _
LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False)
If Not f Is Nothing Then addr = f.Address()
Do Until f Is Nothing
rv.Add f
Set f = rng.FindNext(after:=f)
If f.Address() = addr Then Exit Do
Loop
Set FindAll = rv
End Function
The short answer is that there is no built-in way to return a range with all the find results (i.e. find all) in one go. You have to find the first result (the code you already have) and then use findNext within a while loop, exiting only when the next result until it refers to the same cell as the first result.
There is a good explanation/implementation at http://www.cpearson.com/excel/findall.aspx

How to select a date with a set cell color in Excel?

I am trying to create a macro in excel VBA, that searches the Range (B1:B30) of the value of the ActiveCell in Column “B” by a loop. Along with the search of Column, I also want to check if the date’s cell is colored with a particular color. If the date's cell equals the set color "Good", then I want it to change the color of the cell in Column H of the same row as selected to red.
When I run the code, I get an error message of “Run-time error ‘424’: Object required.” When I go to debug the problem, it highlights the .Find function I have and points to the last line of the search which is “SearchFormat:=False).Activate” What should I do to fix this problem?
Any improvement with my overall code will be very much appreciated.
Sub Find()
Dim FirstAddress As String
Dim MySearch As Variant
Dim Rng As Range
Dim I As Long
MySearch = Array(ActiveCell)
With Sheets("Sheet1").Range("B1:B30")
For I = LBound(MySearch) To UBound(MySearch)
Set Rng = .Find(What:=MySearch(I), _
After:=ActiveCell, _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
SearchFormat:=False).Activate
If Not Rng Is Nothing Then
FirstAddress = Rng.Address
Do
If ActiveCell.Style.Name = "Good" Then
Rng("H" & ActiveCell.Row).Select
Rng.Interior.ColorIndex = xlColorIndexRed
End If
Set Rng = .FindNext(Rng)
Loop While Not Rng Is Nothing And Rng.Address <> FirstAddress
End If
Next I
End With
End Sub
Showing the Debug mode of the run-time error.
Screenshot of the Spreadsheet for reference
Code Review:
You have several problems here.
MySearch = Array(ActiveCell) will always be a single value. So why bother looping through it
You cannot set a range to equal range.activate. Searching Sheets("Sheet1").Range("B1:B30") implies that you are searching a worksheet other that the ActiveSheet. If this is the case than .Find(After:=Activecell) suggests that you are looking for a value after the ActiveCell of another worksheet.
Set Rng = .Find(What:=MySearch(I), _
After:=ActiveCell, _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
SearchFormat:=False).Activate
Rng("H" & ActiveCell.Row) Rng is a Range object. It doesn't work like Range. You cannot pass it a cell address. You can do this Rng(1,"H") which is really shorthand for Rng.cells(1,"H") bit that is misleading because Rng is in column 2 Rng(1,"H") will reference the value in column I.
Sub Find()
Dim FirstAddress As String
Dim MySearch As Variant
Dim Rng As Range
Dim I As Long
MySearch = ActiveCell 'This is the ActiveCell of the ActiveSheet not necessarily Sheets("Sheet1")
With Sheets("Sheet1").Range("B1:B30")
Set Rng = .Find(What:=MySearch, _
After:=.Range("B1"), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
SearchFormat:=False)
If Not Rng Is Nothing Then
FirstAddress = Rng.Address
Do
If Rng.Style.Name = "Good" Then
.Range("H" & Rng.Row).Interior.ColorIndex = xlColorIndexRed
End If
Set Rng = .FindNext(Rng)
Loop While Not Rng Is Nothing And Rng.Address <> FirstAddress
End If
End With
End Sub
UPDATE:
Here is the actual answer to your question:
Sub FindMatchingValue()
Const AllUsedCellsColumnB = False
Dim rFound As Range, SearchRange As Range
If AllUsedCellsColumnB Then
Set SearchRange = Range("B1", Range("B" & Rows.count).End(xlUp))
Else
Set SearchRange = Range("B1:B30")
End If
If Intersect(SearchRange, ActiveCell) Is Nothing Then
SearchRange.Select
MsgBox "You must select a cell in the highlighted area before continuing", vbInformation, "Action Cancelled"
Exit Sub
End If
Set rFound = SearchRange.Find(What:=ActiveCell.Value, _
After:=ActiveCell, _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
SearchFormat:=False)
If Not rFound Is Nothing Then
Do
If rFound.Style.Name = "Good" Then
Range("H" & rFound.Row).Interior.Color = vbRed
End If
Set rFound = SearchRange.FindNext(rFound)
Loop While Not rFound Is Nothing And rFound.Address <> ActiveCell.Address
End If
End Sub
You can't put Activate at the end of the findthe way you are trying to do.
Try this as you find statement.
Set Rng = .Find(What:=MySearch(I), _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False)
Rng.Activate
Then if you want to Activate the range, do that. But, it is best to stay away from Select, Activate etc in VBA code. I strongly suggest not using that last line of code and adjust you code to not rely on Select and Activate.
you may want to consider an Autofilter approach so as to loop only through relevant cells, as follows:
Option Explicit
Sub Find()
Dim cell As Range
With Sheets("Sheet1").Range("B1:B30")
.Rows(1).Insert '<--| insert a dummy header cell to exploit Autofilter. it'll be removed by the end
With .Offset(-1).Resize(.Rows.Count + 1) '<--| consider the range expanded up to the dummy header cell
.Rows(1) = "header" '<--| give the dummy header cell a dummy name
.AutoFilter field:=1, Criteria1:=ActiveCell '<--| filter range on the wanted criteria
If Application.WorksheetFunction.Subtotal(103, .Cells) > 1 Then '<--| if any cell other than "header" one has been filtered...
For Each cell In .Offset(1).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible) '<--| ... loop through filtered cells only
If cell.Style.Name = "Good" Then cell.Offset(, 6).Interior.ColorIndex = 3 '<--| ... and color only properly styled cells
Next cell
End If
.AutoFilter '<--| .. show all rows back...
End With
.Offset(-1).Resize(1).Delete '<--|delete dummy header cell
End With
End Sub

VBA for searching string in a column and copy entire rows depending on the presence of certain string at adjacent cell

I am completely new for VBA.
I have excel data sheet containing numbers and strings. I want to search for certain string say 'CYP' in column I then look for a cell of its row at column C and copy entire rows containing the string of cell C. I want to paste in sheet 2 of the same workbook and loop it again to look for remaining CYPs in column.
Would you help me on this please?
After the suggestion from pnuts, here is my macro code
Sub Macro1()
'
' Macro1 Macro
'
'
Columns("I:I").Select
Range("I729").Activate
Selection.Find(What:="cyp", After:=ActiveCell, LookIn:=xlValues, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).Activate
ActiveWindow.SmallScroll Down:=5
Range("C749").Select
Selection.Copy
Columns("C:C").Select
Range("C734").Activate
Selection.Find(What:="EPT001TT0601C000151", After:=ActiveCell, LookIn:= _
xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext _
, MatchCase:=False, SearchFormat:=False).Activate
Rows("746:750").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Sheet2").Select
ActiveSheet.Paste
End Sub
In this code the CYP was found in I749, cell C749 was copied as string and first row in column C containing the same string was searched followed by copying of the entire row and 4 more followed by it then pasting in sheet2 of the same workbook.
What I wanted was to loop this action again and again upto the end of column I and repeat the same action.
Thank you!
I managed to solve the problem with the help of Trebor76 at Excelforum. Here I am giving solution in that way it might be helpful for some newbies like myself with similar problem.
Option Explicit
Sub Macro1()
'Written and assisted by Trebor76
'Copy an entire row from Sheet1 to Sheet2 for each unique matching item in Col. C if the text in Col. I contains the text 'CYP' (case sensitive)
'http://www.excelforum.com/excel-programming-vba-macros/962511-vba-for-searching-string-in-a-column-and-copy-rows-depending-on-string-in-adjacent-cell.html
Dim rngCell As Range
Dim objMyUniqueArray As Object
Dim lngMyArrayCounter As Long
Dim lngMyRow As Long
Dim varMyItem As Variant
Application.ScreenUpdating = False
Set objMyUniqueArray = CreateObject("Scripting.Dictionary")
For Each rngCell In Sheets("Sheet1").Range("I1:I" & Sheets("Sheet1").Range("I" & Rows.Count).End(xlUp).Row)
If InStr(rngCell, "CYP") > 0 Then
If Not objMyUniqueArray.Exists(Trim(Cells(rngCell.Row, "C"))) Then
lngMyArrayCounter = lngMyArrayCounter + 1
objMyUniqueArray.Add (Trim(Cells(rngCell.Row, "C"))), lngMyArrayCounter
varMyItem = Sheets("Sheet1").Cells(rngCell.Row, "C")
For lngMyRow = 1 To Sheets("Sheet1").Cells(Rows.Count, "C").End(xlUp).Row
If Sheets("Sheet1").Cells(lngMyRow, "C") = varMyItem Then
Rows(lngMyRow).Copy Destination:=Sheets("Sheet2").Range("A" & Sheets("Sheet2").Range("A" & Rows.Count).End(xlUp).Row + 1)
End If
Next lngMyRow
End If
End If
Next rngCell
Set objMyUniqueArray = Nothing
Application.ScreenUpdating = True
MsgBox "All applicable rows have been copied.", vbInformation
End Sub
Cheers!

vba function to copy certain value from one workbook to another

I have 2 workbooks. I need copy the row in one workbook only if it contains a certain value from another workbook. Here's my code, it works for the first i=21 and i=22 but tells me there's an error in Cells.Find when I reach i=23.
For i = 21 To 35
Windows("Run Report.xlsm").Activate
Dim strL3 As String
strL3 = Sheets("Summary").Range("A" & i).Value
Workbooks("Ace Survey - Level 1 and level 3 Trending (w Resolution) v3").Activate
Range("A1").Activate
Cells.Find(What:=strL3, After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
If strL3 = "Call Disconnected" Or strL3 = "Caller Not Present" Then
ActiveCell.Offset(2, 2).Select
Else
ActiveCell.Offset(1, 2).Select
End If
Application.CutCopyMode = False
ActiveCell.Copy
Windows("Run Report.xlsm").Activate
Sheets("Summary").Select
Range("G" & i).Select
ActiveSheet.Paste
Next i
Find returns a Range object if something is found, but Nothing otherwise. You are attempting to Activate the result of using Find, even if it is Nothing - which will generate an error.
You need to store the result of your Find attempt in a Range variable, and check for Nothing.
Dim rngFound As Range
Set rngFound = Range("A1").Find(...)
If Not rngFound Is Nothing Then
' we found something!
Else
' Nothing
End If
But, as advised, you should be supplying more details for your question.