I am trying to apply an autofilter in VBA for three different criterias in the same field. Once I have applied the filter I would like to find all those cells that are blank, can anyone advise?
Sub ApplyAutoFiler()
Dim ws As Worksheet
Dim I, j, NumberOfErrors As Long
IsErrors = False
Set ws = Sheets("Assessments")
NumberOfErrors = 0
Dim Z As Range
Set Z = Cells(4, 3).EntireColumn.Find("*", SearchDirection:=xlPrevious)
If Not Z Is Nothing Then
NumberOfRows = Z.Row
End If
For I = 4 To NumberOfRows
With ws
.AutoFilterMode = False
.Range("W4:AA4").AutoFilter Field:=1, Criteria1:=Array("A", "B", "C"), Operator:=xlFilterValues
.Cells.SpecialCells(xlCellTypeBlanks).Interior.Color = 65535
.AutoFilterMode = False
End With
Next I
End Sub
I ended up doing this as a nested if statement
If Range("W" & i).Value = "A" Or Range("W" & i).Value = "B" Or Range("W" & i).Value = "C" Then
If Range("AD" & i).Value = "" Then
Range("AD" & CStr(i)).Interior.ColorIndex = 3
NumberOfErrors = NumberOfErrors + 1
End If
End If
This seemed to get me close (it also assumes you have a worksheet called "Assessments"):
Sub ApplyAutoFiler()
Dim ws As Worksheet
Set ws = Sheets("Assessments")
With ws
.AutoFilterMode = False
.Range("A:AZ").AutoFilter Field:=23, Criteria1:=Array("a", "b", "c"), Operator:=xlFilterValues
.Cells.SpecialCells(xlCellTypeBlanks).Interior.Color = 65535
.AutoFilterMode = False
End With
End Sub
I know this treads had been quite long. But just want to share. To filter out blank cells, you could use autofilter using the following criteria:
Worksheets("sheet name").Range("A1").autoFilter Field:=18, Criteria1:=(Blanks)
"Field" refers to the column numbers. As for "Criteria1", it can be either
Criteria1:=(Blanks)
or
Criteria1:="="
or
Criteria1:=""
Something I just discovered today about filtering for blanks using VBA code. Be sure to include this in ALL code where you need to have blank cells:
' Get Rows with blanks
WorkRange.AutoFilter Field:=1, Criteria1:="=", Operator:=xlOr, Criteria2:="=" & ""
' Hides Rows with blanks ... same idea with the "<>" for operator
WorkRange.AutoFilter Field:=1, Criteria1:="<>", Operator:=xlOr, Criteria2:="<>" & ""
The first criteria gets true blank cells and those cells with hidden/non-printable characters, the 2nd criteria gets those cells containing an empty string. Excel user-interface handles this nicely, but VBA code requires both criteria.
This undocumented caveat just cost me several hours of debugging, not to mention a few choice words from my manager about "I thought we were removing the blanks from these columns..."
Just thought I would share, in the hopes of saving you all some headaches.
You don't need VBA for this. You can use Conditional Formatting for this. See this example
In the CF rule, set this formula
=AND($AA5="",OR($W5="a",$W5="b",$W5="c"))
ScreenShot
If you still want VBA then see this
Sub Sample()
Dim blnkRange As Range, rng As Range, aCell As Range
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Assessments")
With ws
'~~> Sample range for testing purpose
Set rng = .Range("W4:AA11")
.AutoFilterMode = False
With rng
'~~> Filter on "a","b","c"
.AutoFilter Field:=1, Criteria1:=Array("a", "b", "c"), Operator:=xlFilterValues
'~~> Then filter on blanks on Col AA
.AutoFilter Field:=5, Criteria1:="="
'~~> Using offset. Assuming that Row 4 has headers
Set blnkRange = .Offset(1, 0).SpecialCells(xlCellTypeVisible).Cells
End With
.AutoFilterMode = False
End With
'~~> This will give you the blank cells in Col AA
If Not blnkRange Is Nothing Then
For Each aCell In blnkRange
'~~> Color the blank cells red in Col AA
If aCell.Column = 27 Then aCell.Interior.ColorIndex = 3
Next
End If
End Sub
Related
i need your help on the VBA code :
i would like to make a filter on a database according cells in another sheets
my code is working but make a filter only in one cell. How to filter if the code found all cells from the Range
Please see my code :
Sub test()
Sheets("Dashboard").Select
Dim arr As Variant
'arr = Sheets("Dashboard").Range("B4:B11")
With Sheets("Database")
With .Range("A1:Z" & .Cells(.Rows.Count, "A").End(xlUp).Row)
.AutoFilter 'Turn off any previous filtering
.AutoFilter Field:=1, Criteria1:=Sheets("Dashboard").Range("B4:B11")
End With
End With
End Sub
Thanks for your help
Please, test the next way:
Sub filterByRange()
Dim arr, rng As Range
Set rng = Sheets("Dashboard").Range("B4:B11")
rng.TextToColumns Destination:=rng.cells(1), FieldInfo:=Array(1, 2)
arr = rng.Value
arr = Application.Transpose(Application.Index(arr, 0, 1)) '1D array
With Sheets("Database")
With .Range("A1:Z" & .cells(.Rows.count, "A").End(xlUp).row)
.AutoFilter
.AutoFilter field:=1, Criteria1:=arr, Operator:=xlFilterValues
End With
End With
End Sub
Less is more. I adapted the code provided by #FaneDuru utilising some shortcuts. Please note that when it comes to AutoFilter, there’s (usually) no need to specify the complete range you want to filter – it filters all rows meeting the criteria so last column is irrelevant. As long as the data is contiguous, there’s no need to specify the last row either.
Provided for interest only.
Sub testFilter()
Dim Arr
Arr = Sheets("Dashboard").Range("B4:B11").Value
Arr = Application.Transpose(Application.Index(Arr, 0, 1))
With Sheets("Database").Range("A1").CurrentRegion
.AutoFilter 1, Array(Arr), 7
End With
End Sub
Try this:
Sub SubRangeBasedAutofilter()
'Declarations.
Dim RngCell As Range
Dim RngCriteria As Range
Dim StrCriteria() As String
Dim DblCriteriaCount As Double
'Selecting Dashboard sheet.
Sheets("Dashboard").Select '<-IS THIS NECESSARY?
'Setting RngCriteria.
Set RngCriteria = Sheets("Dashboard").Range("B4:B11")
'Redeclaring StrCriteria() with proper size.
ReDim StrCriteria(Excel.WorksheetFunction.Max(Excel.WorksheetFunction.CountA(RngCriteria) - 1, 1))
'Covering each in RngCriteria.
For Each RngCell In RngCriteria
'Checking if RngCell is not empty.
If RngCell.Value <> "" Then
'Storing the criteria.
StrCriteria(DblCriteriaCount) = "=" & RngCell.Value
DblCriteriaCount = DblCriteriaCount + 1
End If
Next
'Focusing Database sheet.
With Sheets("Database")
'Turning off any eventual autofilter.
.AutoFilterMode = False
'Setting a new autofilter.
With .Range("A1:Z" & .Cells(.Rows.Count, "A").End(xlUp).Row)
.AutoFilter Field:=1, Criteria1:=StrCriteria, Operator:=xlFilterValues
End With
End With
End Sub
I want to create an autofilter macro for an excel sheet, that will filter out any rows that do not contain "ballroom*" in Column E, but will also leave any rows where Column E is empty
Have basic programming knowledge, have taught myself what I know thus far in VBA
This is what I have currently
Sub row_deleter()
Dim ws As Worksheet
Dim rng As Range
Dim lastrow As Long
''setting varibles
Set ws = ActiveSheet
lastrow = ws.Range("E" & ws.Rows.count).End(xlUp).Row
Set rng = ws.Range("E1:E" & lastrow)
''actual filter function
With rng
.AutoFilter field:=5, Criteria1:=IsEmpty(rng), Operator:=xlAnd, Criteria2:="=*ballroom*"
.SpecialCells(xlCellTypeVisible).EntireRow.delete
End With
''turn off filters
ws.AutoFilterMode = False
End Sub
When I try to run this code it gives me a 1004 error saying `AutoFilter` method of range class failed, and the debug points to the `AutoFilter` line. Have tried a few things thus far with syntax etc and nothing seems to be working.
First, let's make sure that your table has an AutoFilter. Additionally, your criteria shouldn't be relevant to any range, just what's being filtered. Also, I believe your criteria should be xlOr - a cell can't be blank AND have ballroom in it. Try this:
Sub row_deleter()
Dim ws As Worksheet
Dim rng As Range
Dim lastrow As Long
''setting varibles
Set ws = ActiveSheet
lastrow = ws.Range("E" & ws.Rows.Count).End(xlUp).Row
Set rng = ws.Range("E1:E" & lastrow)
''turn on autofilter if it's off
If ws.AutoFilterMode = False Then
ws.UsedRange.AutoFilter
End If
''actual filter function
With rng
.AutoFilter Field:=1, Criteria1:="=", Operator:=xlOr, Criteria2:="=*ballroom*"
.SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
''turn off filters
ws.AutoFilterMode = False
End Sub
field:= is an offset and you only have a single column as your range. You want that to be field:=1
You are also using xland you want xlor. Can't have both an empty cell and a cell with ballroom.
.AutoFilter Field:=1, Criteria1:=IsEmpty(rng), Operator:=xlOr, Criteria2:="=*ballroom*"
Thought you have your answer and because of your comment (you want to delete every row which doesn't match your criteria) I adjusted your code to make it easier to read and perform what you actually want it to:
Option Explicit
Sub row_deleter()
Dim lastrow As Long
''setting varibles
'you can use a With ActiveSheet and avoid the use of ws Thought I wouldn't recommend using ActiveSheet unless you attach
'this macro to a button on the sheet itself.
With ActiveSheet
lastrow = .Range("E" & .Rows.Count).End(xlUp).Row
''actual filter function
.UsedRange.AutoFilter Field:=5, Criteria1:="<>", Operator:=xlOr, Criteria2:="<>*ballroom*"
.Range("A2:A" & lastrow).SpecialCells(xlCellTypeVisible).EntireRow.Delete
''turn off filters
.AutoFilterMode = False
End With
End Sub
The following code works on worksheets labeled Walk INs
Sub Find_Duplicatel()
Dim wrkSht As Worksheet 'The worksheet that you're lookin for duplicates in.
Dim rng As Range 'The range containing the duplicates.
Dim Col As Long 'The last column containing data +1
Set wrkSht = ThisWorkbook.Worksheets("Walk INs")
With wrkSht
'Reference to whole data range.
Set rng = .Range("A5:L2003")
'If the sheet is blank an error will be thrown when trying to find the last column.
'This code looks for the last column - you could just set Col to equal the last column number + 1.
On Error Resume Next
Col = 12
Err.Clear
On Error GoTo 0
If Col = 0 Then Col = 0
'Place a COUNTIF formula in the last column.
rng.Offset(, Col).Columns(1).FormulaR1C1 = "=COUNTIF(" & rng.Columns(1).Address(ReferenceStyle:=xlR1C1) & ",RC" & rng.Column & ") & "" duplicates."""
With rng
'Add conditional formatting to first column in range: If the COUNTIF formula is showing >1 then highlight cell.
With .Columns(1)
'This formula is =VALUE(LEFT($M5,FIND(" ",$M5)-1))>1.
'It returns only the number from the duplicate count and checks it is higher than 1.
.FormatConditions.Add Type:=xlExpression, Formula1:= _
"=VALUE(LEFT(" & rng.Offset(, Col).Cells(1).Address(RowAbsolute:=False) & ",FIND("" ""," & _
rng.Offset(, Col).Cells(1).Address(RowAbsolute:=False) & ")-1))>1"
.FormatConditions(.FormatConditions.Count).SetFirstPriority
.FormatConditions(.FormatConditions.Count).Interior.Color = RGB(0, 100, 255)
End With
'Apply filter to your range.
.AutoFilter
.AutoFilter Field:=12, Criteria1:="Yes"
End With
End With
End Sub`
However when I changed Walk INs to VOC_ASST It hangs up on .AutoFilter I am not certain why. Could you inform me what happened & how to fix it. Other than the sheet titles every thing is identical.
You can add some code it to check if there is an AutoFilter already.
If .AutoFilterMode = False Then
.AutoFilter
.AutoFilter Field:=12, Criteria1:="Yes"
End If
I found the following code on the ENCODEDNA website & after modifying it for my worksheet, it works exactly as I expected.
Sub FIND_DUPLICATE()
`Option Explicit
Dim myDataRng As Range
Dim cell As Range
' WE WILL SET THE RANGE (FIRST COLUMN).
Set myDataRng = Range("A1:A" & Cells(Rows.Count, "B").End(xlUp).Row)
For Each cell In myDataRng
cell.Offset(0, 0).Font.Color = vbBlack ' DEFAULT COLOR.
' LOCATE DUPLICATE VALUE(S) IN THE SPECIFIED RANGE OF DATA.
If Application.Evaluate("COUNTIF(" & myDataRng.Address & "," &
cell.Address & ")") > 1 Then
cell.Offset(0, 0).Font.Color = vbRed ' CHANGE FORE COLOR TO
RED.
End If
Next cell
Set myDataRng = Nothing
ErrHandler:
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub`
Thank you to the people that have assisted me.
I would like to add AutoFilter Criteria to my excel table in separate Subs.
What I have at the moment looks a little something like this
.AutoFilter Field:=deviceTypeColumnId, Criteria1:=[dScenarioIndependent], Operator:=xlOr, _
Criteria2:=[dSmartphoneDeviceType]
What I would like to have is a method to first filter by Criteria1, and then, in another Sub, add Criteria2 to the existing AutoFilter. To my mind, it should look something like this:
Sub firstSub
.AutoFilter Field:=deviceTypeColumnId, Criteria1:=[dScenarioIndependent]
end sub
Sub secondSub
.AutoFilter mode:=xlAddCriteria, Field:=deviceTypeColumnId, Criteria1:=[dSmartphoneDeviceType]
'I know that mode doesn't exist, but is there anything like that?
end sub
Do you know any way to achieve this?
There isn't, that I know of, a way of "adding on" criteria to a filter which has previously been applied.
I have produced a work-around, which would work for what you are attempting to do. You will just have to add on scenarios to the select case statement, going up to the maximum number of filters which you will want to have.
EDIT: what it does; copy the filtered column to a new worksheet, and remove duplicates on that column. You're then left with the values which have been used to filter the column. Assign the values to an array, and then apply the number of elements of the array as a filter on the column, whilst including the new value you wish to filter on.
EDIT 2: added in a function to find the last row for when a table is already filtered (we want the last row, not the last visible row).
Option Explicit
Sub add_filter()
Dim wb As Workbook, ws As Worksheet, new_ws As Worksheet
Dim arrCriteria() As Variant, strCriteria As String
Dim num_elements As Integer
Dim lrow As Long, new_lrow As Long
Set wb = ThisWorkbook
Set ws = wb.Sheets("data")
Application.ScreenUpdating = False
lrow = ws.Cells(Rows.Count, 1).End(xlUp).Row
ws.Range("A1:A" & lrow).Copy 'Copy column which you intend to add a filter to
Sheets.Add().Name = "filter_data"
Set new_ws = wb.Sheets("filter_data")
With new_ws
.Range("A1").PasteSpecial xlPasteValues
.Range("$A$1:$A$" & Cells(Rows.Count, 1).End(xlUp).Row).RemoveDuplicates _
Columns:=1, Header:=xlYes 'Shows what has been added to filter
new_lrow = Cells(Rows.Count, 1).End(xlUp).Row
If new_lrow = 2 Then
strCriteria = .Range("A2").Value 'If only 1 element then assign to string
Else
arrCriteria = .Range("A2:A" & Cells(Rows.Count, 1).End(xlUp).Row) 'If more than 1 element make array
End If
Application.DisplayAlerts = False
.Delete
Application.DisplayAlerts = True
End With
If new_lrow = 2 Then
num_elements = 1
Else
num_elements = UBound(arrCriteria, 1) 'Establish number elements in array
End If
lrow = last_row
Select Case num_elements
Case 1
ws.Range("$A$1:$A$" & lrow).AutoFilter 1, _
Array(strCriteria, "New Filter Value"), Operator:=xlFilterValues
Case 2
ws.Range("$A$1:$A$" & lrow).AutoFilter 1, _
Array(arrCriteria(1, 1), arrCriteria(2, 1), _
"New Filter Value"), Operator:=xlFilterValues
Case 3
ws.Range("$A$1:$A$" & lrow).AutoFilter 1, _
Array(arrCriteria(1, 1), arrCriteria(2, 1), _
arrCriteria(3, 1), "New Filter Value"), Operator:=xlFilterValues
End Select
Application.ScreenUpdating = True
End Sub
Function:
Function last_row() As Long
Dim rCol As Range
Dim lRow As Long
Set rCol = Intersect(ActiveSheet.UsedRange, Columns("A"))
lRow = rCol.Row + rCol.Rows.Count - 1
Do While Len(Range("A" & lRow).Value) = 0
lRow = lRow - 1
Loop
last_row = lRow
End Function
Hope this helps.
I am trying to copy the values from one Excel sheet into another using Filter option. For example I have used only ten records, but in real time I am not sure the data that will be present. Also, I need to know the first cell value after a filter. For example, if I use filter the first value is reflecting as B4 and next time it is showing B6. I need to select that also dynamically using macro.
ActiveSheet.Range("$A$1:$BG$10").AutoFilter Field:=2, Criteria1:="2"
Range("B5:BG5").Select
The above code should be modified. Instead of $BG$10 it should be the number of rows, then Instead of B5:BG5 it must be the first cell after filter.
Try this:
Dim rngToFilter As Range
With ActiveSheet
.AutoFilterMode = False 'to make sure no filter is applied yet
Set rngToFilter = .Range("A1", .Range("BG" & Rows.Count).End(xlUp)) 'set the dynamic range
rngToFilter.AutoFilter Field:=2, Criteria1:="2" 'apply the filter
rngToFilter.Resize(.Range("BG" & Rows.Count).End(xlUp).Row - 1).Offset(1, 0).SpecialCells(xlCellTypeVisible).Select 'Offset 1 row to exclude the header, resize to select the first row only.
End With
Above code selects all the items that are filtered.
I you want so select only the 1st item filtered, then use below.
Sub Sample()
Dim rngToFilter As Range, rngFilter As Range
Dim i As Integer
With ActiveSheet
.AutoFilterMode = False 'to make sure no filter is applied yet
Set rngToFilter = .Range("A1", .Range("BG" & Rows.Count).End(xlUp)) 'set the dynamic range
rngToFilter.AutoFilter Field:=2, Criteria1:="2" 'apply the filter
Set rngFilter = rngToFilter.Resize(.Range("BG" & Rows.Count).End(xlUp).Row - 1).Offset(1, _
0).SpecialCells(xlCellTypeVisible)
rngToFilter.Resize(.Range("BG" & Rows.Count).End(xlUp).Row - _
(rngFilter.Cells.Count / rngFilter.Columns.Count)).Offset(1, _
0).SpecialCells(xlCellTypeVisible).Select
End With
End Sub
No error handler yet.
I leave it to you. :D
Try following code:
Sub test()
Dim lastRow As Long, firstVisibleRow As Long
ActiveSheet.AutoFilterMode = False
'find last non empty row number in column A'
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
'apply filter'
Range("$A$1:$BG$" & lastRow).AutoFilter Field:=2, Criteria1:="2"
On Error GoTo errHandler
'find first visible row number in the filtered range, if there is no rows matching the filter criteria, we'll get message from the MsgBox'
firstVisibleRow = Range("$A$2:$BG$" & lastRow).SpecialCells(xlCellTypeVisible).Row
On Error GoTo 0
'select range'
Range("B" & firstVisibleRow & ":BG" & firstVisibleRow).Select
Exit Sub
errHandler:
MsgBox "There is no rows matching the filter criteria"
End Sub