🐍 Python 自动化办公
用 Python 批量修改 160 份结算表
作为工程/造价人,你是否也经历过这种“至暗时刻”:
手里攥着上百份结算资料,领导突然下令:把所有表格里的 “进度申请单” 统一改成 “结算申请单”。
手动打开 → 查找 → 替换 → 保存……160 个文件机械重复,不仅眼睛看花,更是把宝贵的摸鱼时间耗得一干二净。😩
👉 既然是重复劳动,那就交给 Python 吧!
for file in file_list: wb = openpyxl.load_workbook(file) ws = wb['造价汇总表'] ws['C5'].value = ws['C5'].value.replace('进度', '结算') wb.save(file)
脚本跑起来了,文件也在一个个被修改。正准备欢呼时,控制台突然喷出一大片刺眼的红色警告:
UserWarning: Cannot parse header or footer so it will be ignored
心态瞬间凉了半截:难道改坏了?数据丢了?
🛑 别慌!这是典型的“假报错”
在 Python 的世界里,红色不一定代表致命错误。
这次的 UserWarning,仅仅是因为 openpyxl 库暂时不支持解析 Excel 的页眉和页脚(如页码、公司 Logo 等复杂格式)。
💬 程序其实在说:“嘿,我发现了页眉/页脚,但我处理不了,就先跳过它们啦,不影响你改单元格哦!”
再看看控制台下方的绿色日志:
[55/160] ✅ 已修改:xxx → 结算申请单编号/计算式
这铁证如山:160 个文件已成功处理,核心数据完好无损!
如果你有代码洁癖,不想看到这些无害的警告,只需在代码开头加上这两行“消音器”:
import warnings# 过滤掉 openpyxl 的 UserWarningwarnings.filterwarnings('ignore', category=UserWarning, module='openpyxl')
再次运行,世界瞬间清静了 🎧
📝 今日复盘
- 🚀 效率革命:160 个文件秒级完成,告别机械加班
- 🔍 读懂日志:区分 Warning 与 Error,拒绝盲目焦虑
- ⚠️ 常见盲区:页眉页脚是 openpyxl 的已知限制,跳过即可
技术是为了服务于人的。读懂报错,你就离效率自由更近一步。
💬 互动话题
你在用 Python 处理 Excel 时遇到过哪些奇葩报错?评论区聊聊 👇
🔔 关注我,一起用代码解放双手
import osimport openpyxl# ========== 配置 ==========FILE_LIST_PATH = r"D:\asus\Desktop\应用程序\PY功能\结算表格勘误\新建 XLSX 工作表.xlsx"TARGET_SHEET = "造价汇总表"TARGET_CELL = "C5"OLD_TEXT = "进度"NEW_TEXT = "结算"# ==========================def get_file_paths(list_path): """从文件列表中提取所有 .xlsx 路径""" wb = openpyxl.load_workbook(list_path, data_only=True) ws = wb.active paths = [] for row in ws.iter_rows(values_only=True): for cell in row: if cell and str(cell).strip().endswith('.xlsx'): paths.append(str(cell).strip()) return pathsdef main(): file_paths = get_file_paths(FILE_LIST_PATH) total = len(file_paths) print(f"共找到 {total} 个 Excel 文件\n") success, skipped, failed = 0, 0, 0 for i, path in enumerate(file_paths, 1): if not os.path.exists(path): print(f"[{i}/{total}] 文件不存在: {os.path.basename(path)}") failed += 1 continue try: wb = openpyxl.load_workbook(path) if TARGET_SHEET not in wb.sheetnames: print(f"[{i}/{total}] 无工作表'{TARGET_SHEET}': {os.path.basename(path)}") skipped += 1 wb.close() continue ws = wb[TARGET_SHEET] current = ws[TARGET_CELL].value if current is None: print(f"[{i}/{total}] C5 为空: {os.path.basename(path)}") skipped += 1 elif OLD_TEXT in str(current): old_val = str(current) ws[TARGET_CELL].value = old_val.replace(OLD_TEXT, NEW_TEXT) wb.save(path) print(f"[{i}/{total}] 已修改: {os.path.basename(path)} | {old_val} -> {ws[TARGET_CELL].value}") success += 1 else: print(f"[{i}/{total}] C5 不含'{OLD_TEXT}': {os.path.basename(path)} | 当前值: {current}") skipped += 1 except Exception as e: print(f"[{i}/{total}] 错误: {os.path.basename(path)} | {e}") failed += 1 finally: if 'wb' in locals(): wb.close() print(f"\n{'='*50}") print(f"处理完成: 成功 {success} | 跳过 {skipped} | 失败 {failed} | 总计 {total}")if __name__ == "__main__": main() input("\n按回车键退出...")