Простите, недостаточно комментариев. (Администраторы, не стесняйтесь вырезать это в комментарий выше.) Пользовательский ответ “danicotra”, начиная с “Я использую VBA/Macro на основе Worksheet_Change события тоже, но мой подход …” с 0x2 и ‘ сначала удалить фильтр 0x2 и ’, а затем применить его снова 0x2 и является правильным решением при использовании Excel 2007+. Однако .AutoFilter.ApplyFilter недействителен в XL03 и более ранних версиях, поэтому я покажу способ, описанный ниже.
Я прошу истинных экспертов и гуру прочитать код, потому что я уверен, что это материал с верхней полки. Возможно, необъяснимый счет даунвот на этот ответ может быть обращен вспять, когда люди увидят, какие хорошие вещи делаются ниже.
danicotra использовали упрощенный пример. На самом деле, вы можете сделать это в более общем виде. Assume With ActiveSheet для следующего (или другого объекта листа):
Сохраните диапазон автофильтра. Он имеет .AutoFilter.Filters.Count столбцы, и (.AutoFilter.Range.Count/.AutoFilter.Filters.Count) строки, сохраненные в rngAutofilter
Соберите в массиве myAutofilters каждое из 4 свойств каждого из .AutoFilter.Filters.Count autofilter.Items, заботясь о том, чтобы избежать “Ошибок, определенных приложением”, когда .On или .Operator ложны. (MyAutofilters был бы повторен на количество строк и столбцов в шаге 1)
Выключите фильтр, но сохраните выпадающие строки с помощью .ShowAllData
Для каждого элемента фильтра, который был .On в соответствии с сохраненным массивом, сбросьте 3 из 4 свойств каждого из .AutoFilter.Filters.Count autofilter.itemss. Снова позаботьтесь о том, чтобы избежать “Ошибок, определенных приложением”, когда .Operator равен false, поэтому для каждого элемента “i”,
rngAutofilter.AutoFilter Field:=i, Criteria1:=myAutofilters(i,2)
или
rngAutofilter. AutoFilter Field:=i, Criteria1:=myAutofilters(i,2), Operator:=myAutofilters(i,3), Criteria2:=myAutofilters(i,4)
Теперь автофильтр будет переустановлен, в том же диапазоне, что и до запуска вашего кода, но с обновлением автофильтра для изменения данных.
Public myAutofilters As Variant, rngAutofilter As Range 'Public
Sub SaveAndRestoreAutofilters()
'This will update the autofilter display to recognize data changes by turning autofilter off and then on, preserving all characteristics
'Note, XL2007 and later have .autofilter.applyfilter, but not the invaluable XL03 and earlier
Dim i As Long, iNumAutofilters As Long, iNumActiveAutofilters As Long
iNumActiveAutofilters = SaveAutoFilterInfo(iNumAutofilters) 'NOTE! Use CALL or assignment to prevent parentheses from forcing ByVal !
If iNumActiveAutofilters < 1 Then
Application.StatusBar = "0 ACTIVE filters;" & iNumAutofilters & " autofilters"
Exit Sub
End If
ActiveSheet.ShowAllData
Rem Here optionally do stuff which can include changing data or toggling autofilter columns
For i = 1 To iNumAutofilters
If myAutofilters(i, 1) Then
If myAutofilters(i, 3) <> 0 Then 'then .Operator is something, so set it and Criteria2, else just Criteria1
rngAutofilter.AutoFilter Field:=i, Criteria1:=myAutofilters(i, 2), Operator:=myAutofilters(i, 3), Criteria2:=myAutofilters(i, 4) ', On:=true by rule
Else
rngAutofilter.AutoFilter Field:=i, Criteria1:=myAutofilters(i, 2) ', On:=true by rule (it's R/O anyway)
End If
Rem Selection.AutoFilter Field:=i 'How you'd "turn off" only a single column's autofiltering. FYI .On is R/O!
End If
'activesheet.autofiltermode=false 'just FYI, how you comprehensively turn off filtering on a sheet (erasing the dropdowns and criteria and filter range!)
Next i
End Sub
Function SaveAutoFilterInfo(iNumAutofilters As Long) As Long
Dim i As Long, iRowsAutofiltered As Long
SaveAutoFilterInfo = 0 'counts the number that are .On, and returns the total
iNumAutofilters = ActiveSheet.AutoFilter.Range.Columns.Count
If ActiveSheet.AutoFilter.Filters.Count <> iNumAutofilters Then MsgBox "I can't explain this. All bets are off. Aborting.": Exit function
ReDim myAutofilters(1 To iNumAutofilters, 4)
For i = 1 To iNumAutofilters
myAutofilters(i, 1) = ActiveSheet.AutoFilter.Filters(i).On
If myAutofilters(i, 1) Then
SaveAutoFilterInfo = SaveAutoFilterInfo + 1
myAutofilters(i, 2) = ActiveSheet.AutoFilter.Filters(i).Criteria1
myAutofilters(i, 3) = ActiveSheet.AutoFilter.Filters(i).Operator
If myAutofilters(i, 3) <> 0 Then 'then is either xlAnd, xlOr, etc., and there's a second criteria
myAutofilters(i, 4) = ActiveSheet.AutoFilter.Filters(i).Criteria2
End If
End If
Next i
iRowsAutofiltered = ActiveSheet.AutoFilter.Range.Count / ActiveSheet.AutoFilter.Range.Columns.Count
Set rngAutofilter = Cells(ActiveSheet.AutoFilter.Range.Row, ActiveSheet.AutoFilter.Range.Column).Resize(iRowsAutofiltered, iNumAutofilters)
End Function