【问题标题】:Filtering Excel with VBA and exiting Sub if there is no result使用 VBA 过滤 Excel 并在没有结果时退出 Sub
【发布时间】:2017-07-22 03:57:59
【问题描述】:

我有一些代码可以过滤大型数据集,然后选择可见单元格,然后将范围复制并粘贴到其他地方。

Sub Filterstuff()
' Select & Filter data
    Sheets("Main").Select
    Lastrow = ActiveSheet.Range("A2").End(xlDown).Row
    Range("A1").Select
    Range(Selection, Selection.End(xlToRight)).Select
    Range(Selection, Selection.End(xlDown)).Select
    Selection.AutoFilter

' Filter for things
    ActiveSheet.Range("A1:AU" & Lastrow).AutoFilter Field:=39, Criteria1:="words"
    ActiveSheet.Range("A1:AU" & Lastrow).AutoFilter Field:=43, Criteria1:= _
        "<>*wordswords*"

' Find the first unfiltered cell
    Range("A1").Select
    ActiveCell.Offset(1, 0).Select
    Do Until ActiveCell.EntireRow.Hidden = False
        ActiveCell.Offset(1, 0).Select
    Loop

' If there are no unfiltered cells, exit
    If ActiveCell.Row = Lastrow + 1 Then
        Exit Sub

' Else paste results normally
    Else
        Range(Selection, Selection.Offset(0, 47)).Select
        Range(Selection, Selection.End(xlDown)).Select
        Selection.SpecialCells(xlCellTypeVisible).Select
        Selection.Copy
        ' Paste to bottom
        Sheets("PasteSheet").Select
        countrows = Cells(Cells.Rows.Count, "A").End(xlUp).Row
        Range("A" & countrows + 1).Select
        ActiveSheet.Paste
    End If

' Return to Main and unfilter
    Sheets("Main").Select
    Cells.Select
    ActiveSheet.ShowAllData
    Selection.AutoFilter

End Sub

我的问题位于代码块中,如果所有内容都被过滤掉并且过滤后没有包含数据的结果行,则该代码块意味着退出子程序。相关代码从注释部分“查找第一个未过滤的单元格”开始。

此代码查找第一个未隐藏的行,并检查它是否在数据集中的最后一行数据之后。我的问题是它非常慢。我的数据集可以是 100,000+ 行,并且使用 ActiveCell.Offset(1, 0).Select 循环遍历它需要很长时间。

如果所有内容都被过滤掉,我该如何重新编写此代码以退出 sub?

【问题讨论】:

  • 避免使用Select(这将提高运行时性能)。然后,获取所有“数据”范围的句柄(使用提供的第二个链接),然后在应用自动过滤器后,检查范围的 SpecialCells(xlCellTypeVisible).Count。只要.Count 大于您范围内的列数,那么您就有至少一行可见的数据(假设您的数据有标题——如果您的数据没有标题,那么您只需检查..Count &gt; 0。无需循环查看每个单元格是否被自动过滤器隐藏。

标签: vba excel


【解决方案1】:

避免使用Select(这将提高运行时性能):

http://stackoverflow.com/questions/10714251

然后,获取所有“数据”的句柄。最后,应用自动过滤器后,检查范围的SpecialCells(xlCellTypeVisible).Count

只要.Count 大于您范围内的列数,那么您就有至少一行可见的数据(假设您的数据有headers -- 如果没有 headers,你可以比较是否 > 0)。

未经测试:

Sub Filterstuff()
    ' Select & Filter data
    Dim ws as Worksheet
    Dim rng as Range

    Set ws = Worksheets("Main")
    Set rng = ws.Range("A2:AU" & ws.Range("A2").End(xlDown).Row))

    rng.AutoFilter

    ' Filter for things
    rng.AutoFilter Field:=39, Criteria1:="words"
    rng.AutoFilter Field:=43, Criteria1:="<>*wordswords*"

    ' Find the first unfiltered cell
    If rng.SpecialCells(xlCellTypeVisible).Count > rng.Columns.Count Then
        'Autofilter has returned at least one row of data
    Else
        MsgBox "No data results from Autofilter"
        Exit Sub
    End If

    <more code...>

【讨论】:

  • 是的,这可以做到。谢谢你。我认为使用 xlDown 可以安全地找到最后一行,因为 A 列永远不应该有空格,但是链接中的 xlUp 方法要安全得多。我知道我需要对我的代码库进行大规模重构以不使用 Select 和 ActiveSheet,但鉴于我的问题,我现在似乎必须解决这个问题。
  • 我补充说,这只是为了“最佳实践”——原始代码中的真正陷阱是蛮力迭代 :)
猜你喜欢
  • 2014-03-04
  • 2012-02-22
  • 2015-04-10
  • 1970-01-01
  • 2014-07-19
  • 1970-01-01
  • 2018-10-14
  • 2021-12-19
  • 2021-02-06
相关资源
最近更新 更多