VBA Auto Filter If Criteria Exists - excel

I've recorded macros to autofilter and delete rows from a table. But this is not dynamic in the sense that if the filter criteria does not exist in a given table then the macro will break.
I am trying to create a code that will autofilter and delete the rows if the the criteria exists or otherwise do nothing. I am trying to follow this post, but I am missing something. Please help.
My code returns no errors, but also does not do anything. I added the message box to make sure that it was actually running.
Here is my code so far:
Sub autofilter()
Dim lo As ListObject
Set lo = Worksheets("BPL").ListObjects("Table1")
With Sheets(1)
If .AutoFilterMode = True And .FilterMode = True Then
If lo.Parent.autofilter.Filters(7).Criteria1 = "APGFORK" Then
'
lo.Range.autofilter Field:=7, Criteria1:="APGFORK"
Application.DisplayAlerts = False
lo.DataBodyRange.SpecialCells(xlCellTypeVisible).Delete
Application.DisplayAlerts = True
lo.autofilter.ShowAllData
'
End If
End If
End With
MsgBox ("Code Complete")
End Sub

Delete Filtered Rows in an Excel Table
Not entire rows!
Option Explicit
Sub DeleteFilteredRows()
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim tbl As ListObject: Set tbl = wb.Worksheets("BPL").ListObjects("Table1")
Dim dvrg As Range ' Data Visible Range
With tbl
If .ShowAutoFilter Then
If .Autofilter.FilterMode Then .Autofilter.ShowAllData
End If
.Range.Autofilter 7, "APGFORK"
On Error Resume Next
Set dvrg = tbl.DataBodyRange.SpecialCells(xlCellTypeVisible)
On Error GoTo 0
.Autofilter.ShowAllData
End With
Dim IsSuccess As Boolean
If Not dvrg Is Nothing Then
dvrg.Delete xlShiftUp
IsSuccess = True
End If
If IsSuccess Then
MsgBox "Data deleted.", vbInformation
Else
MsgBox "Nothing deleted.", vbExclamation
End If
End Sub

I don't know if it is a bug or a feature, but .AutoFilterMode seems to returns False all the time in Excel 2013 or later. All examples I see that use .AutoFilterMode are earlier than that.
I think the replacement is .ShowAutoFilter on the listobject. In your code, lo.ShowAutoFilter should return True or False depending on whether or not the autofilter is set or not.
But the rest of your code seems problematic too. The test
If lo.Parent.autofilter.Filters(7).Criteria1 = "APGFORK" Then
throws an error and removes the autofilter.

I Ended up taking a different approach:
Dim LastRowG As Long
LastRowG = Range("G" & Rows.Count).End(xlUp).Row
For i = 2 To LastRowG
If Range("G" & i).Value = "APGFORK" Then
lo.Range.autofilter Field:=7, Criteria1:="APGFORK"
Application.DisplayAlerts = False
lo.DataBodyRange.SpecialCells(xlCellTypeVisible).Delete
Application.DisplayAlerts = True
lo.autofilter.ShowAllData
Else
End If
Next i
This way if "APGFORK" does not exist in a data set, it will move on without an error code.

Try this code
Sub Test()
Call DelFilterParam("BPL", "Table1", 7, "APGFORK")
End Sub
Sub DelFilterParam(ByVal wsName As String, ByVal stTable As String, ByVal iField As Integer, ByVal vCriteria As Variant)
Dim x As Long, y As Long, z As Long
With ThisWorkbook.Worksheets(wsName)
With .ListObjects(stTable).DataBodyRange
x = .Rows.Count: y = .Columns.Count
.AutoFilter
.AutoFilter Field:=iField, Criteria1:=vCriteria
On Error Resume Next
z = .SpecialCells(xlCellTypeVisible).Count
On Error GoTo 0
If (x * y) > z And z <> 0 Then .EntireRow.Delete
.AutoFilter
End With
End With
End Sub

Related

Delete all rows in Excel workbook with column C empty using VBA

I am working on a project to clean up a couple hundred excel sheets for an specific import spec. The import process errors out if any rows have a specific value blank, so I'm looking to find the best way to delete all rows in the entire workbook if column C in that row is empty. I found this simple VBA code that works on the active sheet, but I need it to loop through all sheets in the workbook. Any suggestions on a better process so I don't have to run it >100 times?
Sub DelBlankRows()
Columns("C:C").Select
Selection.SpecialCells(xlCellTypeBlanks).Select
Selection.EntireRow.Delete
End Sub
Delete the Rows of a Column's Blanks
Option Explicit
Sub DelRowsOfColumnBlanksTEST()
Const wsCol As Variant = "C" ' or 3
'Const wsCol As String = "C"
'Const wsCol As Long = 3
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Application.ScreenUpdating = False
Dim ws As Worksheet
For Each ws In wb.Worksheets
DelRowsOfColumnBlanks ws, wsCol
Next ws
Application.ScreenUpdating = True
End Sub
Sub DelRowsOfColumnBlanks( _
ByVal ws As Worksheet, _
ByVal WorksheetColumnID As Variant)
If ws Is Nothing Then Exit Sub ' no worksheet
If ws.AutoFilterMode Then
ws.AutoFilterMode = False
End If
Dim urg As Range: Set urg = ws.UsedRange
If urg.Rows.Count = 1 Then Exit Sub ' only one row
On Error Resume Next
Dim crg As Range: Set crg = ws.Columns(WorksheetColumnID)
On Error GoTo 0
If crg Is Nothing Then Exit Sub ' invalid Worksheet Column ID
Dim tcrg As Range: Set tcrg = Intersect(urg, crg)
' ... is only the same as 'Set tcrg = urg.Columns(WorkhseetColumnID)',...
' ... if the first column of the used range is column 'A'.
If tcrg Is Nothing Then Exit Sub ' no intersection
Dim drg As Range: Set drg = tcrg.Resize(tcrg.Rows.Count - 1).Offset(1)
tcrg.AutoFilter 1, "=" ' ... covers blanks: 'Empty', "=""""", "'"... etc.
' Note that although it contains the word 'Blanks',...
' ... 'SpecialCells(xlCellTypeBlanks)' only covers 'Empty'.
On Error Resume Next
Dim spcrg As Range: Set spcrg = drg.SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If Not spcrg Is Nothing Then
spcrg.EntireRow.Delete
'Else
' no 'visible' cells (to delete)
End If
ws.AutoFilterMode = False
End Sub
Option Explicit
Sub CleanWorkbook()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Dim sh As Worksheet
For Each sh In ActiveWorkbook.Worksheets
DeleteRowsOfEmptyColumn sh, "C"
Next
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Sub DeleteRowsOfEmptyColumn(sh As Worksheet, col as string)
Dim rowsToDelete As New Collection
Dim cell
For Each cell In Intersect(sh.UsedRange, sh.Columns(col))
If cell.Value = "" Then
rowsToDelete.Add cell.Row
End If
Next
Dim i As Integer
For i = rowsToDelete.Count To 1 Step -1
sh.Rows(rowsToDelete(i)).Delete
Next
End Sub
I've put a very basic error trap for any sheets with no values in C. You may need to improve this yourself.
Edit: Updated error trap
Sub DelBlankRows()
Dim sh As Worksheet
Application.ScreenUpdating = False
On Error GoTo Handle
For Each sh In ThisWorkbook.Worksheets
sh.Activate
Columns("C:C").Select
Selection.SpecialCells(xlCellTypeBlanks).Select
Selection.EntireRow.Delete
Cont:
Next sh
Application.ScreenUpdating = True
Exit Sub
Handle:
If Err.Number = 1004 Then Resume Cont
End Sub

VBA Delete all rows with blank space and delete rows will cell that contains string

All, I have some VBA that deletes any row in which column C is blank. It also deletes and row in which Column A starts with 'Name' or 'Bar Name'. The problem is when I run these all together it only runs the first 2 steps. Furthermore, it doesn't actually turn off the filtering it's using and leaves the sheet filtered after it deletes the data.
Any idea how to get this to run as one step, this only seems to recognize the VBA for the first sheet?
Sub WB()
With ThisWorkbook.Worksheets("Geez")
Application.ScreenUpdating = False
Columns("C:C").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
Application.ScreenUpdating = True
End With
End Sub
Sub WC()
With ThisWorkbook.Worksheets("Geez")
.AutoFilterMode = False
With Range("a1", Range("a" & Rows.Count).End(xlUp))
.AutoFilter 1, "*Bar Name*"
On Error Resume Next
.Offset(1).SpecialCells(12).EntireRow.Delete
End With
.AutoFilterMode = False
End With
End Sub
Sub WE()
With ThisWorkbook.Worksheets("Class")
Application.ScreenUpdating = False
Columns("C:C").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
Application.ScreenUpdating = True
End With
End Sub
Sub WF()
With ThisWorkbook.Worksheets("Class")
.AutoFilterMode = False
With Range("a1", Range("a" & Rows.Count).End(xlUp))
.AutoFilter 1, "*Name*"
On Error Resume Next
.Offset(1).SpecialCells(12).EntireRow.Delete
End With
.AutoFilterMode = False
End With
End Sub
I try to run all and assign to a button using the below, but it only runs this for the first two steps. It also filters the first sheet, but doesn't actually remove the filter.
Sub Run1()
Call WB
Call WC
Call WE
Call WF
End Sub
Delete Empty and Filter
If you do a procedure for empty cells and another for filtering on one value, you can easily use them in another procedure.
Note all the occurrences of ws: they are showing where you have to put dots (.) instead if you plan to use the With statement: usually in front of Rows, Columns, Range, Cells...
When using On Error Resume Next (defer error handling (ignore errors)), you have to use a 'closing' On Error Goto 0 (turn off error handling).
The 'slight inaccuracy' in defining the range is easily handled with Resize: you don't necessarily want to delete the row below the range.
Using 12 instead of xlCellTypeVisible makes the code unnecessarily less readable.
The Code
Option Explicit
Sub doAll()
Application.ScreenUpdating = False
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Geez")
doEmpty ws
doFilter ws, "*Bar Name*"
Set ws = ThisWorkbook.Worksheets("Class")
doEmpty ws
doFilter ws, "*Name*"
Application.ScreenUpdating = True
End Sub
Sub doEmpty(ws As Worksheet)
ws.AutoFilterMode = False
ws.Columns("C:C").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End Sub
Sub doFilter(ws As Worksheet, ByVal FilterPattern As String)
ws.AutoFilterMode = False
With ws.Range("A1", ws.Range("A" & ws.Rows.Count).End(xlUp))
.AutoFilter 1, FilterPattern
On Error Resume Next
.Resize(.Rows.Count - 1).Offset(1) _
.SpecialCells(xlCellTypeVisible).EntireRow.Delete
On Error GoTo 0
End With
ws.AutoFilterMode = False
End Sub

Where do I add this function

I have a macro in my Excel Workbook that I run reports on.
I want to add in the pastespecial Function below but don't know where to place it in the script further down. It keeps giving me errors. I've tried almost every line.
I also want to add an extract phrase function added in as well. There is some text I want removed from one column at the beginning of every cell eg: alpha/beta/kappa
Help please. Thank you.
++++++++++++++++++++++++++++++++
Copy and Value Paste to Different Sheet
This example will Copy & Paste Values for single cells on different worksheets
1
2
Sheets("Sheet1").Range("A1").Copy
Sheets("Sheet2").Range("B1").PasteSpecial Paste:=xlPasteValues
++++++++++++++++++++++++++++++++++++++
My code below where I want to insert the above pastespecial function:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Option Explicit
Function GetHeadersDict() As Scripting.Dictionary
' We must activate the Microsoft Scripting Runtime from Tools --References
Dim result As Scripting.Dictionary
Set result = New Scripting.Dictionary
With result
.Add "Track #", False
.Add "Date", False
.Add "Status", False
.Add "Shoes", False
.Add "Description", False
End With
Set GetHeadersDict = result
End Function
Function FindHeaderRange(ByVal ws As Worksheet, ByVal header As String) As Range
Set FindHeaderRange = ws.Cells.Find(header, , , xlWhole)
End Function
Sub clearDataNotFormulasSheet2()
Sheets("Results").Range("A2:k96").ClearContents
End Sub
Sub copyColumnData()
On Error GoTo ErrorMessage
Dim ws1 As Worksheet, ws2 As Worksheet
Set ws1 = ThisWorkbook.Sheets("Report")
Set ws2 = ThisWorkbook.Sheets("Results")
clearDataSheet2
Dim numRowsToCopy As Long
numRowsToCopy = ws1.Cells(RowIndex:=Rows.Count, ColumnIndex:=1).End(xlUp).Row - 1
'MsgBox "The no of rows to copy is " & numRowsToCopy
Dim destRowOffset As Long
destRowOffset = ws2.Cells(RowIndex:=Rows.Count, ColumnIndex:=1).End(xlUp).Row
'MsgBox "The next Blank row is " & destRowOffset
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Dim dictKey As Variant
Dim header As String
Dim numColumnsToCopy As Long
Dim Report As Range
Dim dest As Range
Dim headersDict As Scripting.Dictionary
Set headersDict = GetHeadersDict()
For Each dictKey In headersDict
header = dictKey
If headersDict.Item(header) = False Then
Set Report = FindHeaderRange(ws1, header)
If Not (Report Is Nothing) Then
Set dest = FindHeaderRange(ws2, header)
If Not (dest Is Nothing) Then
headersDict.Item(header) = True
' Look at successive headers to see if they match
' If so, copy these columns altogether to make the macro faster
For numColumnsToCopy = 1 To headersDict.Count
'MsgBox numColumnsToCopy
If Report.Offset(ColumnOffset:=numColumnsToCopy).Value = dest.Offset(ColumnOffset:=numColumnsToCopy).Value Then
headersDict.Item(Report.Offset(ColumnOffset:=numColumnsToCopy).Value) = True
Else
Exit For
End If
Next numColumnsToCopy
Report.Offset(RowOffset:=1).Resize(RowSize:=numRowsToCopy, ColumnSize:=numColumnsToCopy).Copy _
dest.Offset(RowOffset:=destRowOffset)
End If
End If
End If
Next dictKey
Dim msg As String
For Each dictKey In headersDict
header = dictKey
If headersDict.Item(header) = False Then
msg = msg & vbNewLine & header
End If
Next dictKey
ExitSub:
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
If msg <> "" Then
MsgBox "The following headers were not copied:" & vbNewLine & msg
End If
Exit Sub
ErrorMessage:
MsgBox "An error has occurred: " & Err.Description
Resume ExitSub
End Sub
Private Sub CommandButton1_Click()
End Sub
I had the same issue of yours just replace Report.Offset(RowOffset:=1).Resize(RowSize:=numRowsToCopy, ColumnSize:=numColumnsToCopy).Copy _ dest.Offset(RowOffset:=destRowOffset)
with
Report.Offset(RowOffset:=1).Resize(RowSize:=numRowsToCopy,ColumnSize:=numColumnsToCopy).Copy
dest.Offset(RowOffset:=destRowOffset).PasteSpecial Paste:=xlPasteValues

Delete values in VBA with hidden Cells

I am trying to delete all "0" values from a table in excel. I have the following code written but it returns that Method 'Range of object'_Worksheet' failed. What do I need to do to fix this?
Sub Macro()
Dim ws As Worksheet
''Set reference
Set ws = ThisWorkbook.Worksheets("Compressed Schedule results")
''Apply Filter
ws.Range("A2:B2").AutoFilter Field:=1, Criteria1:="0"
lrow = ActiveSheet.Cells(Rows.Count, "A").End(xlUp).SpecialCells(xlCellTypeVisible).Row
''Delete the Rows
Application.DisplayAlerts = False
ws.Range("A2:lrow").SpecialCells(xlCellTypeVisible).Delete
Application.DisplayAlerts = True
ws.ShowAllData
End Sub
As #BigBen noted, you are referencing a range with a variable incorrectly. I also removed the SpecialCells when setting the last row:
Sub Macro()
Dim ws As Worksheet
Dim lRow As Long
''Set reference
Set ws = ThisWorkbook.Worksheets("Compressed Schedule results")
lRow = ws.Cells(Rows.Count, "A").End(xlUp).Row
''Apply Filter
ws.Range("A2:B2").AutoFilter Field:=1, Criteria1:="0"
''Delete the Rows
Application.DisplayAlerts = False
ws.Range("A2:A" & lRow).SpecialCells(xlCellTypeVisible).EntireRow.Delete
Application.DisplayAlerts = True
ws.ShowAllData
End Sub

Issue with 'Next' if there is an error 'On Error' ends VBA

I have a code to filter data and copy to new worksheet. I have an issue where if the sheet being created already exists then it will jump to error handling and stop not continue with remaining 'next'. If i move the 'Next' after the error handling it will only loop if there is and error. Is there a way I can have both?
Sub SortDataAll()
' Sort Data All
If (Workbooks("Fakturagrunnlag All_1.xlsm").Sheets("All Focal Point Data").AutoFilterMode And Workbooks("Fakturagrunnlag All_1.xlsm").Sheets("All Focal Point Data").FilterMode) _
Or Workbooks("Fakturagrunnlag All_1.xlsm").Sheets("All Focal Point Data").FilterMode Then
Workbooks("Fakturagrunnlag All_1.xlsm").Sheets("All Focal Point Data").ShowAllData
End If
'~~> Set filter of main data
Dim rRange As Range
Dim rCell As Range
Set rRange = Worksheets("Front Page").Range("A7:A21")
For Each rCell In rRange
MsgBox "Setting filter for " & rCell
Dim rList As String
rList = rCell & "List"
MsgBox "The list for filter is" & rList
' can remove after
Worksheets("All Focal Point Data").Activate
Dim v As Variant
v = Application.WorksheetFunction.Transpose(Range(rList).Value)
Range("A:BC").AutoFilter Field:=54, Criteria1:=v, Operator:=xlFilterValues
Selection.AutoFilter Field:=54, Criteria1:=v, Operator:=xlFilterValues
MsgBox "Check data is filtered"
'~~> Create new sheet and paste data
On Error Resume Next
With ThisWorkbook
.Sheets.Add(After:=.Sheets(.Sheets.Count)).Name = rCell
End With
If Err Then GoTo ErrorJump
Err.clear
Worksheets("All Focal Point Data").Range("A1:BC5000").Copy Worksheets(rCell).Range("A1").Paste
Columns("BB:BB").Delete Shift:=xlToLeft
Next rCell
Exit Sub
ErrorJump:
MsgBox "Sheet already exists":
Application.DisplayAlerts = False
ActiveWindow.SelectedSheets.Delete
Application.DisplayAlerts = True
'Worksheets("Front Page").Activate
'Range("A1").Select
Next rCell
End Sub
I've used a method where you simply try to use the worksheet and let error control create the worksheet if an error is thrown.
In this, if the abc worksheet exists, it is used. If it doesn't exist, it is created then used.
sub testws()
dim wsn as string
wsn = "abc"
on error goto make_ws
with worksheets(wsn)
on error goto 0
...
end with
exit sub
make_ws:
with worksheets.add
.name = wsn
end with
resume
end sub

Resources