Excel教程完整指南 从 Excel 教程开始,像驯兽师一样驾驭数据

VBA 自动筛选实战案例

所属主题:VBA 自动筛选 Excel 表格自动化脚本

执行前检查

$ 要完成: 你每天在 Excel 里手工点下拉菜单筛选数据?VBA 自动筛选能把几分钟的重复点击压缩到一两秒。核心是用...
$ 适用范围: 数据整理

VBA 自动筛选实战案例

你每天在 Excel 里手工点下拉菜单筛选数据?VBA 自动筛选能把几分钟的重复点击压缩到一两秒。核心是用 AutoFilter 方法替代手动操作,实现一键过滤、多条件组合、结果自动复制。下面用真实销售表案例,带你写出第一个能稳定运行的筛选代码。

VBA 自动筛选的工作原理

Excel 的自动筛选功能藏在 数据 选项卡 → 排序和筛选 组 → 筛选 按钮。手动操作时,你点表头下拉箭头勾选值;VBA 就是把整个过程写成固定代码,跑一次宏就完成所有筛选步骤,且每次执行结果一致。

用 VBA 做自动筛选前,数据必须满足三个前置条件:

  1. 标准二维表结构:每一列有唯一表头(Header),没有合并单元格,整块区域没有空行打断。
  2. 筛选功能可用:如果工作表已经启用了筛选,需要先清除旧条件再设置新条件——否则新旧条件叠加,结果可能不是你想要的。
  3. 表头行必须可见:表头一旦被隐藏或筛选掉,AutoFilter 就找不到列对应关系,会报错或跳过。

实战案例:从销售表筛选并提取数据

假设有张销售记录表,A 到 E 列分别是:日期、区域、产品、销售额、负责人,共 200 行记录。你的需求是:筛选出"华东"区域且销售"A 产品"的行,然后把结果复制到一个新工作表。

示例数据:

日期 区域 产品 销售额 负责人
2024-01-05 华东 A产品 12800 张三
2024-01-05 华北 B产品 9500 李四
2024-01-06 华东 A产品 14300 张三
2024-01-06 华南 C产品 7200 王五

基础筛选代码

Sub BasicAutoFilter()
    ' 清除已有筛选状态
    If ActiveSheet.AutoFilterMode Then ActiveSheet.AutoFilterMode = False
    
    ' 启用自动筛选:只保留"华东"区域
    Range("A1").CurrentRegion.AutoFilter Field:=2, Criteria1:="华东"
    
    ' 把当前可见行(筛选结果)复制到新工作表
    Range("A1").CurrentRegion.SpecialCells(xlCellTypeVisible).Copy
    Sheets.Add After:=Sheets(Sheets.Count)
    ActiveSheet.Paste
    
    ' 恢复源表为未筛选状态(不干扰后续操作)
    Sheets(1).AutoFilterMode = False
End Sub

逐行拆解:

  • Range("A1").CurrentRegion:自动识别从 A1 开始的连续数据区域,不用手动算最后一行是第几行。
  • Field:=2:筛选区域是第 2 列(B 列——区域列)。
  • Criteria1:="华东":条件等于"华东"这个文本值。
  • SpecialCells(xlCellTypeVisible):只选中当前页面上能看到(未被隐藏)的单元格——这是避免把隐藏行也复制过去的开关。
  • AutoFilterMode = False:最后关掉筛选箭头,把源表恢复成普通表格,方便下一步操作。

运行结果:新工作表里只有区域等于"华东"的行。如果复制出来的是整张表或空白,优先检查数据区域是否真的从 A1 开始、表头行是否包含在区域内。

多条件筛选

AutoFilter 默认规则:不同列的条件是 AND(且)关系,同一列的多个条件是 OR(或)关系。下面演示两种最常见的多条件写法。

写法一:两列条件叠加(AND)

想筛选"区域=华东"且"产品=A产品",分两步对两列分别设置条件:

Sub MultiColumnFilter()
    With ActiveSheet
        If .AutoFilterMode Then .AutoFilterMode = False
        
        .Range("A1").AutoFilter
        
        ' 第2列 = 华东 AND 第3列 = A产品
        .Range("A1").AutoFilter Field:=2, Criteria1:="华东"
        .Range("A1").AutoFilter Field:=3, Criteria1:="A产品"
    End With
End Sub

运行后,只有同时满足两个条件的行才会显示。

写法二:单列多选(OR)

如果想筛选区域属于"华东"或"华南"两种之一(同一列的 OR 条件):

Sub SingleColumnMultiValue()
    Range("A1").CurrentRegion.AutoFilter Field:=2, _
        Criteria1:=Array("华东", "华南"), Operator:=xlFilterValues
End Sub

注意这里必须用 Operator:=xlFilterValues 配合 Array,不能写成 Criteria1:="华东" 再单独拼第二个条件。如果你用了 Array 但没写 Operator:=xlFilterValues,VBA 会报错或只匹配第一个值。

新手最容易卡的 5 个坑

写筛选代码时,对照这份清单自检,能省下大量调试时间:

1. 列号指错了

Field:= 后面的数字是数据区域内的列序号,不是工作表的绝对列号。如果你的数据从 B 列开始(A 列为空或标题),区域是 B2:G100,那么 Field:=1 对应的是 B 列(区域的第 1 列),而不是 A 列。

怎么避坑:写代码前按 Ctrl+End,看数据最后一格的位置,再数数据区域第一列对应工作表哪一列。

2. 条件值的数据类型写错了

筛选数字列时,条件值必须写成数字(不加引号),或用 "=12800" 这种字符串形式。如果你给数值列写了 "12800"(带引号),VBA 会把它当作文本去匹配——如果源表的销售额确实是数值格式,就会匹配不到任何行。

正确的两种写法:

' 写法一:数值不引号(只适用于精确匹配)
Range("A1").CurrentRegion.AutoFilter Field:=4, Criteria1:=12800

' 写法二:字符串形式的等值比较(更稳定,推荐)
Range("A1").CurrentRegion.AutoFilter Field:=4, Criteria1:="=12800"

' 通配符只对文本列生效
Range("A1").CurrentRegion.AutoFilter Field:=2, Criteria1:="=华*"  ' 匹配以"华"开头的区域

3. 筛选后复制时忘了写 SpecialCells

直接在筛选结果上 Copy,会把隐藏行也一起复制——因为 Copy 默认作用在选中的整个区域,而不只是可见部分。在 Copy 之前加 .SpecialCells(xlCellTypeVisible) 才能只复制当前显示的行。

4. 多次设置条件时顺序依赖

如果先对第 2 列设条件,再对第 3 列设条件,两次是叠加(AND)关系。但如果中间执行了一次 AutoFilterMode = False 再重新启用,第二次会完全覆盖第一次。记住这个规则:只要不关筛选再开,多个条件会叠加;一旦关掉再开,前面的条件就没了,只会保留最后一个。

5. 合并单元格搞事情

数据区域里有合并单元格时,AutoFilter 的行为非常奇怪——有时报错,有时只筛选第一行。最稳妥的做法是:在运行筛选代码前先取消所有合并单元格,或者用 On Error Resume Next 跳过这一部分。

筛选结果验证三连

跑完代码后做三个快速检查,确保筛选没出幺蛾子:

  1. 看行号颜色:筛选后隐藏行的行号显示蓝色,可见行显示黑色。如果全部行号都变蓝了,说明筛选条件没匹配到任何数据(区域选错了,或条件值写错了)。
  2. 看表头下拉箭头:筛选成功后,表头单元格右侧会出现下拉箭头图标。如果没出现箭头,检查 AutoFilter 是否真的成功启用(可以在即时窗口输入 ?ActiveSheet.AutoFilterMode 看返回值是不是 True)。
  3. 手动抽查两行:随便挑两行显示出来的记录,看看条件列的值是不是真的符合筛选条件。别假设代码一定正确——出问题的通常是你的假设不符合实际数据的格式。

常见错误速查表

现象 最可能的原因 最快的解决办法
筛选后显示空白 条件值里藏了不可见空格 先对源表做 =TRIM() 清理,或条件写成 ="*华东*"
只有一行被筛出来 区域没包含表头行 改用 Range("A1").CurrentRegion(从有数据的第一格开始)
复制时连隐藏行一起复制了 忘了写 SpecialCells(xlCellTypeVisible) Copy 前先 .Select,再 Selection.SpecialCells(xlCellTypeVisible).Copy