【问题标题】:How to use "If" in array for filtering multiple columns with multiple criteria vba如何在数组中使用“If”来过滤具有多个条件vba的多个列
【发布时间】:2021-03-24 00:48:12
【问题描述】:

我试图找出我们是否可以在数组中使用“If”来过滤单个代码中的多个列。例如,我有 2 列中的数据 & 要获得结果,我必须使用过滤器两次。

在第 7 列、today-3 和第 8 列之前使用 Apple 进行过滤的第一步

ActiveSheet.Range("A1:W100000").AutoFilter Field:=7, Operator:=xlFilterValues, Criteria1:="Apple"
ActiveSheet.Range("A1:W100000").AutoFilter Field:=8, Operator:=xlFilterValues, Criteria1:="=>"& Date-3)

第二步,在第 7 列和第 7 列以及第 8 列之前使用 Banana 进行过滤

ActiveSheet.Range("A1:W100000").AutoFilter Field:=7, Operator:=xlFilterValues, Criteria1:="Banana"
ActiveSheet.Range("A1:W100000").AutoFilter Field:=8, Operator:=xlFilterValues, Criteria1:="=>"& Date-7)

是否可以通过将“If”用作数组,例如“(If field 7 = Apple, fields 8 = "=>"& Date-3) 和 (If field 7 = Banana,字段 8 = "=>"& Date-7)"?

请帮忙

Sub Get_Value()
    Sheets.ADD After:=Sheets(Sheets.count)
    ActiveSheet.Name = "Sheet2"
    Worksheets("Sheet1").Select
    Worksheets("Sheet1").AutoFilterMode = False
    Application.DisplayAlerts = False
    ActiveSheet.Range("A1:AZ100000").AutoFilter Field:=7, Criteria1:="Apple"
    ActiveSheet.Range("A1:AZ100000").AutoFilter Field:=8, Criteria1:="<=" & Date - 3
If (ActiveSheet.Range("G2", Range("G" & Rows.count).End(xlUp)).SpecialCells(xlCellTypeVisible).count - 1) = 0 Then
    MsgBox "There are no values found"
    Else
    Worksheets("Sheet1").Range("A1").Select
    Range(Selection, Selection.End(xlDown)).Select
    Range(Selection, Selection.End(xlToRight)).Select
    Application.CutCopyMode = False
    Selection.Copy
    Worksheets("Sheet2").Select
    Range("A1").Select
    ActiveSheet.Paste
End If
    Worksheets("Sheet1").Select
    Worksheets("Sheet1").AutoFilterMode = False
    Application.DisplayAlerts = False
    ActiveSheet.Range("A1:AZ100000").AutoFilter Field:=7, Criteria1:="Banana"
    ActiveSheet.Range("A1:AZ100000").AutoFilter Field:=8, Criteria1:="<=" & Date - 7
If (ActiveSheet.Range("G2", Range("G" & Rows.count).End(xlUp)).SpecialCells(xlCellTypeVisible).count - 1) = 0 Then
    MsgBox "There are no values found"
    Else
    ActiveSheet.Range("G2", Range("G" & Rows.count).End(xlUp)).SpecialCells(xlCellTypeVisible).Copy
    Worksheets("Sheet2").Select
    Range("A1").Select
    ActiveSheet.Paste
End If

结束子

【问题讨论】:

  • 如果您需要(7=A AND 8=3)OR(7=B AND 8=7),那么根据您打算用它做什么,有几种可能性。你打算用它做什么?查看它,打印它,将它或其值复制到另一个工作表等。请澄清。另外,如果您没有 99,999 行数据,您可以考虑计算最后一行。
  • 我想将过滤后的数据复制到另一个工作表。如果我使用上面的代码,那么我将不得不复制第一个结果,即 7=A 和 8=3(有时可能没有结果),然后再次应用过滤器,即 7=B 和 8=7 并将第二个结果复制到另一张纸的下一个可用行。为了避免这种重复或重复,我正在寻找具有上述标准的单个过滤器并复制到另一张纸上。工作表不会有 99,999 行数据。
  • 值是否正常,还是您也需要格式和公式?你能发布你到目前为止的完整代码吗?
  • @VBasic2008 - 我添加了完整的代码。如果你也能在值、格式和公式方面提供帮助,那就太好了。提前致谢!
  • 旁白——考虑阅读How to avoid using Select in Excel VBA

标签: excel vba


【解决方案1】:

考虑为您的逻辑需求创建一个新列,并在该条件下应用过滤器。下面避免 SelectActiveSheet 并使用所有 Excel 工作表和范围对象的完整期间限定符。此外,下面仅显示特定的过滤器解决方案,而不是应相应集成的其他新工作表或复制/粘贴步骤。

Dim i As Long

With ThisWorkbook.Worksheets("Sheet1")
    .AutoFilterMode = False
     Application.DisplayAlerts = False

    ' ADD CONDITIONAL COLUMN (G AS 7th COLUMN, H AS 8TH COLUMN)
    For i = 2 To 100000
       .Range("BA" & i).Formula = "=IF(OR(AND(G" & i & " = ""Apple"",  H" & i & " <= DATEVALUE(""" & Date - 3 & """))," _
                                      & " AND(G" & i & " = ""Banana"", H" & i & " <= DATEVALUE(""" & Date - 7 & """))), TRUE, FALSE)"
    Next i
    
    ' ALTERNATIVE PER @VBasic2008
    ' .Range("BA2:BA" & 20).Formula = "=IF(OR(AND(G2 = ""Apple"",  H2 <= TODAY() - 3)," _
    '                                     & " AND(G2 = ""Banana"", H2 <= TODAY() - 7)), TRUE, FALSE)"

    ' APPLY FILTER (BA BEING 53RD COLUMN)
    .Range("A1:BA1").AutoFilter Field:=53, Criteria1:="TRUE"
End With

【讨论】:

  • 循环是非常不可接受的,当你可以改进例如.Range("BA2:BA100000").Formula = "=IF(OR(AND(G2=""Apple"",H2&lt;=TODAY()-3),AND(G2=""Banana"",H2&lt;=TODAY()-7)),TRUE,FALSE)"。你不这么认为吗?
  • @VBasic2008 - 谢谢,公式完美。
  • 好点@VBasic2008 并重写公式!
【解决方案2】:

复制多重过滤 (Advanced Filter)

Option Explicit

Sub copyMultiFiltered()
    
    Const sName As String = "Sheet1"
    Const dName As String = "Sheet2"
    
    Dim Fields As Variant: Fields = Array(7, 8)
    Dim CritPairs As Variant
    CritPairs = Array("Apple", 3, "Banana", 7)
    
    Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
    
    Dim fInit As Long: fInit = LBound(Fields) - 1
    Dim crInit As Long: crInit = LBound(CritPairs) - 1
    Dim rCount As Long: rCount = (UBound(CritPairs) - crInit) / 2 + 1
    Dim Data As Variant: ReDim Data(1 To rCount, 1 To 2)
    
    Dim srg As Range: Set srg = wb.Worksheets(sName).Range("A1").CurrentRegion
    
    Dim j As Long
    For j = 1 To 2
        Data(1, j) = srg.Cells(1, Fields(fInit + j)).Value
    Next j
    For j = 2 To rCount
        Data(j, 1) = CritPairs((j - 2) * 2 + crInit + 1)
        Data(j, 2) = "<=" & CLng(Date - CritPairs((j - 2) * 2 + crInit + 2))
    Next j
    
    Application.ScreenUpdating = False
    
    On Error Resume Next
    Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
    On Error GoTo 0
    If dws Is Nothing Then
        Set dws = wb.Worksheets.Add(After:=wb.Sheets(wb.Sheets.Count))
        dws.Name = dName
    Else
        dws.Cells.Clear
    End If
    
    Dim crg As Range
    Dim drg As Range
    With dws.Range("A1")
        Set crg = .Resize(rCount, 2)
        crg.Value = Data
        Set drg = .Resize(, srg.Columns.Count).Offset(rCount + 1)
    End With
    
    srg.AdvancedFilter xlFilterCopy, crg, drg
    
    dws.Rows(1).Resize(rCount + 1).Delete
    srg.Rows(1).Copy
    With dws.Cells(1)
        .PasteSpecial Paste:=xlPasteColumnWidths
        Application.CutCopyMode = False
        .Worksheet.Activate
        .Select
    End With
    
    Application.ScreenUpdating = True

End Sub

【讨论】:

    猜你喜欢
    • 2022-01-24
    • 2020-01-07
    • 1970-01-01
    • 2019-03-02
    • 2021-07-05
    • 1970-01-01
    • 2023-03-31
    • 2019-10-20
    • 2021-11-20
    相关资源
    最近更新 更多