I have this macro which does exactly what I want except for one change. I want it to sort by column "M" instead of "A". I've tried changing it manually, but I keep getting errors. I know it's probably a simple fix but I just can't seem to get it. Thanks in advance!
I've tried to change "Field:=1" to Field:="13", but I get "Run-time error '1004' AutoFilter method of range class failed".
Debug then highlights "rngFilter.AutoFilter Field:=13, Criteria1:=cell.Value"
Private Sub CommandButton1_Click()
Dim wbDest As Workbook
Dim rngFilter As Range, rngUniques As Range
Dim cell As Range
Set rngFilter = Range("A1", Range("A" & Rows.Count).End(xlUp))
Application.ScreenUpdating = False
With rngFilter
.AdvancedFilter Action:=xlFilterInPlace, Unique:=True
Set rngUniques = Range("A2", Range("A" & Rows.Count).End(xlUp)).SpecialCells(xlCellTypeVisible)
ActiveSheet.ShowAllData
End With
For Each cell In rngUniques
Set wbDest = Workbooks.Add(xlWBATWorksheet)
rngFilter.AutoFilter Field:=1, Criteria1:=cell.Value
rngFilter.EntireRow.Copy
With wbDest.Sheets(1).Range("A1")
.PasteSpecial xlPasteColumnWidths
.PasteSpecial xlPasteValuesAndNumberFormats
End With
Application.CutCopyMode = True
wbDest.Sheets(1).Name = cell.Value
wbDest.SaveAs ThisWorkbook.Path & Application.PathSeparator & _
cell.Value & " " & Format(Date, "mmm_dd_yyyy")
Next cell
rngFilter.Parent.AutoFilterMode = False
Application.ScreenUpdating = True
End Sub
Give this a try. I've updated the code so that all you need to do is change sColumn from A to whatever column letter you want:
Private Sub CommandButton1_Click()
Const sColumn As String = "A"
Dim wbDest As Workbook
Dim rngFilter As Range, rngUniques As Range
Dim cell As Range
Set rngFilter = Range(sColumn & "1", Range(sColumn & Rows.Count).End(xlUp))
Application.ScreenUpdating = False
With rngFilter
.AdvancedFilter Action:=xlFilterInPlace, Unique:=True
Set rngUniques = Range(sColumn & "2", Range(sColumn & Rows.Count).End(xlUp)).SpecialCells(xlCellTypeVisible)
On Error Resume Next
ActiveSheet.ShowAllData
On Error GoTo 0
End With
For Each cell In rngUniques
Set wbDest = Workbooks.Add(xlWBATWorksheet)
rngFilter.AutoFilter Field:=1, Criteria1:=cell.Value
rngFilter.EntireRow.Copy
With wbDest.Sheets(1).Range("A1")
.PasteSpecial xlPasteColumnWidths
.PasteSpecial xlPasteValuesAndNumberFormats
End With
Application.CutCopyMode = True
wbDest.Sheets(1).Name = cell.Value
Application.DisplayAlerts = False
wbDest.SaveAs ThisWorkbook.Path & Application.PathSeparator & cell.Value & " " & Format(Date, "mmm_dd_yyyy")
wbDest.Close False
Application.DisplayAlerts = True
Next cell
rngFilter.Parent.AutoFilterMode = False
Application.ScreenUpdating = True
End Sub
Try substituting this where your debug error is:
ActiveSheet.Range("A1").CurrentRegion.AutoFilter Field:=13, Criteria1:=cell.Value
Basically, it seemed that your rngFilter variable was restricting your range to Column A and you're trying to filter based on a column that's outside of this range.
Let me know if it works!
Related
I am a military recruiter and am trying to use autofilter to filter out a range from another range. I got this from another stackoverflow page but can not figure out how to change that string strSearch to a range like 123#gmail, 234#gmail, 345#gmail, etc.
We get lists of leads but I'd like to keep the running list of opt-outs and have VBA double check and delete any cells that have a value from the opt-out worksheet. I am pretty new to VBA but really enjoy it. Thank you!
I'd like it to be strSearch = Sheets("Opt-Outs").Range("A:A") so that it takes all values in A:A and uses them as an autofilter. I believe it needs to be a string array but am lost as how to get there. Please help.
Sub optout20171227()
Dim ws As Worksheet
Dim lRow As Long
Dim strSearch As String
'~~> Set this to the relevant worksheet
Set ws = ThisWorkbook.Worksheets("Email Addresses")
'~~> Search Text
strSearch = Sheets("Opt-Outs").Range("A2")
With ws
'~~> Remove any filters
.AutoFilterMode = False
lRow = .Range("A" & .Rows.count).End(xlUp).Row
With .Range("A1:A" & lRow)
.AutoFilter Field:=1, Criteria1:="=*" & strSearch & "*"
.Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
'~~> Remove any filters
.AutoFilterMode = False
End With
End Sub
This should do it...
Sub optout20171227()
Dim ws As Worksheet
Dim lRow As Long
Dim strSearch As String
Dim v() As Variant
'~~> Set this to the relevant worksheet
Set ws = ThisWorkbook.Worksheets("Email Addresses")
'~~> Search Text
strSearch = Sheets("Opt-Outs").Range("A2")
v = Application.Transpose(Sheets("Opt-Outs").Range("A:A"))
With ws
'~~> Remove any filters
.AutoFilterMode = False
lRow = .Range("A" & .Rows.count).End(xlUp).Row
With .Range("A1:A" & lRow)
.AutoFilter Field:=1, Criteria1:=v
.Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
'~~> Remove any filters
.AutoFilterMode = False
End With
Dim ws As Worksheet
Dim lRow As Long
Dim strSearch As Variant
Dim i As Integer
i = 1
Sheets("Opt-Outs").Select
Range("H2").Value = "Ready"
Range("A2").Select
Do While Range("H2").Value <> Empty
Sheets("Opt-Outs").Select
Range("A2").Select
Cells(i + 1, 1).Copy
i = i + 1
Range("H2").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
If Range("H2").Value = IsBlank Then
Sheets("Email Addresses").Select
Exit Sub
Else
'~~> Set this to the relevant worksheet
Set ws = ThisWorkbook.Worksheets("Email Addresses")
'~~> Search Text
strSearch = Sheets("Opt-Outs").Range("H2")
With ws
'~~> Remove any filters
.AutoFilterMode = False
lRow = .Range("A" & .Rows.count).End(xlUp).Row
With .Range("A1:A" & lRow)
.AutoFilter Field:=1, Criteria1:="=*" & strSearch & "*"
.Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
'~~> Remove any filters
.AutoFilterMode = False
End With
End If
Loop
I have a worksheet that has all data combined on it. Sample structure is like this (of course columns range all the way over to X and rows are roughly 17K)
Column A -- Column B -- Column C -- Column D -- Column E
Name1 stuff stuff stuff stuff
Name1 stuff stuff stuff stuff
Name2 stuff stuff stuff stuff
Name3 stuff stuff stuff stuff
So I am in need of 3 new worksheets added, each one named Name1, Name2, Name3 and all rows corresponding to that name be copied over to the appropriate sheet.
There is my predicament, how do I scan the worksheet for each unique name in column A, store the name in a variable so I can name a worksheet after it?
I think synax like such would be close, but not perfect -- what would proper VBA be to copy all data for each name to it's own worksheet?
ThisWorkbook.Worksheets.Add After:=ActiveSheet
ActiveSheet.Name = Blah
Set rngCopy = ActiveSheet.UsedRange
Set rngCopy = rngCopy.SpecialCells(XlCellType.xlCellTypeVisible)
ThisWorkbook.Worksheets.Add After:=ActiveSheet
ActiveSheet.Name = Blah
rngCopy.Copy ThisWorkbook.Worksheets(Blah).Cells(1, 1)
Application.CutCopyMode = False
Cells.Select
Cells.EntireColumn.AutoFit
Range("A1").Select
Sub ExtractWorksheets()
Application.ScreenUpdating = False
Dim OriginalAddress As String
Dim OriginalData
With Worksheets("Sheet1").Range("A1").CurrentRegion
OriginalData = .Value
OriginalAddress = .Address
If Not .AutoFilter Then .AutoFilter
Do While .Cells(2, 1) <> ""
.AutoFilter Field:=1, Criteria1:=.Cells(2, 1).Value
Worksheets.Add After:=ActiveSheet
ActiveSheet.Name = getCleanWorksheetName(.Cells(2, 1).Value)
.Copy Destination:=Range("A1")
.Offset(1).EntireRow.Delete
Loop
.Range(OriginalAddress).Value = OriginalData
End With
Application.ScreenUpdating = True
End Sub
'VBA Express http://www.vbaexpress.com/kb/getarticle.php?kb_id=1132
Function getCleanWorksheetName(ByRef SheetName As String) As String
Dim charPairs As Variant, ch As Variant
charPairs = Array(Array(":", "."), Array("/", "."), Array("\", ""), Array("?", "_"), Array("*", "_"), Array("[", "("), Array("]", ")"))
For Each ch In charPairs
If InStr(SheetName, ch(0)) Then SheetName = Replace(SheetName, ch(0), ch(1))
Next
getCleanWorksheetName = Left(SheetName, 31)
End Function
Try it this way.
Sub Copy_To_Worksheets()
'Note: This macro use the function LastRow
Dim My_Range As Range
Dim FieldNum As Long
Dim CalcMode As Long
Dim ViewMode As Long
Dim ws2 As Worksheet
Dim Lrow As Long
Dim cell As Range
Dim CCount As Long
Dim WSNew As Worksheet
Dim ErrNum As Long
'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
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
'This example filters 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, ......
FieldNum = 1
'Turn off AutoFilter
My_Range.Parent.AutoFilterMode = False
'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
'Add a worksheet to copy the a unique list and add the CriteriaRange
Set ws2 = Worksheets.Add
With ws2
'first we copy the Unique data from the filter field to ws2
My_Range.Columns(FieldNum).AdvancedFilter _
Action:=xlFilterCopy, _
CopyToRange:=.Range("A1"), Unique:=True
'loop through the unique list in ws2 and filter/copy to a new sheet
Lrow = .Cells(Rows.Count, "A").End(xlUp).Row
For Each cell In .Range("A2:A" & Lrow)
'Filter the range
My_Range.AutoFilter Field:=FieldNum, Criteria1:="=" & _
Replace(Replace(Replace(cell.Value, "~", "~~"), "*", "~*"), "?", "~?")
'Check if there are no more then 8192 areas(limit of areas)
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 for the value : " & cell.Value _
& vbNewLine & "It is not possible to copy the visible data." _
& vbNewLine & "Tip: Sort your data before you use this macro.", _
vbOKOnly, "Split in worksheets"
Else
'Add a new worksheet
Set WSNew = Worksheets.Add(After:=Sheets(Sheets.Count))
On Error Resume Next
WSNew.Name = cell.Value
If Err.Number > 0 Then
ErrNum = ErrNum + 1
WSNew.Name = "Error_" & Format(ErrNum, "0000")
Err.Clear
End If
On Error GoTo 0
'Copy the visible data to the new worksheet
My_Range.SpecialCells(xlCellTypeVisible).Copy
With WSNew.Range("A1")
' 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
.Select
End With
End If
'Show all data in the range
My_Range.AutoFilter Field:=FieldNum
Next cell
'Delete the ws2 sheet
On Error Resume Next
Application.DisplayAlerts = False
.Delete
Application.DisplayAlerts = True
On Error GoTo 0
End With
'Turn off AutoFilter
My_Range.Parent.AutoFilterMode = False
If ErrNum > 0 Then
MsgBox "Rename every WorkSheet name that start with ""Error_"" manually" _
& vbNewLine & "There are characters in the name that are not allowed" _
& vbNewLine & "in a sheet name or the worksheet already exist."
End If
'Restore ScreenUpdating, Calculation, EnableEvents, ....
My_Range.Parent.Select
ActiveWindow.View = ViewMode
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
You'll find more info here.
http://www.rondebruin.nl/win/s3/win006_4.htm
so this code was made in excel 2013 and the workstations I have to use it on operate with 2003. In 2013 it works just fine, when it's in 2003 it returns "Runtime error "9" Subscript out of range". If someone could help me figure this out I would appreciate it. It appears the issue is with this bit of data
Set wsSheet = Worksheets("Sheet1")
With wsSheet
Set rnData = Range("A2:A" & Range("A" & Rows.Count).End(xlUp).Row)
End With"
Once again thank you for the help.
`Private Sub UserForm_Initialize()
Dim wsSheet As Worksheet
Dim rnData As Range
Dim vaData As Variant
Dim ncData As New VBA.Collection
Dim lnCount As Long
Dim vaItem As Variant
Set wsSheet = Worksheets("Sheet1")
With wsSheet
Set rnData = Range("A2:A" & Range("A" & Rows.Count).End(xlUp).Row)
End With
vaData = rnData.Value
On Error Resume Next
For lnCount = 1 To UBound(vaData)
ncData.Add vaData(lnCount, 1), CStr(vaData(lnCount, 1))
Next lnCount
On Error GoTo 0
With ComboBox1
.Clear
For Each vaItem In ncData
.AddItem ncData(vaItem)
Next vaItem
End With
End Sub
Private Sub CommandButton1_Click()
Dim c As Range
With Range("B2:B" & Range("B" & Rows.Count).End(xlUp).Row)
Set c = .Find(ComboBox2.Value, LookIn:=xlValues)
c.Activate
ActiveCell.EntireRow.Copy
Sheets("Sheet2").Select
RowCount = Cells(Cells.Rows.Count, "a").End(xlUp).Row
Range("a" & RowCount + 1).Select
ActiveSheet.Paste
Application.CutCopyMode = False
End With
Sheets("Sheet1").Select
Range("a1").Select
Unload Me
End Sub
Private Sub ComboBox1_Change()
Dim cell As Range
Me.ComboBox2.Clear
For Each cell In Range("A2:A" & Range("A" & Rows.Count).End(xlUp).Row)
If cell.Value = Me.ComboBox1 Then
Me.ComboBox2.AddItem (cell.Offset(0, 1).Value)
End If
Next cell
Me.ComboBox2.ListIndex = 0
End Sub`
Might be this typo (you are missing the dots before the two ranges):
With wsSheet
Set rnData = .Range("A2:A" & .Range("A" & Rows.Count).End(xlUp).Row)
End With
And as rory pointed out in the comments above, check if you are addressing the correct workbook. Maybe add this to be safe:
Set wsSheet = ThisWorkbook.Worksheets("Sheet1")
i have 50 workbooks and i made a code to copy from a main one the rows in which are the corespondent names to the other 49 files. the problem is in pasting to the 49 target files - paste method doesn't work. The errors is when the filter doesn't find entries for a name. How can i include a line that if the filter doesn't find a name in the main file, it will paste "no entries this month" in the file with the name that wasn't find? Thank you.
Any help is welcomed.
Sub name1()
Dim ws As Worksheet
Dim rng As Range, rngA As Range, rngB As Range
Dim LRow As Long
Set ws = Sheets("name list")
With ws
LRow = .Range("A" & .Rows.Count).End(xlUp).Row
Set rng = .Range("A1:M" & LRow)
.AutoFilterMode = False
With rng
.AutoFilter Field:=12, Criteria1:="name1"
Set rngA = .Offset(1, 0).SpecialCells(xlCellTypeVisible)
End With
.AutoFilterMode = False
With rng
.AutoFilter Field:=13, Criteria1:="name1"
Set rngB = .Offset(1, 0).SpecialCells(xlCellTypeVisible)
End With
.AutoFilterMode = False
rng.Offset(1, 0).EntireRow.Hidden = True
Union(rngA, rngB).EntireRow.Hidden = False
End With
End Sub
Sub name11()
Dim lst As Long
Dim rng As Range
Dim i As Integer
Set rng = Application.Intersect(ActiveSheet.UsedRange, Range("A:M"))
rng.SpecialCells(xlCellTypeVisible).Select
Selection.Copy
Application.DisplayAlerts = False
Workbooks.Open Filename:= _
"\\HOFS\persons\name1.xlsm" _
, UpdateLinks:=true
With Sheets("tribute").Range("A" & Rows.Count).End(xlUp).Offset(1)
'.PasteSpecial Paste:=xlPasteColumnWidths
.PasteSpecial Paste:=xlPasteValues
End With
ActiveWorkbook.Close SaveChanges:=True
Application.DisplayAlerts = False
Windows("name list.xlsm").Activate
rng.Offset(1, 0).EntireRow.Hidden = False
End Sub
Sub TRANSFER_name1()
Call name1
Call name11
End Sub
Set the last row separately.
' Gives the first empty row in column 1 (A)
lastRow = Worksheets("tribute").Cells(Worksheets("tribute").Rows.Count, 1).End(xlUp).Row + 1
' Pastes values
Worksheets("tribute").Range("A" & lastRow).PasteSpecial Paste:=xlPasteValues
Its probably much better to avoid copy/paste situations. This can get super time consuming over time.
try somethign like this instead:
With Sheets("tribute").Range("A" & Rows.Count).End(xlUp).Offset(1).value = rng.Value
This is a bit crude but I am sure you can significantly simplify your code if you do.
Dim wbk As Workbook
Dim Filename As String
Dim path As String
Dim rCell As Range
Dim rRng As Range
Dim wsO As Worksheet
Dim StartTime As Double
Dim SecondsElapsed As Double
Dim sheet As Worksheet
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.Calculation = xlCalculationManual
StartTime = Timer
path = "pathtofolder" & "\"
Filename = Dir(path & "*.xl??")
Set wsO = ThisWorkbook.Sheets("Sheet1")
Do While Len(Filename) > 0
DoEvents
Set wbk = Workbooks.Open(path & Filename, True, True)
Set rRng = sheet.Range("b1:b308")
For Each rCell In rRng.Cells
wsO.Cells(wsO.Rows.count, 1).End(xlUp).Offset(1, 0).Value = rCell
Next rCell
wbk.Close False
Filename = Dir
Loop
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Application.Calculation = xlCalculationAutomatic
SecondsElapsed = Round(Timer - StartTime, 2)
MsgBox "This code ran successfully in " & SecondsElapsed & " seconds", vbInformation
I am getting following error when trying to auto filter in vba:
The object invoked has disconnected from its clients.
So what i am trying to do is auto filter, search for empty spaces and delete the rows. Can anyone please help?
I have tried the standard solutions provided online e.g. option explicit etc but to no avail.
Data:
Code:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim lngLastRow As Long
Dim lngLastRowD As Long
Application.ScreenUpdating = False
'Concatenate the Row A and B
lngLastRow = Cells(Rows.Count, "A").End(xlUp).Row
Worksheets(1).Range("D2:D" & lngLastRow).Value = Evaluate("=A2:A" & lngLastRow & "&""""&" & "B2:B" & lngLastRow)
lngLastRowD = Worksheets(1).Cells(Rows.Count, "D").End(xlUp).Row
Set ws = Worksheets(1)
Set Rng = Worksheets(1).Range("A2:A" & lngLastRowD)
With Rng
.AutoFilter field:=1, Criteria1:=""
.Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
ws.AutoFilterMode = False
Application.ScreenUpdating = True
ThisWorkbook.Sheets(1).Range("A2").Select
End Sub
Since Worksheets() want the name of the sheet, like "Sheet1", use sheets(1).
Why are you creating the variable ws and rng when you only use them once
I ran this and it deleted rows with no data in column A.
Private Sub Worksheet_Change()
Dim lngLastRow As Long
Dim lngLastRowD As Long
Application.ScreenUpdating = False
'Concatenate the Row A and B
lngLastRow = Cells(Rows.Count, "A").End(xlUp).Row
sheets(1).Range("D2:D" & lngLastRow).Value = Evaluate("=A2:A" & lngLastRow & "&""""&" & "B2:B" & lngLastRow)
lngLastRowD = Worksheets(1).Cells(Rows.Count, "D").End(xlUp).Row
With sheets(1).Range("A2:A" & lngLastRowD)
.AutoFilter field:=1, Criteria1:=""
.Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
sheets(1).AutoFilterMode = False
Application.ScreenUpdating = True
Sheets(1).Range("A2").Select
End Sub
In the end i restored in approaching the issue from another angle:
Dim i As Integer, counter As Integer
i = 2
For counter = 1 To lngLastRowD
If Worksheets(1).Range("A2:A" & lngLastRowD).Cells(i) = "" And Worksheets(1).Range("D2:D" & lngLastRowD).Cells(i) <> "" Then
Worksheets(1).Range("A2:A" & lngLastRowD).Range("A" & i & ":D" & lngLastRowD).Select
Selection.Delete
GoTo TheEND
Else
i = i + 1
Debug.Print "i is " & i
End If
Next