查看: 224|回复: 3

Python实战:使用pandas和xlwings批量筛选Excel工作簿所有工作表数据

[复制链接]
发表于 昨天 11:00 | 显示全部楼层 |阅读模式
在日常办公中,经常需要从一个包含多个工作表的Excel工作簿中,按同一条件筛选数据(例如只保留“销售区域=华东”的记录)。手动操作需要逐表筛选、复制、粘贴,不仅繁琐而且容易遗漏。本文介绍一种基于pandas和xlwings的自动化方案,能稳定地遍历工作簿中所有工作表,按指定字段和值进行筛选,并将结果写入新的工作簿。

适用场景与前置检查
此脚本适用于多个工作表结构相似(表头在第一行、字段名一致、数据连续),且需按同一个字段过滤的场景,例如多月份销售表或区域明细表。
运行前务必确认三点:表头是否在第一行、筛选字段名称是否在所有工作表中统一、数据区域是否连续无空行。若不符合,脚本需额外兼容处理。

核心原理与流程
流程可拆解为五步:打开源工作簿 → 遍历每张工作表 → 利用pandas读取为DataFrame → 按条件过滤数据 → 将结果写入新建的工作簿。
pandas擅长数据筛选与操作,xlwings负责与Excel文件直接交互(打开、读取、写入、保存),两者配合比模拟鼠标点击更稳定。

完整代码实现
以下代码展示一个典型场景:从“销售明细.xlsx”中所有工作表里提取“销售区域”为“华东”的数据,生成新文件“筛选结果_华东.xlsx”。
  1. import os
  2. import re
  3. import pandas as pd
  4. import xlwings as xw
  5. def safe_sheet_name(name):
  6.     """清理工作表名称,避免超过Excel限制或包含非法字符"""
  7.     name = str(name).strip()
  8.     name = re.sub(r'[\\/:*?\[\]]', "_", name)
  9.     return name[:31] if name else "筛选结果"
  10. # 请根据实际环境修改以下参数
  11. source_file = r"E:\example\销售明细.xlsx"
  12. result_file = r"E:\example\筛选结果_华东.xlsx"
  13. filter_column = "销售区域"
  14. filter_value = "华东"
  15. app = xw.App(visible=False, add_book=False)
  16. try:
  17.     wb = app.books.open(source_file)
  18.     result_wb = app.books.add()
  19.    
  20.     # 删除默认多余工作表,保留第一张备用
  21.     while len(result_wb.sheets) > 1:
  22.         result_wb.sheets[-1].delete()
  23.    
  24.     output_count = 0
  25.     for sht in wb.sheets:
  26.         print(f"正在处理工作表:{sht.name}")
  27.         try:
  28.             data = sht.range("A1").options(
  29.                 pd.DataFrame,
  30.                 header=1,
  31.                 index=False,
  32.                 expand="table"
  33.             ).value
  34.         except Exception as e:
  35.             print(f"跳过:{sht.name},读取失败:{e}")
  36.             continue
  37.         
  38.         if data is None or data.empty:
  39.             print(f"跳过:{sht.name},空表或无有效数据")
  40.             continue
  41.         
  42.         # 清理字段名前后空格
  43.         data.columns = [str(col).strip() for col in data.columns]
  44.         
  45.         if filter_column not in data.columns:
  46.             print(f"跳过:{sht.name},缺少字段:{filter_column}")
  47.             continue
  48.         
  49.         # 条件筛选
  50.         result = data[data[filter_column].astype(str).str.strip() == filter_value]
  51.         if result.empty:
  52.             print(f"未命中:{sht.name},没有符合条件的数据")
  53.             continue
  54.         
  55.         # 写入结果工作簿
  56.         if output_count == 0:
  57.             result_sht = result_wb.sheets[0]
  58.             result_sht.name = safe_sheet_name(sht.name)
  59.         else:
  60.             result_sht = result_wb.sheets.add(name=safe_sheet_name(sht.name), after=result_wb.sheets[-1])
  61.         result_sht.range("A1").value = result
  62.         result_sht.autofit()
  63.         output_count += 1
  64.         print(f"已写入:{sht.name},筛选结果 {len(result)} 行")
  65.    
  66.     wb.close()
  67.     if output_count == 0:
  68.         print("没有任何工作表筛选出结果,结果文件未保存。")
  69.         result_wb.close()
  70.     else:
  71.         result_wb.save(result_file)
  72.         result_wb.close()
  73.         print(f"筛选完成:{result_file}")
  74. finally:
  75.     app.quit()
复制代码

关键判断:为什么必须先检查字段存在性
批量处理时,不能默认所有工作表字段完全规范。如果某张表缺少目标字段或字段名有差异,直接使用data[filter_column]会引发异常。代码中通过if filter_column not in data.columns提前判断,可跳过并输出日志,确保脚本不被中断。
若数据来源混乱,可维护一个字段别名列表(如[“销售区域”,“区域”,“所属区域”]),逐个匹配。但需注意别名不能跨语义字段使用,以免误判。

效果验证与数据对账
脚本运行后,不能只看文件是否生成。建议至少检查:结果文件能否正常打开、每个工作表是否存在、筛选字段值是否全部为目标值(可用代码检查)、行数与手工筛选结果是否一致、关键字段是否完整。
验证代码片段(可放在脚本最后):
  1. # 验证某个结果表中的筛选字段是否全部符合条件
  2. check_result = result[filter_column].astype(str).str.strip().eq(filter_value).all()
  3. if check_result:
  4.     print(f"{sht.name} 验证通过:筛选结果全部为 {filter_value}")
  5. else:
  6.     print(f"{sht.name} 验证失败:存在不符合条件的数据")
复制代码

常见踩坑与处理经验
1. 字段名隐藏空格:表头可能带有不可见空格,使用strip()清理字段名和数据值可解决。
2. 筛选值不统一:如“华东”“华东区”“华东区域”被视为不同值,需在筛选前做标准化替换。
3. 工作表名称超长:Excel限制工作表名不超过31字符,safe_sheet_name()做了截断和非法字符替换。
4. 结果文件被占用:运行脚本前关闭源文件和结果文件,否则保存会失败。
5. 默认空白工作表:新建工作簿自带空白表,应删除多余表或复用第一张表,避免结果文件出现无用空表。

总结与扩展建议
本方案的核心模式是“打开工作簿→遍历工作表→读取DataFrame→条件筛选→写入结果”,适用于结构一致的多表批量过滤。值得保留的经验:字段校验比筛选语法更重要;结果验证不能省略;稳定性高于代码简洁。
后续可将源文件路径、筛选条件、字段别名等参数化,或封装成窗口工具,使其成为可复用的自动化组件。
回复

使用道具 举报

发表于 昨天 11:10 | 显示全部楼层

Re: Python实战:使用pandas和xlwings批量筛选Excel工作簿所有工作表数据

这个方案很实用,把pandas的数据处理能力和xlwings的Excel操作结合得恰到好处。代码里对工作表名称的清理和空表/字段缺失的异常处理都考虑得很周全,生产环境下确实容易踩这些坑。 提两个小思路供参考:1)如果数据量很大,可以考虑用`pandas.read_excel`配合`sheet_name=None`先批量读入内存,再统一筛选,避免频繁打开Excel对象;2)筛选值可以扩展成列表或正则,支持多值匹配或模糊筛选,适用面会更广。另外注意xlwings依赖本地安装的Excel,在服务器或无Office环境可能需要换用openpyxl直接写xlsx。 不管怎样,这套代码已经能直接解决“逐表手动筛选”的痛点了,收藏备用。
回复 支持 反对

使用道具 举报

发表于 昨天 11:10 | 显示全部楼层

Re: Python实战:使用pandas和xlwings批量筛选Excel工作簿所有工作表数据

这个方案很实用,把繁琐的逐表筛选自动化了,代码结构也很清晰。特别是对工作表名称的清理和异常处理的考虑,让脚本在真实环境下更稳定。我注意到在筛选条件那里用了 `astype(str).str.strip()` 比对,能避免数字或空格带来的误判,细节处理很到位。 如果想进一步通用化,可以考虑把筛选条件做成参数列表(比如多个字段或值的组合),或者支持通过配置文件传入字段和值,这样适应更多场景。另外,如果数据量非常大,pandas的读取可能会占用较多内存,可以留意一下性能。 总体来讲,这个脚本在批量处理同结构工作表时非常高效,文档也写得很清楚,容易上手。感谢分享!
回复 支持 反对

使用道具 举报

发表于 昨天 11:10 | 显示全部楼层

Re: Python实战:使用pandas和xlwings批量筛选Excel工作簿所有工作表数据

非常实用的分享!这个批处理脚本解决了逐表手工筛选的痛点,而且步骤清晰,还贴心地做了字段名清理、空表跳过和非法字符处理,细节考虑得很周到。 建议可以补充两点:一是如果工作表数量特别多(比如几十上百个),`expand='table'` 读取全表可能较慢,可以改用 `range` 配合 `used_range` 或者分块读取来优化性能;二是对于 `.xls` 格式的旧版文件,xlwings 也支持,但 pandas 直接用 `pd.read_excel` 读取速度可能会更快,可以给用户一个备选方案。另外,可以提醒用户注意筛选字段的格式(比如数值型与字符串的比较),避免因类型不一致导致筛选失效。 总之,代码结构完整,注释清晰,很适合作为团队自动化的基础模板。感谢分享!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-7-1 01:47 , Processed in 0.034975 second(s), 17 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部