VBA Looping Through Worksheet to find multiple instances of word - excel

I am trying to write a macro for excel that searches Sheet1 and
finds all instances of the words Force and Grade, then
copies the cells beneath those words (all cells to the first empty row), and pastes to Sheet2.
These words (Force and Grade) can be found in any cell in Worksheet1 and the size of the used area changes every time the file is created.
So far, I can only get it to find the first instance of each word. I have tried many types of loops from examples on this website and others.
I feel like this should be simple, so I am not sure why I can't find the solution. I have tried a For Next Loop that starts with For i To ws.Columns.Count (with "ws" set to Sheet1), but it turns into an infinite loop (although the total column count was only around 15). Any help or nudge in the right direction would be appreciated.
Here is the code that works so far:
my code
'COPY AND PASTE ALL FORCE VALUES TO FROM SHEET1 TO SHEET2
Sheets("Sheet1").Select
Cells.Find(What:=strSearch1, After:=ActiveCell, LookIn:=xlValues, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False _
, SearchFormat:=False).Activate
ActiveCell.Offset(1, 0).Activate 'select cell below the word "Force"
Range(ActiveCell, ActiveCell.End(xlDown)).Select 'select all cells after "Force" to first empty cell
numBonds = Range(ActiveCell, ActiveCell.End(xlDown)).Count
Selection.Copy
Sheets("Sheet2").Select
Cells(Selection.Row, Columns.Count).End(xlToLeft).Offset(0, 1).Select 'paste to next column
ActiveSheet.Paste

You should use FindNext to indentify all the matches. Something like this to copy all cells below all instances of Force to column A of Sheet2
Dim StrSearch As String
Dim rng1 As Range
Dim rng2 As Range
StrSearch = "Force"
With Worksheets(1).UsedRange
Set rng1 = .Find(StrSearch, , xlValues, xlPart)
If Not rng1 Is Nothing Then
strAddress = rng1.Address
Set rng2 = rng1
Do
Set rng1 = .FindNext(rng1)
Set rng2 = Union(rng2, rng1)
Loop While Not rng1 Is Nothing And rng1.Address <> strAddress
End If
End With
If Not rng2 Is Nothing Then
For Each rng3 In rng2
Range(rng2.Offset(1, 0), rng3.End(xlDown)).Copy Sheets(2).Cells(Rows.Count, "A").End(xlUp)
Next
End If

With Worksheets(1).UsedRange
'Code to copy and paste Force values
Set rng1 = .Find(strSearch1, LookIn:=xlValues)
SampleCnt = Application.WorksheetFunction.CountIf(Sheets("Sheet1").Range("A1:BJ2000"), "Grade")
Do While i < SampleCnt
rng1.Offset(1, 0).Activate 'select cell below the word "Force"
Range(ActiveCell, ActiveCell.End(xlDown)).Select 'select all cells after "Force" to first empty cell
numBonds = Range(ActiveCell, ActiveCell.End(xlDown)).Count
Selection.Copy
Sheets("Sheet2").Select
Worksheets("Sheet2").Columns(Cnt).Select
ActiveSheet.Paste
Sheets("Sheet1").Select
Set rng1 = .FindNext(rng1)
Cnt = Cnt + 2
i = i + 1
Loop
'Code to copy and paste Grade values
Cnt = 4
i = 0
Set rng2 = .Find(strSearch2, LookIn:=xlValues)
Do While i < SampleCnt
rng2.Offset(1, 0).Activate 'select cell below the word "Grade"
Range(ActiveCell, ActiveCell.End(xlDown)).Select 'select all cells after "Grade" to first empty cell
numBonds = Range(ActiveCell, ActiveCell.End(xlDown)).Count
Selection.Copy
Sheets("Sheet2").Select
Worksheets("Sheet2").Columns(Cnt).Select
ActiveSheet.Paste
Sheets("Sheet1").Select
Set rng2 = .FindNext(rng2)
Cnt = Cnt + 2
i = i + 1
Loop
End With

Related

Expanding macro for sorting and copy/pasting data to other worksheets

I export a schedule from MS Teams to Excel for data manipulation.
I made a macro that changes the dates field to a date format for the EU and sorts by it by date.
Then it goes to the next worksheet and checks the names of employees and creates a worksheet for each of the names.
Then it jumps back to the first worksheet, sorts by "name" criteria and copies the data for every single one to its own respective worksheet.
This is what I got so far that is OK:
Sub Temp1()
'Convert Cell Format from Text to Date and change MDY to DMY Format
Sheets("Shifts").Select
Range("D2:D1000").Select
Selection.TextToColumns Destination:=Range("D2"), DataType:=xlFixedWidth, _
FieldInfo:=Array(0, 3), TrailingMinusNumbers:=True
Range("F2:F1000").Select
Selection.TextToColumns Destination:=Range("F2"), DataType:=xlFixedWidth, _
FieldInfo:=Array(0, 3), TrailingMinusNumbers:=True
'Add the Sheets for each member of the "Members" Sheet
Sheets("Members").Select
Dim xRg As Excel.Range
Dim wSh As Excel.Worksheet
Dim wBk As Excel.Workbook
Set wSh = ActiveSheet
Set wBk = ActiveWorkbook
Application.ScreenUpdating = False
For Each xRg In wSh.Range("A2:A22")
With wBk
.Sheets.Add After:=.Sheets(.Sheets.Count)
ActiveCell.FormulaR1C1 = "Evidencija radnog vremena"
Selection.Font.Size = 20
Selection.Font.Bold = True
ActiveCell.Offset(1, 0).Range("A1").Select
ActiveCell.FormulaR1C1 = "Godina i mjesec"
Selection.Font.Size = 14
Selection.Font.Bold = True
ActiveCell.Offset(1, 0).Range("A1").Select
ActiveCell.FormulaR1C1 = "Radnik"
Selection.Font.Bold = True
ActiveCell.Offset(2, 0).Range("A1").Select
On Error Resume Next
ActiveSheet.Name = xRg.Value
Range("B2").Value = ActiveSheet.Name
If Err.Number = 1004 Then
Debug.Print xRg.Value & " already used as a sheet name"
End If
On Error GoTo 0
End With
Next xRg
Application.ScreenUpdating = True
'Sort by Date
Sheets("Shifts").Select
Range("A1").Sort Key1:=Range("D1"), Order1:=xlAscending, Header:=xlYes
After this I need some kind of loop or switch case or Foreach - i don't know what exactly.
I have it hardcoded for now, but it will become bulky, slow and problematic to maintain.
What I need to do:
Go through the list of employees, find for the employee all data and copy it to his respective worksheet - which has already been created.
Here is the hardcoded version of the code:
ActiveSheet.Range("$A$1:$L$276").AutoFilter Field:=1, Criteria1:= _
"Employee name"
Range("A1").Select
Range(Selection, Selection.End(xlToRight)).Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Sheets("Employee name").Select
ActiveSheet.Paste
ActiveSheet.PageSetup.Orientation = xlPortrait
Columns("A:L").AutoFit
For Each r In Range("I:I").SpecialCells(xlCellTypeConstants)
r.Interior.ColorIndex = xlNone
If r.Value Like "*Home Office*" Then r.Interior.Color = vbGreen
If r.Value Like "*Neradni dan*" Then r.Interior.Color = vbRed
If r.Value Like "*Bolovanje*" Then r.Interior.Color = vbBlue
If r.Value Like "*Godišnji odmor*" Then r.Interior.ColorIndex = 29
Next
Columns("L").EntireColumn.Delete
Columns("J").EntireColumn.Delete
Columns("H").EntireColumn.Delete
Columns("C").EntireColumn.Delete
Columns("B").EntireColumn.Delete
Columns("G").EntireColumn.Delete
I copied the whole code below.
A clarification of what it needs to do:
sort the data in the first worksheet - already handled
create the worksheets by the names in the 3rd worksheet - working
On the first sheet, that is already "sorted" - I need to go through all the names, copy the the data that is relevant to the sheet - i.e the sheets are named by names that are found in row a. so i need it to go through the first worksheet, need all the data that has the same name in the row a and copy it to the respective sheet. - PLEASE HELP :)
Sub TEMPExcelObradiTablicuZaObracunPlaca()
'Convert Cell Format from Text to Date and change MDY to DMY Format
Sheets("Shifts").Select
Range("D2:D1000").Select
Selection.TextToColumns Destination:=Range("D2"), DataType:=xlFixedWidth, _
FieldInfo:=Array(0, 3), TrailingMinusNumbers:=True
Range("F2:F1000").Select
Selection.TextToColumns Destination:=Range("F2"), DataType:=xlFixedWidth, _
FieldInfo:=Array(0, 3), TrailingMinusNumbers:=True
'Ovdje dodajem potrebne Sheetove iz Members Sheeta
Sheets("Members").Select
Dim xRg As Excel.Range
Dim wSh As Excel.Worksheet
Dim wBk As Excel.Workbook
Set wSh = ActiveSheet
Set wBk = ActiveWorkbook
Application.ScreenUpdating = False
For Each xRg In wSh.Range("A2:A22")
With wBk
.Sheets.Add After:=.Sheets(.Sheets.Count)
ActiveCell.FormulaR1C1 = "Evidencija radnog vremena"
Selection.Font.Size = 20
Selection.Font.Bold = True
ActiveCell.Offset(1, 0).Range("A1").Select
ActiveCell.FormulaR1C1 = "Radnik"
Selection.Font.Size = 14
Selection.Font.Bold = True
ActiveCell.Offset(1, 0).Range("A1").Select
ActiveCell.FormulaR1C1 = "Godina i mjesec"
Selection.Font.Bold = True
ActiveCell.Offset(2, 0).Range("A1").Select
'Range("B2).Value = DateAdd(mmmm, yyyy) -> OVDJE SAM ZAPEO TU NASTAVITI!!! - dodavanje datuma u b2 celiju!
On Error Resume Next
ActiveSheet.Name = xRg.Value
Range("B2").Value = ActiveSheet.Name
If Err.Number = 1004 Then
Debug.Print xRg.Value & " already used as a sheet name"
End If
On Error GoTo 0
End With
Next xRg
Application.ScreenUpdating = True
'Sort by Date
Sheets("Shifts").Select
Range("A1").Sort Key1:=Range("D1"), Order1:=xlAscending, Header:=xlYes
'Define LASTROW to find the last row and column in Members Sheetu!
Dim LastRow As Long, LastColumn As Long
LastRow = Cells.Find(What:="*", After:=Range("A1"), SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
LastColumn = Cells.Find(What:="*", After:=Range("A1"), SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column
Range("A1").Resize(LastRow, LastColumn).Select
'Proba ForEach petlje
' Creating a range of sheet names from the data on Members
Dim SheetNamesRange As Range
Set SheetNamesRange = Sheets("Members").Range("A2:A" & LastRow)
' Iterate through all sheets in the range and write the word "Updated" in cell B2
Dim SheetName As Variant, SheetNameString As String
For Each SheetName In SheetNamesRange
' OVDJE SAM ISKOMENTIRAO OVA 2 REDA
'SheetNameString = CStr(SheetName)
'ThisWorkbook.Sheets(SheetNameString).Range("Q2") = "Updated"
Sheets("Shifts").Range("$A$1:$L$276").AutoFilter Field:=1, Criteria1:="SheetNameString"
Range("A1").Select
Range(Selection, Selection.End(xlToRight)).Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
'SheetNameString = CStr(SheetName)
Sheets.CStr(SheetNameString).Select
ActiveSheet.Paste
ActiveSheet.PageSetup.Orientation = xlPortrait
Columns("A:L").AutoFit
For Each r In Range("I:I").SpecialCells(xlCellTypeConstants)
r.Interior.ColorIndex = xlNone
If r.Value Like "*Home Office*" Then r.Interior.Color = vbGreen
If r.Value Like "*Neradni dan*" Then r.Interior.Color = vbRed
If r.Value Like "*Bolovanje*" Then r.Interior.Color = vbBlue
If r.Value Like "*Godišnji odmor*" Then r.Interior.ColorIndex = 29
Next
Columns("L").EntireColumn.Delete
Columns("J").EntireColumn.Delete
Columns("H").EntireColumn.Delete
Columns("C").EntireColumn.Delete
Columns("B").EntireColumn.Delete
Columns("G").EntireColumn.Delete
Next SheetName
End Sub
You are right, a For Each loop can be used here. Here is some code that outlines the basic principle:
Private Sub Shone()
' Creating a range of sheet names from the data on Sheet1
Dim SheetNamesRange As Range
Set SheetNamesRange = ThisWorkbook.Sheets("Sheet1").Range("A1:A3")
' Iterate through all sheets in the range and write the word "Updated" in cell B2
Dim SheetName As Variant, SheetNameString As String
For Each SheetName In SheetNamesRange
SheetNameString = CStr(SheetName)
ThisWorkbook.Sheets(SheetNameString).Range("B2") = "Updated"
Next SheetName
End Sub
In this example, I want to grab the names of sheets written on Sheet1, and write the word "Updated" in cell B2 on each of those sheets.
The cells A1, A2, and A3 on the sheet Sheet1 contain the following text, respectively, "Sheet1", "Sheet2", "Sheet3". First, I create a Range of data. That data is just the sheet names in cells A1:A3. It goes without saying that your Range will contain different data, but I believe that you have already taken care of that part.
Next, I iterate through that Range of data. A For Each loop requires the iterator (in this case, the variable SheetName) to be a Variant datatype. As I iterate through all of the sheets, I finally get to what I want to do: write the word "Updated" in cell B2. Finally, we reach the Next statement which tells us that the next step of the For Each loop will start, if there are any more members in the SheetNamesRange to iterate through.

Excel macro to search for a keyword and and copy the entire row to another sheet

I have a excel sheet with around 50k rows and i need a macro to search for a cell in that sheet and if it finds it to copy the entire row to another sheet, my problem is that the keyword may be on multiple rows so if there are like 4 cells with that keyword i need it to copy all 4 rows and paste them in another sheet
Dim intPasteRow As Integer
intPasteRow = 2
Sheets("Sheet2").Select
Columns("A:AV").Select
On Error Resume Next
Selection.Find(What:="m12", After:=ActiveCell, LookIn:= _
xlFormulas, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:= _
xlNext, MatchCase:=True, SearchFormat:=True).Activate
If Err.Number = 91 Then
MsgBox "ERROR: 'Keyword' could not be found."
Sheets("Sheet1").Select
End
End If
Dim intRow As Integer
intRow = ActiveCell.Row
Rows(intRow & ":" & intRow).Select
Selection.Copy
Sheets("Sheet1").Select
ActiveSheet.Paste
End Sub
Sub saci()
Dim rng As Range
Set rng = Range(ActiveCell, ActiveCell.Offset(10000, 0))
rng.EntireRow.Select
With Selection.EntireRow
.Cut
.Offset(.Rows.Count + 1).Insert
.Select
End With
Range("A4").Select
End Sub
so far its finding the first "m12" cell in Sheet2 and copies the entire row to Sheet1, how do i make it continue to search after finding "m12" and copy all rows with the "m12" in them instead of just the first one?

How to loop through a range of cells?

I have values in this "Sample Analysis Data" sheet in the range B2:B10.
For each cell in the range, the code looks for that value in the sheet "Meta Data". It then copies the cells in that row and pastes it in "Sample Analysis Data" (to the right of the searched value). This works for the value in B2.
I can't get it to move on to B3 and then B4 and such. It loops though and does the same thing again for B2.
What do I need to do to get it to loop to from B2 through to B10?
Along with this, how do I get it to go from B2 to the last entry in the column (as each data set I work with could have a different number of rows of data,) not just to B10?
Sub GetMetaData()
Worksheets("Sample Analysis Data").Activate
Range("B2").Select
Dim srch As Range, cell As Variant
Set srch = Range("B2:B10")
For Each cell In srch
Sheets("Meta Data").Activate
Cells.Find(What:=cell, LookIn:=xlValues, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False _
, SearchFormat:=False).Activate
ActiveSheet.Cells(ActiveCell.Row, 1).Select
Range(ActiveCell, ActiveCell.End(xlToRight).End(xlToRight)).Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Sample Analysis Data").Activate
ActiveCell.Offset(0, 7).Select
ActiveSheet.Paste
Next cell
End Sub
Try this?
Change the i=8 to however many cells you need to offset (you indicated B2:B10, which is 8)
Sub testcopy()
Dim srch As Range, metarg As Range, rg As Range, pstrg As Range
Dim i As Long
Dim ws As Worksheet, ws2 As Worksheet
Set ws = ThisWorkbook.Sheets("Sample Analysis Data")
Set ws2 = ThisWorkbook.Sheets("Meta Data")
Set metarg = ws2.Range("A1:A100") 'range that includes the key that you are searching in B2:B10
Set srch = ws.Range("B1") 'i'm offsetting, so i'm going back one row
For i = 1 To 8 'change 8 to how many cells to offset
Set rg = metarg.Find(srch.Offset(i, 0).Value, LookIn:=xlValues, lookat:=xlWhole) 'find the value in meta sheet
If Not rg Is Nothing Then
Set pstrg = ws2.Range(rg, ws2.Cells(rg.Row, rg.End(xlToRight).Column))
pstrg.Copy
srch.Offset(i, 1).PasteSpecial xlPasteValues
Application.CutCopyMode = False
End If
Next i
End Sub

How do you get a defined range address to show up as a relative reference in formula?

How I can get the the range address for rng3 to show up in my sum formula as a relative reference (ex. B2:B4) instead of as the range name?
The sum formula I am trying to use it for is giving a value of 0.
I am trying to copy the formula down the rest of column D.
It is for a range based on the last column in the spreadsheet that changes every week.
Sub needhelp ()
Dim rng1 As Range
Dim rng2 As Range
Dim rng3 As Range
Dim rng4 As Range
Dim fillrange As Range
Dim cell1 As Range
Dim cell2 As Range
Dim cellAddress As Range
Range("G1").Select
Range("G1").End(xlToRight).Select
ActiveCell.Offset(1, 0).Select
ActiveCell.Offset(0, -2).Select
Set cell1 = ActiveCell
Set rng1 = Cells.Find("*", [cell1], , , xlByColumns, xlNext)
ActiveCell.Offset(0, 2).Select
Set cell2 = ActiveCell
Set rng2 = Cells.Find("*", [cell2], , , xlByColumns, xlPrevious)
If Not rng2 Is Nothing Then
Set rng3 = Range([cell1], [cell2])
MsgBox "Range is " & rng3.Address(0, 0)
Application.Goto rng3
MsgBox "Range is " & rng3.Address(0, 0)
Application.Goto rng3
Range("D2").Select
' *** Here is when I need help.
Worksheets("Confidential").Range("D2").Formula = "=SUM(rng3) / 3"
ActiveCell.Offset(0, -1).Select
Selection.End(xlDown).Select
ActiveCell.Offset(0, 1).Select
Range(Selection, Selection.End(xlUp)).Select
Cells.Select
Cells.EntireColumn.AutoFit
End If
End Sub
I also tried the following (did not work):
' Debug.Print Range("rng4").Address(External:=True)
' Try to use this to fill average range with formula using loop (some other time):
' ActiveWorkbook.Names.Add Name:="fillrange", RefersTo:=Selection
' Range("D2").Select
' ActiveWorkbook.Names.Add Name:="", RefersTo:=Selection
Your formula should be:
"=SUM(" & rng3.Address(0,0) & ") / 3"
You need to quote out the vba.
Also, all the .Select slow down the code. See THIS POST for methods to avoid using it. It will speed up the code.

Search and paste data from sheet 2 to sheet 1 form

I have Sheet1 which is a form with fields where we enter data to be fed in the database (Sheet2).
Ideally, here's what I want it to do:
I want to search a field/record using the form contents in Sheet1, then search for that term on Sheet2. If it doesn't exist on Sheet2, give me a pop up message saying data doesn't exist.
If it does exist in Column A on Sheet2, then select the cell to the right of the result (Column B). Then paste that cell's contents in relevant fields on Sheet1
Then continue until all of the fields on Sheet1 has been searched for on Sheet2.
Here's the code I've been using. It only works for about 5 lines before it comes up with an error. Any help would be greatly appreciated.
I really don't want the MsgBox to pop up at all.
Sub abc()
Do Until IsEmpty(ActiveCell)
Dim MyString As String
MyString = ActiveCell
Sheets("Sheet2").Select
Set RangeObj = Cells.Find(What:=MyString, After:=ActiveCell, _
LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False)
If RangeObj Is Nothing Then MsgBox "Not Found" Else: RangeObj.Select
ActiveCell.Offset(0, 1).Range("A1").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Sheet1").Select
ActiveCell.Offset(0, 1).Range("A1").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
ActiveCell.Offset(-1, -1).Select
Loop
End Sub
Please let me know what I'm doing wrong.
You were on the right path.. just a few amendments to how you were copying the data.
Option Explicit
Sub sheet2_lookup()
Dim strVal As String
Dim wb As Workbook, ws1 As Worksheet, ws2 As Worksheet, RangeObj As Range
Set wb = ThisWorkbook
Set ws1 = wb.Sheets("Sheet1")
Set ws2 = wb.Sheets("Sheet2")
Cells(1, 1).Activate '' amend this to your starting cell
While ActiveCell.Value2 <> ""
strVal = ActiveCell.Value2
Set RangeObj = ws2.Columns("A").Find(What:=strVal, After:=Cells(1, 1), LookIn:=xlValues)
If RangeObj Is Nothing Then
MsgBox "Not Found"
Else
ActiveCell.Offset(0, 1).Value2 = RangeObj.Offset(0, 1).Value2
End If
ActiveCell.Offset(1, 0).Activate
Wend
End Sub
Let me know how it goes.

Resources