这个问题有时会出现(例如:参见here和here),并且几乎总是基于某些循环(使用AutoFilter()
本身或数组)给出解决方案
由于某些原因,Excel开发人员将AutoFilter
自定义数组条件的功能限制为最多两个,因此以下操作将不起作用:
Dim filterNotCriteria = Array("<>A","<>B","<>C")
someRange.AutoFilter field:=1, Criteria1:=filterNotCriteria, Operator:=xlFilterValues
虽然我认为完全{em>提供此AutoFilter()
功能会非常有帮助,因为它是针对“非自定义”功能的
因此,在等待Excel开发人员添加(或修复它,因为它在我看来更像是个错误)的同时,我将以公开调查的方式开始这个问题(不确定这是否合适)从性能和可用性的角度来看,什么可能是最好的VBA修复
我正在添加第一个答案以开始滚球
答案 0 :(得分:1)
我的第一个想法是坚持使用AutoFilter()
,以从其性能中受益
使用一些逆向思维,步骤如下:
具有相应NOT(条件)的过滤器
以便得到我们不需要的东西
隐藏我们获得的行,并且我们不需要
离开“需要的”行
如下:
Option Explicit
Function AutoFilterNot(rngToFilter As Range, fieldToFilterOn As Long, filterNotCriteria As Variant) As Range
Dim notRng As Range ' helper range variable
With rngToFilter ' reference wanted range to filter, headers row included
.AutoFilter field:=fieldToFilterOn, Criteria1:=filterNotCriteria, Operator:=xlFilterValues ' filter on "not wanted" values
If Application.Subtotal(103, .Resize(, 1)) > 1 Then ' if any filtered cell other than header row
Set notRng = .Offset(1).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible) ' temporarily set 'myRng' to "not wanted" rows
.Parent.AutoFilterMode = False ' remove filters and show all rows
notRng.EntireRow.Hidden = True ' leave "wanted" rows only visible
Set AutoFilterNot = .Offset(1).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible) ' get referenced range "wanted" rows
.EntireRow.Hidden = False ' unhide all referenced range rows
Else
.Parent.AutoFilterMode = False ' remove filters
End If
End With
End Function
并且可以在某些“主要”代码中使用,如下所示:
Dim filteredRng As Range
Set filteredRng = AutoFilterNot(Range("A1:C200"), 2, Array("B102", "A107"))
答案 1 :(得分:0)
集成重复性Filter
功能的方法
这个想法是定义一个include
条件数组,它否定地应用Filter
函数(即通过参数False
)以排除数组dont
中的搜索项(包含所有条件)您不想显示)。
Sub ExcludeThem()
' Purpose: exclude search terms "A","B" and "C" from AutoFilter display
' [0] temporary boundary delimiters needed (because of automatic wild card search by Filter function)
Const delim$ = "."
' [1] define exclude criteria
Dim dont
dont = Array("A", "B", "C"): AddDelimiters dont, delim
' [2] define include items; consider dictionary keys instead to get only unique items :-)
Dim include, rng As Range ' change source range to your Needs (here A1:A10)
Set rng = Sheet1.Range("A1:A10") ' refers to sheet via CodeName, e.g. AutFlt or Sheet1
include = Application.Transpose(rng.Value2): AddDelimiters include, delim
' [3] resize include items by subsequent filtering out dont items
Dim i&
For i = 0 To UBound(dont)
include = Filter(include, dont(i), False, vbTextCompare)
Next i
' [4] clear remaining include items from temporary delimiters
RemoveDelimiters include, delim
' [5] Execute AutoFilter, cf. https://docs.microsoft.com/en-us/office/vba/api/excel.range.autofilter
rng.AutoFilter field:=1, Criteria1:=include, Operator:=xlFilterValues
End Sub
帮助过程
Sub AddDelimiters(ByRef arr, Optional ByVal delim$ = ".")
' Purpose: add boundary delimiters to array items
Dim i&
For i = LBound(arr) To UBound(arr)
arr(i) = delim & arr(i) & delim
Next i
End Sub
Sub RemoveDelimiters(ByRef arr, Optional ByVal delim$ = ".")
' Purpose: remove boundary delimiters from array items
Dim i&
For i = LBound(arr) To UBound(arr)
arr(i) = Replace(arr(i), delim, vbNullString)
Next i
End Sub