copy rows from one sheet to another with multiple criteria - vba

I'm working on a macro that will search a List sheet for different counties and then paste the entire row onto the current sheet. I have a worksheet for each person (named Mark, John, etc.) and each person is assigned several counties. Mark has three counties, listed in cells J1:L1, which I've named as a range (MyCounties). I need a macro that will look through Sheet "List" column "I" for each of those counties and copy the entire row onto Sheet "Mark" starting at "A4". I'm using a modified macro I found on here, but I must be doing something wrong. It is currently giving me an error "Application defined or object defined error" in regards to Set Rng = Sheets("List").Range([I4], Range("I" & Rows.Count).End(xlUp))
Sub NewSheetData()
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
Dim Rng As Range, rCell As Range
Set Rng = Sheets("List").Range([I4], Range("I" & Rows.Count).End(xlUp))
For Each rCell In Range("MyCounties")
On Error Resume Next
With Rng
.AutoFilter , field:=1, Criteria1:=rCell.Value
.Offset(1).SpecialCells(xlCellTypeVisible).EntireRow.Copy _
Sheets("Sheet2").Range("A" & Rows.Count).End(xlUp).Offset(1)
.AutoFilter
End With
On Error GoTo 0
Next rCell
Application.EnableEvents = True
End Sub

This code will need to be adjusted to accommodate your named ranges and worksheet names. It currently uses named ranges with worksheet scope from each worksheet.
Sub NewSheetData()
Dim w As Long, sWSs As Variant, vCrit As Variant, rw As Long
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
sWSs = Array("Mark", "John", "etc")
For w = LBound(sWSs) To UBound(sWSs)
With Worksheets(sWSs(w))
vCrit = .Range("MyCounties").Value2
rw = Application.Max(.Cells(.Rows.Count, "A").End(xlUp).Row + 1, 4)
End With
With Worksheets("List")
If .AutoFilterMode Then .AutoFilterMode = False
With .Range(.Cells(4, "I"), .Cells(.Rows.Count, "I").End(xlUp))
.AutoFilter field:=1, Criteria1:=vCrit, Operator:=xlFilterValues
With .Offset(1, 0).Resize(.Rows.Count - 1, .Columns.Count)
If CBool(Application.Subtotal(103, .Cells)) Then
.Cells.EntireRow.Copy Destination:=Worksheets(sWSs(w)).Cells(rw, "A")
End If
End With
End With
If .AutoFilterMode Then .AutoFilterMode = False
End With
Next w
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
This uses the values from each worksheet's MyCounties named range as an array of criteria for .AutoFilter. using an array as criteria requires the Operator:=xlFilterValues parameter. It also checks to make sure that there are filtered values to copy before copying them.

may be your EntireRow is copying rows whose first column is blank
you could use UsedRange property of worksheet object to get the last used row
furthermore you'd better place With Rng oustide the loop, since it doesn't change with it
Option Explicit
Sub NewSheetData()
Dim Rng As Range, rCell As Range
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
With Sheets("List")
Set Rng = .Range("I4", .Range("I" & .Rows.Count).End(xlUp))
End With
With Rng
For Each rCell In Range("MyCounties")
.AutoFilter , Field:=1, Criteria1:=rCell.Value
If Application.WorksheetFunction.Subtotal(103, .cells) > 1 Then .Resize(.Rows.Count - 1).Offset(1).EntireRow.Copy _
Sheets("Sheeta2").Range("A" & Sheets("Sheeta2").UsedRange.Rows(Sheets("Sheeta2").UsedRange.Rows.Count).Row).Offset(1)
Next
.Parent.AutoFilterMode = False
End With
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub

Related

Best way to create multiple Excel workbooks from a master file and the files must use an existing template with mutiple worksheets

I am trying to write code for a project. There is a preexisting template from the client. I need to create new files by dividing one master excel file into new files. The files must use the template which has multiple worksheets. The data will be separated by Identification numbers, but some files will have thousands of data rows. I am trying to write visual basic code to create the files, but am having some difficulty. Any suggestions are greatly appreciated.
Something like this should be pretty close.
Sub Copy_With_AutoFilter2()
'Note: This macro use the function LastRow
'Important: The DestSh must exist
Dim My_Range As Range
Dim DestSh As Worksheet
Dim CalcMode As Long
Dim ViewMode As Long
Dim FilterCriteria As String
Dim CCount As Long
Dim rng As Range
'Set filter range on ActiveSheet: A1 is the top left cell of your filter range
'and the header of the first column, D is the last column in the filter range.
'You can also add the sheet name to the code like this :
'Worksheets("Sheet1").Range("A1:D" & LastRow(Worksheets("Sheet1")))
'No need that the sheet is active then when you run the macro when you use this.
Set My_Range = Range("A1:D" & LastRow(ActiveSheet))
My_Range.Parent.Select
'Set the destination worksheet
'Note: the sheet "RecordsOfTheNetherlands" must exist in your workbook
Set DestSh = Sheets("RecordsOfTheNetherlands")
If ActiveWorkbook.ProtectStructure = True Or _
My_Range.Parent.ProtectContents = True Then
MsgBox "Sorry, not working when the workbook or worksheet is protected", _
vbOKOnly, "Copy to new worksheet"
Exit Sub
End If
'Change ScreenUpdating, Calculation, EnableEvents, ....
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
.EnableEvents = False
End With
ViewMode = ActiveWindow.View
ActiveWindow.View = xlNormalView
ActiveSheet.DisplayPageBreaks = False
'Firstly, remove the AutoFilter
My_Range.Parent.AutoFilterMode = False
'Filter and set the filter field and the filter criteria :
'This example filter on the first column in the range (change the field if needed)
'In this case the range starts in A so Field 1 is column A, 2 = column B, ......
'Use "<>Netherlands" as criteria if you want the opposite
My_Range.AutoFilter Field:=1, Criteria1:="=Netherlands"
'If you want to filter on a cell value you can use this, use "<>" for the opposite
'This example uses the activecell value
'My_Range.AutoFilter Field:=1, Criteria1:="=" & ActiveCell.Value
'This will use the cell value from A2 as criteria
'My_Range.AutoFilter Field:=1, Criteria1:="=" & Range("A2").Value
''If you want to filter on a Inputbox value use this
'FilterCriteria = InputBox("What text do you want to filter on?", _
' "Enter the filter item.")
'My_Range.AutoFilter Field:=1, Criteria1:="=" & FilterCriteria
'Check if there are not more then 8192 areas(limit of areas that Excel can copy)
CCount = 0
On Error Resume Next
CCount = My_Range.Columns(1).SpecialCells(xlCellTypeVisible).Areas(1).Cells.Count
On Error GoTo 0
If CCount = 0 Then
MsgBox "There are more than 8192 areas:" _
& vbNewLine & "It is not possible to copy the visible data." _
& vbNewLine & "Tip: Sort your data before you use this macro.", _
vbOKOnly, "Copy to worksheet"
Else
'Copy the visible data and use PasteSpecial to paste to the Destsh
With My_Range.Parent.AutoFilter.Range
On Error Resume Next
' Set rng to the visible cells in My_Range without the header row
Set rng = .Offset(1, 0).Resize(.Rows.Count - 1, .Columns.Count) _
.SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If Not rng Is Nothing Then
'Copy and paste the cells into DestSh below the existing data
rng.Copy
With DestSh.Range("A" & LastRow(DestSh) + 1)
' Paste:=8 will copy the columnwidth in Excel 2000 and higher
' Remove this line if you use Excel 97
.PasteSpecial Paste:=8
.PasteSpecial xlPasteValues
.PasteSpecial xlPasteFormats
Application.CutCopyMode = False
End With
'Delete the rows in the My_Range.Parent worksheet
'rng.EntireRow.Delete
End If
End With
End If
'Close AutoFilter
My_Range.Parent.AutoFilterMode = False
'Restore ScreenUpdating, Calculation, EnableEvents, ....
ActiveWindow.View = ViewMode
Application.Goto DestSh.Range("A1")
With Application
.ScreenUpdating = True
.EnableEvents = True
.Calculation = CalcMode
End With
End Sub
Function LastRow(sh As Worksheet)
On Error Resume Next
LastRow = sh.Cells.Find(What:="*", _
After:=sh.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlValues, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
On Error GoTo 0
End Function
https://www.rondebruin.nl/win/s3/win006_2.htm

if cell contains specific text, copy whole row

I'm trying to create a macro that does this:
Check the values from a small list (I've used an array)
Go in a worksheet and for every row that contains one of the values of the array copy the entire row in another worksheet.
I've mixed other macros to create one but I got one problem, the macro check the value on the array and copies all the rows in my worksheet but every time it doesn't copy the first row found: ex, if row that contain "abl" are: 100,200 and 300, the macro just copy 200 and 300 ignoring 100.
This is my macro
Sub Test_339_1()
With Application
.Calculation = xlCalculationManual
.ScreenUpdating = False
Dim nam(1 To 7) As String, cel As Range, rng As Range
i = 1
Set rng = Worksheets("Ctr 339").Range("V4:V10")
For Each cel In rng
nam(i) = cel.Value
i = i + 1
Next cel
For i = 1 To 7
For Each cell In Sheets("FB03").Range("E:E")
If cell.Value = nam(i) Then
matchRow = cell.Row
Rows(matchRow & ":" & matchRow).Copy
Sheets("Test_macro").Select
ActiveSheet.Rows(matchRow).Select
ActiveSheet.Paste
Sheets("FB03").Select
End If
Next
Sheets("Test_macro").Select
Next i
Sheets("Test_macro").Select
On Error Resume Next
Range("A1:A50000").Select
Selection.SpecialCells(xlCellTypeBlanks).EntireRow.Delete
.Calculation = xlCalculationAutomatic
.ScreenUpdating = True
End With
End Sub
Try this refactored code:
Sub Test_339_1()
Dim nam(1 To 7) As String, cel As Range, lastrow As Long
With Application
.Calculation = xlCalculationManual
.ScreenUpdating = False
nam = Worksheets("Ctr 339").Range("V4:V10").Value
lastrow = Sheets("FB03").Cells(Sheets("FB03").Rows.Count, "E").End(xlUp).Row
For Each cell In Sheets("FB03").Range("E1:E" & lastrow)
For i = 1 To 7
If cell.Value = nam(i) Then
matchRow = cell.Row
Sheets("FB03").Rows(matchRow).Copy Sheets("Test_macro").Rows(Sheets("Test_macro").Cells(Sheets("Test_macro").Rows.Count, "E").End(xlUp).Row + 1)
Exit For
End If
Next i
Next cell
.Calculation = xlCalculationAutomatic
.ScreenUpdating = True
End With
End Sub
It should be quicker, It will not loop over 7 million times.
AutoFilter() should speed things up quite a bit:
Option Explicit
Sub Test_339_1()
Dim nam As Variant
nam = Application.Transpose(Worksheets("Ctr 339").Range("V4:V10").Value)
With Sheets("FB03")
With .Range("E1", .Cells(.Rows.Count, "E").End(xlUp))
.AutoFilter Field:=1, Criteria1:=nam, Operator:=xlFilterValues '<--| filter referenced range on its 3rd column (i.e. "State") with 1
If Application.WorksheetFunction.Subtotal(103, .Cells) > 1 Then '<--| if any filterd cells other than header
With .Resize(.Rows.Count - 1).Offset(1).SpecialCells(xlCellTypeVisible)
.EntireRow.Copy Sheets("Test_macro").Cells(.Cells(1, 1).Row,1)
End With
End If
End With
.AutoFilterMode = False
End With
End Sub
you only need row 1 to be a header one, i.e. actual data to be filtered begin from row 2 downwards
also this pastes values in target sheet from cell A1 downwards without blank rows. Should original row sequence be respected, it can be done

Delete method of Range class failed

I have some code where I am using index(match) based on a cell with a dropdown menu. When users select a certain security, a CUSIP is outputted which then pastes formulas from bloomberg to output the data into excel.
I then proceed to create a table but would like to filter the table using autofilter and delete the rows that dont meet the filter criteria but that doesnt seem to be working for some reason! I also have insrted an activex control form button so that when a user double clicks on the dropdown menu they can search for a security and it would autocomplete.
Please help, Thanks!
Sub INDEX_MATCH_CUSIP_TO_SHORTDESCRIPTION()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Sheets("Sheet4").Range("B3:E100").Delete
Range("B2").Select
test = Application.WorksheetFunction.Index(Sheets("DEX Spread Report (Corp)").Range("B7:B1600"), Application.WorksheetFunction.Match(ActiveCell.Value, Sheets("DEX Spread Report (Corp)").Range("D7:D1600"), 0), 1)
ActiveCell.Offset(1, 0).Value = test
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Sub BBRG_FORMULAS_FOR_SECURITY()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Dim CUSIPS As String
Sheets("Sheet4").Select
Range("B2").Select
CUSIPS = ActiveCell.Offset(1, 0).Value
ActiveCell.Offset(2, 0).Value = "=BDS(""" & CUSIPS & """ & ""& CUSIP"",""ALL_HOLDERS_PUBLIC_FILINGS"", ""STARTCOL=1"", ""ENDCOL=1"")"
ActiveCell.Offset(2, 1).Value = "=BDS(""" & CUSIPS & """ & ""& CUSIP"",""ALL_HOLDERS_PUBLIC_FILINGS"", ""STARTCOL=6"", ""ENDCOL=8"")"
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Sub Create_Table_and_AutoFilter()
Dim wksDest As Worksheet
Dim LastRow As Long
Dim rng As Range
Dim rngDelete As Range
Sheets("Sheet4").Select
Set wksDest = Worksheets("Sheet4")
LastRow = Cells(Rows.Count, 2).End(xlUp).row
LastRow1 = Cells(Rows.Count, 2).End(xlUp).row
ActiveSheet.ListObjects.Add(xlSrcRange, Range(Cells(4, 2), Cells(LastRow, 5)), , xlYes).Name = "HoldersTable"
With wksDest
Set rng = Range(Cells(4, 2), Cells(LastRow1, 5))
rng.AutoFilter Field:=1, Criteria1:="<=1000"
Set rngDelete = rng.SpecialCells(xlCellTypeVisible)
rng.AutoFilter
rngDelete.EntireRow.Delete
End With
End Sub
you're most probably trying to delete table header
try substituting the code from With wksDestto End With with the following snippet:
With wksDest.Range(Cells(4, 2), Cells(LastRow1, 5))
.AutoFilter Field:=1, Criteria1:="<=1000"
If Application.WorksheetFunction.Subtotal(103, .Cells.Resize(,1)) > 1 Then .offset(1).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible).EntireRow.Delete
.AutoFilter
End With

Delete all rows if duplicate in excel - VBA

I need to remove all rows without leaving any unique record. If duplicate exists delete all matching rows. Criteria is column C if any duplicate record exists in column C then delete entire row (including unique).
Below given code is working but leaving the unique row Even I don't want that.
Code:
Sub DDup()
Sheets("MobileRecords").Activate
With ActiveSheet
Set Rng = Range("A1", Range("C1").End(xlDown))
Rng.RemoveDuplicates Columns:=Array(3, 3), Header:=xlYes
End With
End Sub
I like the code from Jeeped, but it isn't the best readable one. Therefore, here is another solution.
Sub remDup()
Dim rng As Range, dupRng As Range, lastrow As Long, ws As Worksheet
Dim col As Long, offset As Long, found As Boolean
'Disable all the stuff that is slowing down
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
'Define your worksheet here
Set ws = Worksheets(1)
'Define your column and row offset here
col = 3
offset = 0
'Find first empty row
Set rng = ws.Cells(offset + 1, col)
lastrow = rng.EntireColumn.Find( _
What:="", After:=ws.Cells(offset + 1, col)).Row - 1
'Loop through list
While (rng.Row < lastrow)
Do
Set dupRng = ws.Range(ws.Cells(rng.Row + 1, col), ws.Cells(lastrow, col)).Find( _
What:=rng, LookAt:=xlWhole)
If (Not (dupRng Is Nothing)) Then
dupRng.EntireRow.Delete
lastrow = lastrow - 1
found = True
If (lastrow = rng.Row) Then Exit Do
Else
Exit Do
End If
Loop
Set rng = rng.offset(1, 0)
'Delete current row
If (found) Then
rng.offset(-1, 0).EntireRow.Delete
lastrow = lastrow - 1
End If
found = False
Wend
'Enable stuff again
Application.ScreenUpdating = True
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
End Sub
It works with more than one duplicate and you can define an row offset, which defines how much rows you ignore at the beginning of the column.
I like to try these without any declared variables. It is good practise for keeping your cell / worksheet / workbook hierarchy together.
Sub dupeNuke()
With Worksheets("Sheet1") '<~~ you should know what worksheet you are supposed to be on
If .AutoFilterMode Then .AutoFilterMode = False
With .Cells(1, 1).CurrentRegion
With .Resize(.Rows.Count - 1, 1).Offset(1, 2)
With .FormatConditions
.Delete
.Add Type:=xlExpression, Formula1:="=COUNTIF(C:C, C2)>1"
End With
With .FormatConditions(.FormatConditions.Count)
.Interior.Color = vbRed
End With
End With
With .Resize(.Rows.Count, 1).Offset(0, 2)
.AutoFilter Field:=1, Criteria1:=vbRed, Operator:=xlFilterCellColor
With .Resize(.Rows.Count - 1, .Columns.Count).Offset(1, 0)
If CBool(Application.Subtotal(103, Cells)) Then
.EntireRow.Delete
End If
End With
End With
With .Resize(.Rows.Count - 1, 1).Offset(1, 2)
With .FormatConditions
.Delete
End With
End With
End With
If .AutoFilterMode Then .AutoFilterMode = False
End With
End Sub
Obviously, this is heavily reliant on the With ... End With statement. An underrated / underused method in my estimation.

Run time error 438, excel VBA Macros - AutoFilter

so I've been working on this for the last couple of days and I don't seem to be able to make it work.
Sub Button3_Click()
Dim DeleteValue As String
Dim rng As Range
Dim calcmode As Long
With Application
calcmode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
End With
'Fill in the value that you want to delete
'Tip: use DeleteValue = "<>ron" to delete rows without ron
DeleteValue = "<>assap"
'Sheet with the data, you can also use Sheets("MySheet")
With ActiveSheet
'Firstly, remove the AutoFilter
ActiveSheet.AutoFilterMode = False
'Apply the filter 'The problem is this line according to the debugger
ActiveSheet.Sheets("Sheet1").Range("A2:A" & .Rows.Count).AutoFilter Field:=1, Criteria1:=DeleteValue
With .AutoFilter.Range
On Error Resume Next
Set rng = .Offset(1, 0).Resize(.Rows.Count - 1, 1) _
.SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If Not rng Is Nothing Then rng.EntireRow.Delete
End With
'Remove the AutoFilter
.AutoFilterMode = False
End With
With Application
.ScreenUpdating = True
.Calculation = calcmode
End With
End Sub
What this is supposed to do is to look for cells in column A without "assap" and delete them, but I'm not sure what's wrong in this code, and I literally got it online and most people seem to have it working but me. I also tried to add and try other things but still the same problem happens, if anyone can help me I'd appreciate it.
the error is 438 run time error
Remove ActiveSheet.Sheets("Sheet1") from the beginning of this line:
ActiveSheet.Sheets("Sheet1").Range("A2:A" & .Rows.Count).AutoFilter Field:=1, Criteria1:=DeleteValue
There are a couple of problems; mostly stemming from your use of .Rows.Count for the entire ActiveSheet and the incorrect use of a With ... End With statement. Work with the Range.CurrentRegion property to reduce the area to the 'data island' originating in A1.
Sub Button3_Click()
Dim DeleteValue As String
Dim calcmode As Long
With Application
calcmode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
End With
'Fill in the value that you want to delete
'Tip: use DeleteValue = "<>ron" to delete rows without ron
DeleteValue = "<>assap"
'Sheet with the data, you can also use Sheets("MySheet")
With ActiveSheet
'Firstly, remove the AutoFilter
If .AutoFilterMode Then .AutoFilterMode = False
'Work with the range of cells containing data
With .Cells(1, 1).CurrentRegion
'Apply the filter 'The problem is this line according to the debugger
.Cells.AutoFilter Field:=1, Criteria1:=DeleteValue
With .Resize(.Rows.Count - 1, .Columns.Count).Offset(1, 0)
If CBool(Application.Subtotal(103, .Cells)) Then
.Rows.EntireRow.Delete
End If
End With
End With
'Remove the AutoFilter
.AutoFilterMode = False
End With
With Application
.ScreenUpdating = True
.Calculation = calcmode
End With
End Sub
Your use of .Rows.Count while attempting to use the Range.Offset property to push the range down was trying to push the range off the bottom of the worksheet. Even with a smaller range that was not going to push rows off the bottom of the worksheet a Range.Resize property should predeed a Range.Offset property.
'Use THIS
With .Resize(.Rows.Count - 1, .Columns.Count).Offset(1, 0)
'Not this
With .Offset(1, 0).Resize(.Rows.Count - 1, .Columns.Count)
you can specify the range as row for example i have used first row for filtering criteria
ActiveSheet.Rows(2).AutoFilter Field:=1, Criteria1:=DeleteValue