find and select the finding until the next find - excel

Basically, I'm writing a code that finds text in a Master sheet, I am looking for "Admin" after finding the admin I need to select from this cell unit next find and paste in separate sheets.
I tried different ways but now work, any suggestions?
Example
Sub FindNext_Example()
Dim FindValue As String
FindValue = "Bangalore"
Dim Rng As Range
Set Rng = Range("A2:A11")
Dim FindRng As Range
Set FindRng = Rng.Find(What:=FindValue)
Dim FirstCell As String
FirstCell = FindRng.Address
Do
Range(FristCell).Select
Selection.Copy
Worksheets.Add
ActiveSheet.Paste
Sheets("Sheet0").Select
Set FindRng = Rng.FindNext(FindRng)
Loop While FirstCell <> FindRng.Address
MsgBox "Search is over"
End Sub
Example
Example of finding and select the find row until next find
paste in new sheet
next find
until the end

Try this code:
Sub SubChopList()
'Declarations.
Dim DblColumnOffset As Double
Dim RngSource As Range
Dim RngSearch As Range
Dim RngTop As Range
Dim RngBottom As Range
Dim StrSearch As String
Dim StrDestinationAddress As String
Dim WksSource As Worksheet
'Settings.
Set WksSource = ActiveSheet
Set RngSource = WksSource.Range("A1")
Set RngSource = Range(RngSource, RngSource.End(xlDown).End(xlToRight))
'Setting DblColumnOffset equal to the offset from the first column of RngSource and the column to be searched.
DblColumnOffset = 2
'Setting the column to be searched.
Set RngSearch = RngSource.Columns(1).Offset(0, DblColumnOffset)
'Setting the value to be searched.
StrSearch = "Admin"
'Setting the address of the cell where the data will be pasted in the new sheets.
StrDestinationAddress = "A1"
'Setting RngTop as the first cell that contains StrSearch after the first cell of RngSearch.
Set RngTop = RngSearch.Find(What:=StrSearch, _
After:=RngSearch.Cells(1, 1), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False _
)
'Setting RngBottom as the cell in the row upon the first cell that contains StrSearch after RngTop.
Set RngBottom = RngSearch.Find(What:=StrSearch, _
After:=RngTop, _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False _
).Offset(-1, 0)
'Repeating until the last block is reached.
Do
'Creating a new sheet.
Worksheets.Add
'Copy-pasting the block delimited by RngTop and RngBottom in the new sheet at the address specified in StrDestinationAddress.
WksSource.Range(RngTop, RngBottom).Offset(0, -DblColumnOffset).Resize(, RngSource.Columns.Count).Copy Range(StrDestinationAddress)
'Setting RngTop as the first cell that contains StrSearch after RngBottom.
Set RngTop = RngSearch.Find(What:=StrSearch, _
After:=RngBottom, _
LookIn:=xlFormulas, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False _
)
'Setting RngBottom as the cell in the row upon the first cell that contains StrSearch after RngTop.
Set RngBottom = RngSearch.Find(What:=StrSearch, _
After:=RngTop, _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False _
).Offset(-1, 0)
Loop Until RngTop.Row > RngBottom.Row
'Reporting the last block as did for all the previous blocks in the Do Loop cycle.
Set RngBottom = RngSearch.Cells(RngSearch.Rows.Count, 1)
Worksheets.Add
WksSource.Range(RngTop, RngBottom).Offset(0, -DblColumnOffset).Resize(, RngSource.Columns.Count).Copy Range(StrDestinationAddress)
End Sub
Select the sheet with the data you want to chop and run it.

Create Criteria Worksheets
Adjust the values in the constants section.
The Code
Option Explicit
Sub addCriteriaWorksheets()
Const wsName As String = "Sheet1"
Const sCellAddress As String = "A1"
Const Criteria As String = "Admin*"
Const CriteriaColumn As Long = 3
Const dCellAddress As String = "A1"
Dim wb As Workbook: Set wb = ThisWorkbook
Application.ScreenUpdating = False
With wb.Worksheets(wsName).Range(sCellAddress).CurrentRegion
.Worksheet.AutoFilterMode = False
.AutoFilter CriteriaColumn, Criteria
Dim rg As Range
On Error GoTo SpecialCellsError
Set rg = .Columns(CriteriaColumn).Resize(.Rows.Count - 1).Offset(1) _
.SpecialCells(xlCellTypeVisible)
On Error GoTo 0
Dim nCount As Long: nCount = rg.Cells.Count
Dim Coord As Variant: ReDim Coord(1 To nCount, 1 To 3)
Dim arg As Range
Dim cel As Range
Dim n As Long
For Each arg In rg.Areas
For Each cel In arg.Cells
n = n + 1
Coord(n, 1) = cel.Row
If n > 1 Then
Coord(n - 1, 2) = Coord(n, 1) - 1
Coord(n - 1, 3) = Coord(n - 1, 2) - Coord(n - 1, 1) + 2
End If
Next cel
Next arg
n = n + 1
Coord(n - 1, 2) = .Rows.Count
Coord(n - 1, 3) = Coord(n - 1, 2) - Coord(n - 1, 1) + 2
.Worksheet.AutoFilterMode = False
Dim cCount As Long: cCount = .Columns.Count
Dim Data As Variant: Data = .Value
Dim Result As Variant
Dim i As Long, j As Long, k As Long
For n = 1 To nCount
ReDim Result(1 To Coord(n, 3), 1 To cCount)
For j = 1 To cCount
Result(1, j) = Data(1, j)
Next j
k = 1
For i = Coord(n, 1) To Coord(n, 2)
k = k + 1
For j = 1 To cCount
Result(k, j) = Data(i, j)
Next j
Next i
With wb.Worksheets.Add(After:=wb.Sheets(wb.Sheets.Count))
.Range(dCellAddress).Resize(k, cCount).Value = Result
End With
Next n
.Worksheet.Select
End With
ProcExit:
Application.ScreenUpdating = True
Exit Sub
SpecialCellsError:
Resume ProcExit
End Sub

Related

Find last column with data and add data after that column

I have some data in my worksheet and what I want to achieve is that I want to add data after 1 column from the last column with data.
I have tried the Range().End property but I think I am not able to implement it correctly.
colnum = Sheet3.Range("A:Z").End(xlToLeft).Column + 2
The above code gives me the column number as '1' and plus 2 means it gives column number '3' which is 'C'.
Data in my worksheet is something like this:
I want a dynamic search and my code should find column 'E' as the last column with data and start adding data from column 'F'. Any suggestions are appreciated.
This function returns an array where the first element is the last row number, and the second element the last column number.
Function LastRowCol(Worksht) As Long()
'Uncomment if on worksheet
'Application.Volatile
Dim WS As Worksheet, R As Range
Dim LastRow As Long, LastCol As Long
Dim L(1) As Long
Select Case TypeName(Worksht)
Case "String"
Set WS = Worksheets(Worksht)
Case "Worksheet"
Set WS = Worksht
End Select
With WS
Set R = .Cells.Find(what:="*", after:=.Cells(1, 1), _
LookIn:=xlFormulas, lookat:=xlPart, searchorder:=xlByRows, _
searchdirection:=xlPrevious)
If Not R Is Nothing Then
LastRow = R.Row
LastCol = .Cells.Find(what:="*", after:=.Cells(1, 1), _
LookIn:=xlFormulas, lookat:=xlPart, searchorder:=xlByColumns, _
searchdirection:=xlPrevious).Column
Else
LastRow = 1
LastCol = 1
End If
End With
L(0) = LastRow
L(1) = LastCol
LastRowCol = L
End Function
Sub change_code_name()
'Requires Trust Access to VBA Object Model
Dim wbk As Object, sheet As Object
ActiveWorkbook.VBProject.name = "VBAProject"
Set wbk = ActiveWorkbook.VBProject.VBComponents(ActiveWorkbook.CodeName)
wbk.name = "wbk_code_name"
Set sheet = ActiveWorkbook.VBProject.VBComponents(ActiveWorkbook.Sheets(1).CodeName)
sheet.name = "sheet_code_name"
End Sub
In the case of your code line, assuming your worksheet CodeName is Sheet3, it would be something like:
colnum = LastRowCol(Sheet3)(1) + 1
and would apply to the active workbook.
See also Error in finding last used cell in Excel with VBA for an extensive discussion of the various methods of finding the last row/column and the pitfalls of each.
Edit:
Examining your screenshot, it seems that you might want to exclude Row 1 from the testing. If that is the case, then try this slightly modified code:
Option Explicit
Function LastRowCol(Worksht, Optional excludeRows As Long = 0) As Long()
'Uncomment if on worksheet
'Application.Volatile
Dim WS As Worksheet, R As Range
Dim LastRow As Long, LastCol As Long
Dim L(1) As Long
Dim searchRng As Range
Select Case TypeName(Worksht)
Case "String"
Set WS = Worksheets(Worksht)
Case "Worksheet"
Set WS = Worksht
End Select
If excludeRows > 0 Then
With WS
Set searchRng = Range(.Cells(excludeRows + 1, 1), .Cells(.Rows.Count, .Columns.Count))
End With
Else
Set searchRng = WS.Cells
End If
With searchRng
Set R = .Cells.Find(what:="*", after:=.Cells(1, 1), _
LookIn:=xlFormulas, lookat:=xlPart, searchorder:=xlByRows, _
searchdirection:=xlPrevious)
If Not R Is Nothing Then
LastRow = R.Row
LastCol = .Cells.Find(what:="*", after:=.Cells(1, 1), _
LookIn:=xlFormulas, lookat:=xlPart, searchorder:=xlByColumns, _
searchdirection:=xlPrevious).Column
Else
LastRow = 1
LastCol = 1
End If
End With
L(0) = excludeRows + 1
L(1) = LastCol
LastRowCol = L
End Function
and, in your macro:
colnum = LastRowCol(Sheet3,1)(1) + 1

How can I use advanced filter if I have the criteria in a cell?

The cell is going to change the value and it is in different locations of the worksheet. The point is that I haven't been able that my macro understand that criteria that is located in the last cell of a column, the second in this case
This is the code that I am using
Public Sub Excel()
Dim T#, crit As Range, Data As Range, ws As Worksheet
Dim r&, fc As Range, lc As Range, fr1 As Range, fr2 As Range
Dim year%
year = 2019
Set fc = ActiveSheet.UsedRange.Item(1)
Set lc = GetMaxCell
Set Data = ActiveSheet.Range(fc, lc)
Set ws = Sheets.Add
With Data
Set fr1 = Data.Worksheet.Range(fc, fc.Offset(, lc.Column))
Set fr2 = ws.Range(ws.Cells(fc.Row, fc.Column), ws.Cells(fc.Row, lc.Column))
With fr2
fr1.Copy
.PasteSpecial xlPasteColumnWidths: .PasteSpecial xlPasteAll
.Item(1).Select
End With
Set crit = .Resize(2, 1).Offset(, lc.Column + 1)
'This is the part that I need to understand
crit = [{"AÑO";<>lRow)}]
.AdvancedFilter xlFilterCopy, crit, fr2
.Worksheet.Delete
End With
End Sub
Public Function GetMaxCell(Optional ByRef rng As Range = Nothing) As Range
'Returns the last cell containing a value, or A1 if Worksheet is empty
Const NONEMPTY As String = "*"
Dim lRow As Range, lCol As Range
If rng Is Nothing Then Set rng = Application.ActiveWorkbook.ActiveSheet.UsedRange
If WorksheetFunction.CountA(rng) = 0 Then
Set GetMaxCell = rng.Parent.Cells(1, 1)
Else
With rng
Set lRow = .Cells.Find(What:=NONEMPTY, LookIn:=xlFormulas, _
After:=.Cells(1, 1), _
SearchDirection:=xlPrevious, _
SearchOrder:=xlByRows)
If Not lRow Is Nothing Then
Set lCol = .Cells.Find(What:=NONEMPTY, LookIn:=xlFormulas, _
After:=.Cells(1, 1), _
SearchDirection:=xlPrevious, _
SearchOrder:=xlByColumns)
Set GetMaxCell = .Parent.Cells(lRow.Row, lCol.Column)
End If
End With
End If
End Function
Thanks for your help

Trying to paste entire workbooks at the bottom of another workbook

So it's working but it's pasting with 10 empty rows above and I am not sure why.
Sub Stuffff()
Dim Rng As Range
Set Rng = ThisWorkbook.Worksheets("Sheet2").Range("A1:AY300")
Rng.Copy
Dim s11 As Workbook
Set s11 = Workbooks("11 Production")
Dim last As Long
Dim Rngnew As Range
With s11.Sheets("Sheet1")
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
last = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
Else
last = 1
End If
End With
Set Rngnew = s11.Worksheets("Sheet1").Range("A" & last + 1)
Rngnew.PasteSpecial
End Sub
Maybe you could try :
Sub Stuffff()
Dim Rng As Range
Set Rng = ThisWorkbook.Worksheets("Sheet2").Range("A1:AY300")
Rng.Copy
Dim s11 As Workbook
Set s11 = Workbooks("11 Production")
Dim last As Long
Dim Rngnew As Range
With s11.Sheets("Sheet1")
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
last = .range("A65000").end(xlup).offset(1,0).row
Else
last = 1
End If
End With
Set Rngnew = s11.Worksheets("Sheet1").Range("A" & last)
Rngnew.PasteSpecial
End Sub
That should work, unless you have more than 65 K rows in your workbook.

Set variable column in search looping through worksheets not working,

I'm working on a macro that needs to find every value in a range in "sheet1" and search for it in all the sheets of the workbook (may be up to 7 sheets), as it takes too long, looking for the values in the entire sheets, I would like to reduce the search field on each sheet up to one variable column with header IP.
This is the macro I have so far, but I can't get it to work only on that specified range, however, removing those lines makes the macro work ok.
Thank you in advance.
Sub findInventory()
Dim ws As Worksheet
Dim strWhat, rngFound, mString As String
Dim rngSearch, osfind, rfind, rfcol As Range
Dim i, x As Integer
Dim LastRow, oscol, lcol, e, lrowA, remChar, fcol As Long
Sheets("GVM Report").Cells(1, 1).Offset(0, 1).Resize(, 2).EntireColumn.Insert
Sheets("GVM Report").Cells(1, 1).Offset(0, 1).Value = "INVENTORY"
Sheets("GVM Report").Cells(1, 1).Offset(0, 2).Value = "OPSDB"
Set rfind = ActiveWorkbook.Sheets("GVM Report").Rows("1:3").Find(What:="IP", LookAt:=xlWhole, MatchCase:=False, SearchFormat:=False)
lcol = rfind.Column
Set osfind = ActiveWorkbook.Sheets("GVM Report").Rows("1:3").Find(What:="OS*", LookAt:=xlWhole, MatchCase:=False, SearchFormat:=False)
oscol = osfind.Column
LastRow = Sheets("GVM Report").Range("A" & Rows.Count).End(xlUp).Row
For x = 2 To LastRow
strWhat = Sheets("GVM Report").Cells(x, lcol)
For Each ws In Worksheets
Set rfcol = ws.Rows("1:3").Find(What:="IP", LookAt:=xlWhole, MatchCase:=False, SearchFormat:=False)
fcol = rfcol.Column
With ws.Columns(fcol)
Select Case ws.name
Case "Operations", "Data", "FYI all OS", "Unique Values", "GVM Report"
Case Else
Set rngSearch = ws.Cells.Find(What:=strWhat)
If strWhat <> "" Then
If Not rngSearch Is Nothing Then
i = i + 1
If i = 1 Then
rngFound = rngSearch.Worksheet.name
Else
rngFound = rngFound & " | " & rngSearch.Worksheet.name
End If
End If
End If
Sheets("GVM Report").Cells(x, 2) = rngFound
End Select
End With
Next ws
rngFound = ""
i = 0
Next x
End Sub
I'm not sure if I can replicate your error, but I've tidied up your code a little and it might be useful for you, so here it goes:
Sub findInventory()
Dim ws As Worksheet
Dim wsGVM As Worksheet: Set wsGVM = ThisWorkbook.Sheets("GVM Report")
Dim strWhat As String, rngFound As String, mString As String
Dim rngSearch As Range, osfind As Range, rfind As Range, rfcol As Range
Dim i As Integer, x As Long, LastRow As Long, oscol As Long, lcol As Long, fcol As Long
wsGVM.Cells(1, 1).Offset(0, 1).Resize(, 2).EntireColumn.Insert
wsGVM.Cells(1, 1).Offset(0, 1).Value = "INVENTORY"
wsGVM.Cells(1, 1).Offset(0, 2).Value = "OPSDB"
Set rfind = wsGVM.Rows("1:3").Find(What:="IP", LookAt:=xlWhole, MatchCase:=False, SearchFormat:=False)
If Not rfind Is Nothing Then lcol = rfind.Column
Set osfind = wsGVM.Rows("1:3").Find(What:="OS*", LookAt:=xlWhole, MatchCase:=False, SearchFormat:=False)
If Not osfind Is Nothing Then oscol = osfind.Column
LastRow = wsGVM.Range("A" & Rows.Count).End(xlUp).Row
For x = 2 To LastRow
strWhat = wsGVM.Cells(x, lcol)
For Each ws In Worksheets
Set rfcol = ws.Rows("1:3").Find(What:="IP", LookAt:=xlWhole, MatchCase:=False, SearchFormat:=False)
If Not rfcol Is Nothing Then
fcol = rfcol.Column
With ws.Columns(fcol)
Select Case ws.Name
Case "Operations", "Data", "FYI all OS", "Unique Values", "GVM Report"
''''
Case Else
If strWhat <> "" Then
Set rngSearch = .Find(What:=strWhat)
If Not rngSearch Is Nothing Then
i = i + 1
If i = 1 Then
rngFound = rngSearch.Worksheet.Name
Else
rngFound = rngFound & " | " & rngSearch.Worksheet.Name
End If
End If
End If
wsGVM.Cells(x, 2) = rngFound
End Select
End With
End If
Next ws
rngFound = ""
i = 0
Next x
End Sub
I did a test with dummy'ed up data and got the following results:
INVENTORY
Sheet2 | Sheet3
Sheet2
Sheet3
which is consistent with what I would expect given the dummy data I created. Perhaps there are leading, trailing spaces or other non-visible difference that cause a data mismatch on cells that appear to be equal?

Find two consecutive numbers

I have this code, but I'd like for it to find two adjacent cells with the values 7 and 2 (7 first in every pair) in column A and offset (from the 7) to the next column and insert a value to a specific row range.
Sub mark()
Dim FirstAddress As String
Dim MyArr As Variant
Dim Rng As Range
Dim I As Long
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
MyArr = Array("X")
With Sheets("Sheet1").Range("A:A")
.Offset(0, 1).ClearContents
For I = LBound(MyArr) To UBound(MyArr)
Set Rng = .Find(What:=MyArr(I), _
After:=.Cells(.Cells.Count), _
LookIn:=xlFormulas, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
FirstAddress = Rng.Address
Do
Rng.Offset(0, 1).Value = "X"
Set Rng = .FindNext(Rng)
Loop While Not Rng Is Nothing And Rng.Address <> FirstAddress
End If
Next I
End With
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
Any suggestions appreciated.
Please try this code. I have expanded it to provide for specifying different results to be inserted at the found location.
Sub Mark2()
' 14 Feb 2018
Dim Ws As Worksheet
Dim Crits() As Variant
Dim Fun() As Variant
Dim MarkRng As Range
Dim R As Long
Dim i As Long
Dim Count As Integer
Set Ws = Worksheets("FindPair") ' replace with actual name
Crits = Array(7, 2, 13, 3, 17, 4) ' 1st, 2nd, 1st, 2nd, 1st, 2nd criterium
' Match the ranges in Fun() to the targets in Crits()
' 2 ranges for each Crit, each range 1 or more cells
' Omitted ranges must be represented by a comma
' Fun ranges specified in excess of available space will be ignored
' (for example, A32 + B28:B32 = 6 cells but MarkRng has only 5 cells)
Fun = Array("A32", "B28:B32", "A33:A35", "B33:B34", , "B100:B104")
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
For i = LBound(Crits) To UBound(Crits) Step 2
Count = 0
Do
R = MatchRow(Crits(i), Ws, (R = 0))
If R Then
With Ws
If .Cells(R + 1, 1).Value = Crits(i + 1) Then
' column 2 = column B
Set MarkRng = Range(.Cells(R, 2), .Cells(R + 5, 2))
WriteResult i, Fun, MarkRng
Count = Count + 1
End If
End With
Else
If Count = 0 Then
MsgBox "No match was found for " & Crits(i), _
vbInformation, "Failure advice"
End If
Exit Do
End If
Loop
Next i
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
Private Function MatchRow(ByVal Crit As Variant, _
Ws As Worksheet, _
ByVal NewSearch As Boolean) As Long
' 13 Feb 2018
Static Rng As Range
Static Rstart As Long
Static Rend As Long
Dim Fnd As Range
With Ws
If NewSearch Then
Rstart = 2 ' start search in row 2
' find last used row
Rend = .Cells(.Rows.Count, 1).End(xlUp).Row
End If
Set Rng = Range(.Cells(Rstart, 1), .Cells(Rend, 1))
End With
With Rng
Set Fnd = .Find(What:=Crit, _
After:=.Cells(.Cells.Count), _
LookIn:=xlFormulas, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
End With
If Not Fnd Is Nothing Then
MatchRow = Fnd.Row
Rstart = Fnd.Row + 1
End If
End Function
Private Sub WriteResult(ByVal Ix As Long, _
Fun() As Variant, _
Target As Range)
' 14 Feb 2018
Dim Ws As Worksheet
Dim Rng As Range, R As Long ' source
Dim Rt As Long
Dim i As Long
With Target
Set Ws = .Worksheet
For i = 0 To 1
If Not IsError(Fun(Ix + i)) Then
Set Rng = Ws.Range(Fun(Ix + i))
For R = 1 To Rng.Cells.Count
If Rt < .Cells.Count Then
Rt = Rt + 1
.Cells(Rt).Value = Rng.Cells(R).Value
End If
Next R
End If
Next i
End With
End Sub

Resources