#excel #vba #autofilter
#excel #vba #автофильтр
Вопрос:
Я написал макрос, который выполняет поиск по рабочей книге и применяет автофильтр к любым объектам списка, у которых есть столбец с именем «Code». Однако, когда я применяю фильтр, он не отфильтровывает пустые строки. Есть идеи о том, как я могу их отфильтровать?
Вот код, который применяет фильтр:
Public Sub ApplyFilter(filter As Variant)
Dim wb As Workbook
Dim ws As Worksheet
Dim lo As ListObject
Set wb = ActiveWorkbook
' Loop through each sheet in the workbook
For Each ws In wb.Sheets
' Find any listobjects within the sheet
For Each lo In ws.ListObjects
Dim r As Integer
' Find the column named Code and filter on this column
r = lo.Range.Rows(1).Find("Code").Column
' Clear any existing filter
lo.Range.AutoFilter Field:=r
' If the filter code is not "All Categories", 999, apply the filter
If filter(0) <> 999 Then
lo.Range.AutoFilter Field:=r, Criteria1:=filter, Operator:=xlFilterValues
End If
Next
Next
End Sub
Передаваемый фильтр представляет собой массив, который может иметь только один критерий или несколько. Я также попытался добавить criteria2:=»», но это ничего не изменило.
Дайте мне знать, если у вас есть какие-либо идеи. Спасибо!
Вот другой связанный код:
Public Sub FilterInvoice(filter As Range)
Me.ApplyFilter Me.BuildFilter(filter)
End Sub
Public Function BuildFilter(filter As Range) As Variant
Dim r As Range
Dim arFilter() As String
' Get the cell of the current category
Set r = Range("Categories").Find(filter.Value)
' Set the initial filter value to the category id
ReDim Preserve arFilter(1)
arFilter(0) = r.Offset(0, -1).Value
' Find any child categories, add child id's to filter array
For c = 1 To Application.CountIf(Range("Categories").Columns(3), arFilter(0))
Dim PrevChild As Range
' Expand the filter array
ReDim Preserve arFilter(c 1)
If c = 1 Then
Set PrevChild = Range("Categories").Columns(3).Find(arFilter(0))
Else
' If it is not the first time through the loop, look for the next child after PrevChild
Set PrevChild = Range("Categories").Columns(3).Find(arFilter(0), PrevChild)
End If
' Offset the found child to get its code, add it to the filter array
arFilter(c) = PrevChild.Offset(, -2)
Next
' Add "<>" and "<900" to the criteria list to hide blank rows
'ReDim Preserve arFilter(UBound(arFilter) 2)
'arFilter(UBound(arFilter) - 1) = "<>"
'arFilter(UBound(arFilter)) = "<900"
'Return the filter array
BuildFilter = arFilter
End Function
Ответ №1:
Если вы выполняете фильтрацию по нескольким критериям с использованием массива, то, не включая «=», автофильтр должен фильтровать пробелы. Например, это НЕ приведет к фильтрации пробелов:
Criteria1:=Array("test", "2", "3", "4", "=")
В противном случае вам может потребоваться скрыть их вручную с помощью специальных ячеек (xlcelltypeblanks).
Редактировать:
Хорошо, я думаю, что, возможно, я вас смутил своим первым решением. Я удалил его.
Теперь, когда я вижу ваш код, я думаю, что может произойти то, что, когда вы перебираете диапазон и добавляете свои критерии, вы, вероятно, добавляете пустую ячейку. Пройдите цикл по одному и убедитесь, что это не так. Вы можете добавить это, чтобы отобразить фильтр и убедиться, что он не содержит пробелов:
Отладка.Print Join(arfilter, «,»)
Комментарии:
1. Не могли бы вы расширить? Мне нужно, чтобы одним из критериев был мой массив, содержащий коды, для которых я фильтрую. Я попытался использовать массив в качестве первого критерия и «<>» в качестве критерия 2, это не дало никаких результатов. Если я оставлю для оператора значение xlFilterValues, он выдает исходные результаты (с пустыми строками). Из любопытства, что означает критерий «<>»?
2. Если вам нужна дополнительная помощь, пожалуйста, покажите мне код, который заполняет фактический фильтр, который вы используете, и вызывает подпрограмму applyfilter.
3. Думаю, это будет вручную. Я изменил код build-filter, чтобы добавить оба «<>» и «<900» в конец массива, и он продолжал давать мне странные результаты как с xlAnd, так и с xlFilterValues. Спасибо за информацию!
4. Вы правы. Мне нужно было, чтобы мое первое сохранение redim было сохранением redim с сохранением arfilter(0), а не arfilter(1). Спасибо за помощь!
Ответ №2:
Я знаю, что это старый вопрос, но я не смог найти удовлетворительного ответа нигде в Интернете
Итак, я хотел бы поделиться решением, которое, похоже, работает довольно хорошо:
ActiveSheet.Range("$A$1:$V$3000").AutoFilter Field:=ActiveSheet.Range("$A$1:$V$1").Find("Monitoring").Column, _
Criteria1:="<>Done", Operator:=xlFilterValues
пустые ячейки все еще присутствуют, поэтому нам не нужно их отфильтровывать
ActiveSheet.Range("$A$1:$V$1").Find("Monitoring").EntireColumn.SpecialCells(xlCellTypeBlanks).EntireRow.Hidden = True
Конечно, поскольку он использует xlFilterValues, вы также можете использовать фильтр массива
ActiveSheet.Range("$A$1:$V$3000").AutoFilter Field:=ActiveSheet.Range("$A$1:$V$1").Find("Monitoring").Column, _
Criteria1:=Array( _
"Department1", "Department2", "Department3", "Department4", _
"Department5", "Department6", "="), Operator:=xlFilterValues
Надеюсь, вам понравится!