在办公自动化中,经常遇到多个部门提交的 Excel 报表格式不统一的问题,比如日期有的显示为 2026/1/1,有的显示为 2026-01-01;金额有的没有千分位,有的保留不同小数位;百分比有的显示为 0.1234,有的显示为 12.34%。如果人工逐个修改几十个工作簿,效率低且容易出错。本文介绍如何使用 Python 的 xlwings 库,批量扫描文件夹中的所有 Excel 文件,动态识别数据区域末端行号,然后对指定列设置 number_format 来统一显示格式,并附带验证脚本确保改版生效。
- import os
- import xlwings as xw
- # ====== 可修改参数 ======
- folder_path = r"e:\file\target" # 存放所有 Excel 文件的文件夹
- sheet_name = "Sheet1" # 要处理的工作表名称
- # ==========================
- app = xw.App(visible=False, add_book=False)
- try:
- for file in os.listdir(folder_path):
- # 跳过 Excel 临时文件
- if file.startswith("~$"):
- continue
- # 只处理 .xlsx, .xls, .xlsm 文件
- if not file.lower().endswith((".xlsx", ".xls", ".xlsm")):
- continue
- full_path = os.path.join(folder_path, file)
- wb = None
- try:
- wb = app.books.open(full_path)
- # 检查目标工作表是否存在
- sheet_names = [s.name for s in wb.sheets]
- if sheet_name not in sheet_names:
- print(f"跳过:{file},不存在工作表:{sheet_name}")
- continue
- sht = wb.sheets[sheet_name]
- # 动态获取连续数据区域的末行(以 A1 单元格为基准)
- last_row = sht.range("A1").current_region.last_cell.row
- if last_row < 2:
- print(f"跳过:{file},没有有效数据")
- continue
- # 定义各列区域(假定:A列日期,B列金额,C列百分比)
- rng_date = sht.range(f"A2:A{last_row}")
- rng_amount = sht.range(f"B2:B{last_row}")
- rng_rate = sht.range(f"C2:C{last_row}")
- # 设置显示格式
- rng_date.number_format = "yyyy-mm-dd"
- rng_amount.number_format = "#,##0.00"
- rng_rate.number_format = "0.00%"
- wb.save()
- print(f"已更改数据格式:{file},末行:{last_row}")
- finally:
- if wb is not None:
- wb.close()
- finally:
- app.quit()
复制代码
关键逻辑解析
- current_region.last_cell.row:从 A1 出发,找到当前连续单元格区域的最后一个单元格的行号,从而实现动态适应不同工作簿的数据行数。如果数据区域中间有整行空行,该区域可能提前结束,所以应确保待处理表格中无空白行隔断数据。
- number_format:只改变 Excel 的显示规则,不修改底层数值。如果单元格内容本质上是文本(如“2026/1/1”是字符串而非日期),单纯设置 number_format 可能不会立即生效,需要配合数据类型转换。
- 异常防护:跳过 ~$ 开头的临时文件;检查工作表是否存在;如果只有表头没有数据(last_row < 2)则跳过;使用 try/finally 确保每个工作簿正确关闭,避免进程残留。
操作建议
1. 正式执行前,先复制一份测试目录,放入 2~3 个样例文件验证效果。
2. 确认工作表名称和列顺序与脚本一致。如果表头不在第 1 行,或需要按表头文字动态定位,可结合 xlwings 的 .expand() 或 .api 属性增强。
3. 批量处理时,建议先在脚本内打印文件名和识别的末行:- print(f"当前文件:{file}")
- print(f"识别到的数据末行:{last_row}")
复制代码 这样便于快速定位结构异常的文件。
验证脚本
处理完成后,建议用只读脚本抽查格式:- import os
- import xlwings as xw
- folder_path = r"e:\file\target"
- sheet_name = "Sheet1"
- app = xw.App(visible=False, add_book=False)
- try:
- for file in os.listdir(folder_path):
- if file.startswith("~$") or not file.lower().endswith((".xlsx", ".xls", ".xlsm")):
- continue
- full_path = os.path.join(folder_path, file)
- wb = None
- try:
- wb = app.books.open(full_path)
- if sheet_name not in [s.name for s in wb.sheets]:
- print(f"跳过:{file}")
- continue
- sht = wb.sheets[sheet_name]
- print(f"文件:{file}")
- print("A2 日期格式:", sht.range("A2").number_format)
- print("B2 金额格式:", sht.range("B2").number_format)
- print("C2 百分比格式:", sht.range("C2").number_format)
- print("-" * 40)
- finally:
- if wb is not None:
- wb.close()
- finally:
- app.quit()
复制代码 该脚本不修改文件,只读取 number_format 属性,可以快速确认格式是否已写入。
常见陷阱与延伸
- 文本型数据:如果单元格左上角有绿色三角(Excel 的智能标记),说明该单元格以文本形式存储数字/日期。仅靠 number_format 无法将其转换为真实数值或日期,需要先用 xlwings 的 .value 覆盖或使用 Excel 的“分列”功能。
- 外观格式扩展:除了 number_format,还可以用 .api 设置字体、边框、对齐、底色等,例如:- header_rng = sht.range("A1:C1")
- header_rng.api.Font.Bold = True
- header_rng.api.HorizontalAlignment = -4108 # 居中
- header_rng.color = (217, 217, 217) # 浅灰色底色
复制代码 不过外观格式依赖本地 Excel 环境,批量处理前需在典型机器上测试。
总结
批量统一多个工作簿的显示格式,是用 Python 做 Excel 自动化的典型实践。核心在于动态获取数据范围(current_region.last_cell.row)并精准设置 number_format。本文提供的代码已包含临时文件跳过、工作表检查、末行验证、格式写入和结果验证,可直接用于实际场景。记住:格式规范是数据质量的一部分,将规则固化为脚本,才能实现真正可复用的报表标准化工具。 |