Excel:具有两个以上条件的自动筛选例外

时间:2018-09-09 16:05:49

标签: excel vba autofilter

这个问题有时会出现(例如:参见herehere),并且几乎总是基于某些循环(使用AutoFilter()本身或数组)给出解决方案 >

由于某些原因,Excel开发人员将AutoFilter自定义数组条件的功能限制为最多两个,因此以下操作将不起作用:

    Dim filterNotCriteria = Array("<>A","<>B","<>C")

    someRange.AutoFilter field:=1, Criteria1:=filterNotCriteria, Operator:=xlFilterValues

虽然我认为完全{em>提供此AutoFilter()功能会非常有帮助,因为它是针对“非自定义”功能的

因此,在等待Excel开发人员添加(或修复它,因为它在我看来更像是个错误)的同时,我将以公开调查的方式开始这个问题(不确定这是否合适)从性能和可用性的角度来看,什么可能是最好的VBA修复

我正在添加第一个答案以开始滚球

2 个答案:

答案 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