Select and copy specific cells - excel

I have an excel sheet that I want to select some cells based on their values then copy these cells to another sheet using VBA.
I have a chunk of code that go through all the excel sheetd and search for a specific value then return the total of this cells.
I need to copy right now just the cells in column H that have values "name" & "contact" and copy all these values to the sheet2 in the same workbook.
Then I to copy the cells that are next to the name and contact.
The end result is a new table that contain 2 columns name and contact and under each column the values of each name and contact that belong to it
Sample Data
Scan:
Private Sub CommandButton1_Click()
row_number = 4
count_of_str = 0
Do
DoEvents
row_number = row_number + 1
item_in_review = Sheets("Sheet1").Range("H" & row_number)
If InStr(item_in_review, "name") Then
count_of_str = count_of_str + 1
End If
Loop Until item_in_review = ""
MsgBox "the str occured: " & count_of_str & " times."
End Sub

Utilise the Find / FindNext methods
It's not entirely clear which columns your data is in. I have assumed the labels name and contact are in H, and the actual data in I
Also, I have assumed that every name will have a contact, and have not included any checks for that.
Sub Demo()
Dim row_number As Long, count_of_str As Long
Dim rToSearch As Range, rFound As Range, rng As Range
Dim strSearchTerm As String
Dim FirstAddr As String
Dim ws As Worksheet, rDest As Range
Dim cl As Range, ar As Range
strSearchTerm = "name"
With Sheets("Sheet1")
Set rToSearch = .Range(.Cells(5, 8), .Cells(.Rows.Count, 8).End(xlUp))
End With
Set rng = rToSearch.Find( _
What:=strSearchTerm, _
After:=rToSearch.Cells(rToSearch.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False)
If Not rng Is Nothing Then
FirstAddr = rng.Address
Do
count_of_str = count_of_str + 1
If rFound Is Nothing Then
Set rFound = rng.Offset(0, 1)
Else
Set rFound = Union(rFound, rng.Offset(0, 1))
End If
Set rng = rToSearch.FindNext(rng)
Loop Until rng.Address = FirstAddr
End If
MsgBox "the str occured: " & count_of_str & " times."
' rFound now refers to all found cells
' Copy to somewhere
Set ws = Worksheets("YourDestinationSheet") '<~~Update as required
Set rDest = ws.Range("YourDestinationRange") '<~~Update as required
If Not rFound Is Nothing Then
rFound.Copy rDest '<~~ copy names
rFound.Offset(1, 0).Copy rDest.Offset(0, 1) '<~~ copy contacts
End If
' Process found cells
' eg
If Not rFound Is Nothing Then
For Each ar In rFound.Areas
For Each cl In ar.Cells
Debug.Print cl.Address
Next cl, ar
End If
End Sub

Untested:
Private Sub CommandButton1_Click()
Dim count_of_str As Long
Dim c as Range, d As Range
count_of_str = 0
Set c = Sheets("Sheet1").Range("H4") 'cell to check
Set d = Sheets("Sheet2").Range("A2") 'destination to copy to
Do While Len(c.Value) > 0
If InStr(c.Value, "name") > 0 Then
count_of_str = count_of_str + 1
c.Copy d
Set d = d.Offset(1, 0) 'next destination row
End If
Set c = c.Offset(1, 0) 'next cell to check
Loop
MsgBox "the str occured: " & count_of_str & " times."
End Sub

Related

VBA excel search tool

Tried doing a search tool to the excel sheet (VBA) I'm working on.
So far every time I search for the text, it ends up filtering only the first row and not any row that has the value I'm looking for. I added a picture to show what it returns and the code as well. Is there anything I need to change to the code to make it search for all the data in the sheet instead of having it to show only one row? Any help is appreciated.
Search result of only the first row:
Sub SearchAllSheets()
Dim ws As Worksheet, OutputWs As Worksheet
Dim rFound As Range
Dim strName As String
Dim count As Long, LastRow As Long
Dim IsValueFound As Boolean
IsValueFound = False
Set OutputWs = Worksheets("sheet1") '---->change the sheet name as required
LastRow = OutputWs.Cells(Rows.count, "A").End(xlUp).Row
On Error Resume Next
strName = InputBox("What are you looking for?")
If strName = "" Then Exit Sub
For Each ws In Worksheets
If ws.Name <> "Output" Then
With ws.UsedRange
Set rFound = .Find(What:=strName, After:=.Cells(1, 1), LookIn:=xlValues, LookAt:=xlWhole)
If Not rFound Is Nothing Then
Application.Goto rFound, True
IsValueFound = True
'MsgBox rFound.Row
rFound.EntireRow.Copy
OutputWs.Cells(LastRow + 1, 1).PasteSpecial xlPasteAll
Application.CutCopyMode = False
LastRow = LastRow + 1
End If
End With
End If
Next ws
On Error GoTo 0
If IsValueFound Then
OutputWs.Select
MsgBox "Result pasted to Sheet Output"
Else
MsgBox "Value not found"
End If
End Sub
Try this:
Sub SearchAllSheets()
Dim ws As Worksheet, OutputWs As Worksheet
Dim rFound As Range, IsValueFound As Boolean
Dim strName As String
Dim count As Long, LastRow As Long
Set OutputWs = Worksheets("Output") '---->change the sheet name as required
LastRow = OutputWs.Cells(Rows.count, "A").End(xlUp).row
strName = Trim(InputBox("What are you looking for?"))
If strName = "" Then Exit Sub
For Each ws In Worksheets
If ws.Name <> OutputWs.Name Then
Debug.Print "Checking " & ws.Name
Set rFound = FindAll(ws.UsedRange, strName)
If Not rFound Is Nothing Then
Set rFound = rFound.EntireRow
count = rFound.Cells.count / Columns.count 'how many matched rows?
Debug.Print "Found " & count & " rows"
rFound.Copy OutputWs.Cells(LastRow + 1, 1)
LastRow = LastRow + count
IsValueFound = True
End If
End If
Next ws
If IsValueFound Then
OutputWs.Select
MsgBox "Result(s) pasted to Sheet " & OutputWs.Name
Else
MsgBox "Value not found"
End If
End Sub
'find all cells in range `rng` with value `val` and return as a range
Public Function FindAll(rng As Range, val As String) As Range
Dim rv As Range, f As Range
Dim addr As String
Set f = rng.Find(what:=val, After:=rng.Cells(rng.Cells.count), _
LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False)
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

For every value in column loop through table and copy row of every instance, paste to another sheet

For each value in Sheet("Scrap2") Column A.
find all matching instances of this value in column A of Sheet("VA_Data"). copy entire row and paste to first empty Row on sheet("List")
My code right now basically only copys the first instance it comes to of the match and then moves to the next value in Sheet("Scrap2").
If there are 10 cells in col A of sheet "VA_Data" that match the first value of Scrap2, then those 10 rows need to copy entire row and paste to first empty rows on sheet "List".
any help is appreciated.
Option Explicit
Public Sub Loop_VA_Data()
Dim wsa As Worksheet
Dim wsb As Worksheet
Dim wsc As Worksheet
Dim a As Integer
Dim b As Integer
Dim c As Integer
Dim stra As String
Dim rng As Range
On Error GoTo errLoop_VA_Data
Application.ScreenUpdating = False
Set wsa = ThisWorkbook.Worksheets("Scrap2")
Set wsb = ThisWorkbook.Worksheets("VA_Data")
Set wsc = ThisWorkbook.Worksheets("List")
wsa.Range("B:B").Clear
wsc.Rows("2:" & wsc.Range("A1").CurrentRegion.Rows.Count + 1).Clear
a = 2
Do
If Trim(wsa.Cells(a, 1).Value) = "" Then
Exit Do
End If
stra = Trim(wsa.Cells(a, 1).Value)
Set rng = wsb.Range("A:A").Find(What:=stra, LookIn:=xlValues, LookAt:=xlWhole)
If Not (rng Is Nothing) Then
b = rng.Row
c = wsc.Range("A1").CurrentRegion.Rows.Count + 1
wsb.Rows(b).Copy wsc.Rows(c)
wsa.Cells(a, 2).Value = "Found on row " & b
Else
wsa.Cells(a, 2).Value = "Not Found"
End If
If Not (rng Is Nothing) Then
Set rng = Nothing
End If
a = a + 1
Loop
MsgBox "Complete!", vbInformation
GoTo closeout
Exit Sub
errLoop_VA_Data:
MsgBox "Err Number is: " & Err.Number & " / Err Desc is: " & Err.Description & " in sub Loop_VA_Data!", vbCritical
closeout:
If Not (wsa Is Nothing) Then
Set wsa = Nothing
End If
If Not (wsb Is Nothing) Then
Set wsb = Nothing
End If
If Not (wsc Is Nothing) Then
Set wsc = Nothing
End If
If Not (rng Is Nothing) Then
Set rng = Nothing
End If
Exit Sub
End Sub
I think #urdearboy has the right idea - using a filter & copying en masse. The following code assumes the data on your VA_Data sheet is contiguous. Let me know how you go with it.
Option Explicit
Sub Filter_Copy()
Application.ScreenUpdating = False
Dim c As Range
Dim LastRow As Long, PasteRow As Long
Dim ws1 As Worksheet, ws2 As Worksheet, ws3 As Worksheet
Set ws1 = Sheets("Scrap2")
Set ws2 = Sheets("VA_Data")
Set ws3 = Sheets("List")
LastRow = ws1.Cells(Rows.Count, 1).End(xlUp).Row
For Each c In ws1.Range(ws1.Cells(1, 1), ws1.Cells(LastRow, 1))
With ws2.Cells(1, 1).CurrentRegion
.AutoFilter 1, c.Value
PasteRow = ws3.Cells(Rows.Count, 1).End(xlUp).Row + 1
.Offset(1).Resize(.Rows.Count - 1).Copy ws3.Range("A" & PasteRow)
.AutoFilter
End With
Next c
End Sub

Fetch values in Target sheet from Source sheet based on the unique ID

There are two sheets - Source and Target. There is a unique ID in both sheets in Column-A.
In TargetSheet based on the uniqueID (Column-A), I want to fetch values from SourceSheet(Column-B) to TargetSheet(Column-B).
There are unique IDs in TargetSheet(Column-A) which are not in SourceSheet(Column-A), hence they should be left blank.
Sub Recon()
Dim lrow, i, j As Long
lrow = Range("A1048576").End(xlUp).Row
TargetSheet.Activate
Range("A1").Select
j = 1
For i = 3 To lrow
Do
j = j + 1
If Range("A" & i) = SourceSheet.Range("A" & j) Then
Cells(i, 2) = SourceSheet.Range("B" & j).Value
End If
Loop Until Range("A" & i) = SourceSheet.Range("A" & j)
Next i
End Sub
You can do it combining VLOOKUP trapped into an IFERROR to handle missing ids. VLOOKUP will look a value in a column and if found, will return a value in same row but different custom column. If there is no coincidence, it will raise an error, so we combine it with IFERROR to transform that error into blank value, which means that id is not found.
VLOOKUP function
IFERROR function
My fake data is just 2 sheets like yours:
The code I've used:
Sub test()
Dim WKsource As Worksheet
Dim WKTarget As Worksheet
Dim UF As Long
Set WKsource = ThisWorkbook.Worksheets("SourceSheet")
Set WKTarget = ThisWorkbook.Worksheets("TargetSheet")
With WKTarget
UF = .Range("A" & .Rows.Count).End(xlUp).Row
.Range("B2:B" & UF).FormulaR1C1 = "=IFERROR(VLOOKUP(RC[-1]," & WKsource.Name & "!C1:C2,2,FALSE),"""")" 'get values
.Range("B2:B" & UF) = .Range("B2:B" & UF).Value 'paste formula results as values
End With
Set WKTarget = Nothing
Set WKsource = Nothing
End Sub
My final output:
Try this:
`Sub Test()
Dim Source As Range
Set Source = ThisWorkbook.Worksheets("Source").Range("A2:A5")
Dim Target As Range
Set Target = ThisWorkbook.Worksheets("Target").Range("A2:A6")
Dim TargetCell As Range
Dim FoundCell As Range
For Each TargetCell In Target
Set FoundCell = Source.Find(TargetCell.Value, _
Source.Cells(1, 1), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchDirection:=xlNext)
If Not FoundCell Is Nothing Then
TargetCell.Offset(, 1) = FoundCell.Offset(, 1)
End If
Next TargetCell
End Sub`

Find word in column and copy lines below on different sheet

I have source data which are not aligned to table.
I want to find text (e.g. Account), copy the two whole lines below the cell with the found text (Account) and paste them on a different Sheet. Then search down and do again until the data ends. Data should be pasted in the order it is reached.
The cell with word "Account" will be always in the column A. The search should be for the exact word "Account", because in the column can be cells which contain e.g. "Payer account".
This code shows me an error msg
"Run-time error 438 - object doesnt support this property or method"
Private Sub Search_n_Copy()
Dim LastRow As Long
Dim rng As Range, C As Range
With Worksheets("INPUT_2") ' <-- here should be the Sheet's name
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row ' last row in column A
Set rng = .Range("A1:A" & LastRow) ' set the dynamic range to be searched
' loop through all cells in column A and copy below's cell to sheet "Output_2"
For Each C In rng
If C.Value = "Account" Then
C.Offset(-1, 0).Copy C.Offset.OUTPUT_2(-7, -1) ' use offset to put value in sheet "Output_2", column E
End If
Next C
End With
End Sub
This post doesn't point out what the error in your original code is. Ron Rosenfeld has already covered that in the comment.
Here is another faster way (as compared to looping) which uses .Find/.FindNext to achieve what you want. It also doesn't copy the rows in a loop but copies in the end.
Private Sub Search_n_Copy()
Dim ws As Worksheet
Dim rngCopy As Range, aCell As Range, bcell As Range
Dim strSearch As String
strSearch = "Account"
Set ws = Worksheets("INPUT_2")
With ws
Set aCell = .Columns(1).Find(What:=strSearch, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
Set bcell = aCell
If rngCopy Is Nothing Then
Set rngCopy = .Rows((aCell.Row + 1) & ":" & (aCell.Row + 2))
Else
Set rngCopy = Union(rngCopy, .Rows((aCell.Row + 1) & ":" & (aCell.Row + 2)))
End If
Do
Set aCell = .Columns(1).FindNext(After:=aCell)
If Not aCell Is Nothing Then
If aCell.Address = bcell.Address Then Exit Do
If rngCopy Is Nothing Then
Set rngCopy = .Rows((aCell.Row + 1) & ":" & (aCell.Row + 2))
Else
Set rngCopy = Union(rngCopy, .Rows((aCell.Row + 1) & ":" & (aCell.Row + 2)))
End If
Else
Exit Do
End If
Loop
Else
MsgBox SearchString & " not Found"
End If
'~~> I am pasting to Output sheet. Change as applicable
If Not rngCopy Is Nothing Then rngCopy.Copy Sheets("Output").Rows(1)
End With
End Sub
Screenshot
The codle would be like this. This code Use variant.
Private Sub Search_n_Copy()
Dim LastRow As Long
Dim rng As Range, C As Range
Dim vR(), n As Long, k As Integer, j As Integer
Dim Ws As Worksheet
With Worksheets("INPUT_2") ' <-- here should be the Sheet's name
.Columns("e").ClearContents
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row ' last row in column A
Set rng = .Range("A1:A" & LastRow) ' set the dynamic range to be searched
' loop through all cells in column A and copy below's cell to sheet "Output_2"
For Each C In rng
If C.Value = "Account" Then
For j = 1 To 2
n = n + 1
ReDim Preserve vR(1 To 6, 1 To n)
For k = 1 To 6
vR(k, n) = C.Offset(j, k - 1) ' use offset to put value in sheet "Output_2", column E
Next k
End If
Next C
If n > 0 Then
Set Ws = Sheets.Add '<~~~ Sheets("your sheet name")
With Ws
.Range("a1").Resize(n, 6) = WorksheetFunction.Transpose(vR)
End With
End If
End With
End Sub

find in column distinguishing between empty and blank cells

I need to find the first cell in a column that's either empty or contains only blanks. I came up with the following..
Dim FindString As String
Dim Rng As Range
Dim Done As Boolean
FindString = ""
With Sheets("Yahoo").Range("A:A")
Set Rng = .Find(What:=FindString, _
After:=.Cells([Stock_Start_Row], 1), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
j = Rng.Row
Done = False
Do Until Done
FindString = .Cells(j, 1)
FindString = Replace(FindString, " ", "")
If FindString = "" Then
j = j - 1
Else
Done = True
End If
Loop
MsgBox "Found" & " " & Rng.Row & " " & j
Else
MsgBox "Nothing found"
End If
End With
This will discover and clear any blank cells immediately before the first empty cell but will not discover blank cells among the preceding cells.
Is there any way to search for cells containing one or more blanks?
If so I could add a second search.
I need to find the first cell in a column that's either empty or
contains only blanks.
This will go through column A on sheet("Yahoo"). It should work for you:
Sub FindBlankOrEmptyCells()
Dim wbk As Workbook
Set wbk = ThisWorkbook
Dim ws As Worksheet
Set ws = wbk.Sheets(1)
Dim cell As Range
Dim BlankCounter As Integer
Dim i As Integer
Dim OldCellValue As Variant ' just for the heck of it
For Each cell In Sheets("Yahoo").Range("A:A")
OldCellValue = cell.Value
cell.NumberFormat = "#"
cell.Value = "'" & cell.Value
BlankCounter = 0
If cell.Value = "" Then
MsgBox "Found an empty cell in Column A, Row: " & " " & cell.Row
Exit Sub
End If
For i = 1 To Len(cell)
If cell.Characters(i, 1).Text = " " Then
BlankCounter = BlankCounter + 1
End If
If BlankCounter = Len(cell) Then
MsgBox "Found a cell full of blanks in Column A, Row: " & " " & cell.Row
cell.Clear
cell.Value = OldCellValue
cell.Value = cell.Value
Exit Sub
' If you want to delete the contents of the cell or continue looping you can delete this Exit Sub and put in:
' cell.ClearContents
' then it will loop through all the cells and delete blanks and message you each time
End If
Next i
cell.Clear
cell.Value = OldCellValue
cell.Value = cell.Value
Next cell
End Sub
This will find the first cell that is either empty or contains only blanks(spaces). It will stop once it finds a cell that meets that criteria. If you want to continue looping you can enable the code I commented out. Let me know how it works.
EDIT:
If you want to use the .find function to gain some efficiency that is possible - but eventually you are going to need to loop through all the characters in a cell and determine if it contains all spaces. Try this one out(I stopped it at row 30 so it doesn't keep popping up messages for blanks - but you could remove the messages and extend to Loop Until to row 999999):
Sub FindBlankOrEmptyCellsWithFindFunction()
Dim FindString As String
Dim Rng As Range
Set Rng = Sheets("Yahoo").Range("A1")
Dim Done As Boolean
Dim wbk As Workbook
Set wbk = ThisWorkbook
Dim ws As Worksheet
Set ws = wbk.Sheets(1)
Dim cell As Range
Dim BlankCounter As Integer
Dim i As Integer
Dim ii As Integer
Dim LoopStopperRange As Range
Dim OldCellValue As Variant
ii = 0
Do
ii = ii + 1
FindString = " "
With Sheets("Yahoo").Range("A:A")
Set Rng = .Find(What:=FindString, _
After:=.Cells(Rng.Row, 1), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then ' If Rng Is Something Then
If ii = 1 Then
Set LoopStopperRange = Rng
End If
If LoopStopperRange = Rng And ii > 1 Then
Exit Do
End If
For Each cell In Rng
OldCellValue = cell.Value
cell.NumberFormat = "#"
cell.Value = "'" & cell.Value
BlankCounter = 0
If cell.Value = "" Then
MsgBox "Found an empty cell in Column A, Row: " & " " & cell.Row
'Exit Sub
End If
For i = 1 To Len(cell)
If cell.Characters(i, 1).Text = " " Then
BlankCounter = BlankCounter + 1
End If
If BlankCounter = Len(cell) Then
MsgBox "Found a cell full of blanks in Column A, Row: " & " " & cell.Row
cell.Clear
cell.Value = OldCellValue
cell.Value = cell.Value
'Exit Sub
' If you want to delete the contents of the cell or continue looping you can delete this Exit Sub and put in:
' cell.ClearContents
' then it will loop through all the cells and delete blanks
End If
Next i
cell.Clear
cell.Value = OldCellValue
cell.Value = cell.Value
Next cell
Else
End If
End With
Loop Until Rng Is Nothing
Set Rng = Sheets("Yahoo").Range("A1")
Do
ii = ii + 1
FindString = ""
With Sheets("Yahoo").Range("A:A")
Set Rng = .Find(What:=FindString, _
After:=.Cells(Rng.Row, 1), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then ' If Rng Is Something Then
For Each cell In Rng
OldCellValue = cell.Value
cell.NumberFormat = "#"
cell.Value = "'" & cell.Value
BlankCounter = 0
If cell.Value = "" Then
MsgBox "This loop will go until Row 30 so you don't have to pause/break out. Found an empty cell in Column A, Row: " & " " & cell.Row
'Exit Sub
End If
Next cell
Else
End If
End With
Loop Until Rng.Row = 30
'Loop Until Rng.Row = 99999
End Sub
Good Luck.

Resources