资讯动态

Python读取Excel并写入:pandas与openpyxl实战避坑指南

发布时间:2026/10/14 23:12:16 来源:尧图企业网站定制
简介这是一份面向Python初学者与数据处理入门者的Excel读写实战脚本合集针对日常数据分析、报表自动化等场景中频繁出现的表格读取与写入需求提供可直接运行的代码参考。压缩包共4个文件全部为py脚本整体约6KB涵盖读取Excel、读取数值型数据、读取并处理表格以及读写结合等典型用法便于按需查阅与二次修改。资源围绕pandas与openpyxl两大常用库展开既演示read_excel、to_excel等基础接口也涉及条件筛选、单元格遍历、工作簿创建与保存等操作帮助读者理解DataFrame与工作表对象之间的差异。目前已有702人学习下载适合希望快速上手Excel自动化处理、积累脚本模板的开发者参考借鉴。1. 从一份“python读取Excel并写入.zip”说起它到底能帮你省下多少手工活如果你日常要处理报表、台账、对账单大概率遇到过这种场景业务方丢来一个几十兆的 Excel里面七八个 sheet字段命名五花八门你要把其中几张表按条件筛出来再拼到另一份模板里发回去。手工复制粘贴不仅慢还容易在筛选条件上翻车。这份“python读取Excel并写入.zip”就是冲着这类重复劳动来的——它把读取、清洗、写入这条链路打包成可直接复用的脚本集合核心依赖是 pandas 加 openpyxl覆盖 xlsx 与 xls 两种常见格式。适合谁会一点 Python 基础、但没系统写过 Excel 批处理的人也适合已经用 pandas 但总在日期格式、合并单元格、多 sheet 写入上踩坑的熟手。它解决的不是“能不能读”的问题而是“读进来之后怎么稳定写出去”的问题。2. 读取环节pandas.read_excel 的参数怎么配才不翻车2.1 先搞清楚你的 Excel 到底长什么样很多人拿到文件直接pd.read_excel(data.xlsx)结果第一行是标题、第二行是空行、第三行才是表头读出来列名全是Unnamed: 0。这不是 pandas 的锅是你没告诉它表头在第几行。常见做法是先手动打开文件看一眼结构再用header参数指定。如果文件里有多个 sheetsheet_name不写默认只读第一个写None会返回一个字典key 是 sheet 名value 是对应 DataFrame。这个字典结构在后续按 sheet 分别处理时特别顺手。import pandas as pd # sheet_nameNone 返回字典适合多 sheet 批量处理 sheets pd.read_excel( source.xlsx, sheet_nameNone, # 读所有 sheet header2, # 表头在第 3 行索引从 0 开始 dtype{订单号: str} # 强制订单号为字符串防止前导零丢失 ) for name, df in sheets.items(): print(name, df.shape)逻辑说明sheet_nameNone是批量读取的关键省去逐个指定名字的麻烦。header2对应人类视角的第 3 行索引从 0 起算。dtype参数容易被忽略但订单号、身份证号、银行卡号这类字段一旦被识别成数字前导零会消失后续写入再读就对不上。参数怎么改如果表头就在第一行header用默认的 0如果文件没有表头设headerNone再自己传names列表。2.2 日期列和合并单元格是两个高频雷区Excel 里的日期在底层是序列号pandas 读进来可能是datetime也可能是int取决于单元格格式和 openpyxl 的解析结果。稳妥做法是读完后统一用pd.to_datetime转一次并指定errorscoerce把转不了的变成 NaT方便后续排查。合并单元格更麻烦pandas 只会把值放在合并区域的左上角其余位置是 NaN。如果你需要向下填充用ffill()但要注意它会把整列都填满包括本来就不该有值的行。我一般会先确认合并范围再决定是填充还是直接丢弃。# 日期统一转换转不了的置为 NaT df[下单日期] pd.to_datetime(df[下单日期], errorscoerce) # 合并单元格向下填充仅对指定列操作 df[所属区域] df[所属区域].ffill() # 检查填充后是否还有空值 print(df[所属区域].isna().sum())逻辑说明errorscoerce是后悔药避免因为一个脏日期导致整个脚本报错中断。ffill()只对所属区域这一列生效不会污染其他列。参数怎么改如果合并单元格是横向的用bfill(axis1)如果填充后仍有关键列为空说明源文件本身有缺失需要回到业务侧确认而不是在脚本里硬填。3. 写入环节to_excel 的坑比读取只多不少3.1 多 sheet 写入与追加模式to_excel默认会覆盖同名文件如果你想把多个 DataFrame 写进同一个文件的不同 sheet必须用ExcelWriter上下文管理器。这里有个血泪经验modea追加模式在 openpyxl 引擎下对已存在的文件支持并不完美尤其是文件本身有格式、有公式的时候追加写入可能破坏原有内容。常见做法是要么一次性把所有 sheet 写进新文件要么先读原文件所有 sheet合并新数据后再整体覆盖写回。with pd.ExcelWriter(output.xlsx, engineopenpyxl) as writer: df_summary.to_excel(writer, sheet_name汇总, indexFalse) df_detail.to_excel(writer, sheet_name明细, indexFalse) # 调整列宽openpyxl 原生操作 worksheet writer.sheets[汇总] worksheet.column_dimensions[A].width 20逻辑说明with语句保证文件句柄正确关闭避免写一半进程退出导致文件损坏。indexFalse是绝大多数场景下的正确选择除非你确实需要保留行号。列宽调整需要拿到writer.sheets里的 worksheet 对象这是 openpyxl 的能力pandas 本身不提供。参数怎么改如果输出文件要给非技术同事看建议加上freeze_panes冻结首行但注意这个参数在不同 pandas 版本里位置有变化写之前先确认版本。3.2 格式保留与大数据量分块如果你需要保留源文件的字体、颜色、边框pandas 的to_excel做不到它只写值。这时候要么用 openpyxl 直接操作单元格要么用 xlsxwriter 引擎配合add_format。另一个现实问题是数据量几万行以内to_excel没问题几十万行内存和写入时间都会明显上升。我一般会先按业务维度拆分或者直接输出 CSV 给下游Excel 只作为最终展示层。# 大数据量分块写入避免一次性占用过多内存 chunk_size 50000 with pd.ExcelWriter(big_output.xlsx, engineopenpyxl) as writer: for i, chunk in enumerate(pd.read_excel(big_source.xlsx, chunksizechunk_size)): chunk.to_excel(writer, sheet_namefpart_{i}, indexFalse)逻辑说明chunksize是read_excel的参数返回一个迭代器每次只加载指定行数。写入时按 chunk 分 sheet既控制内存也方便后续定位问题数据在哪一块。参数怎么改chunk_size根据机器内存调整一般 5 万到 10 万行比较稳如果 sheet 数量有上限要求可以改成追加到同一个 sheet但需要手动控制startrow。4. 避坑与排查那些让我加班到凌晨的 Excel 问题4.1 现象读进来列名多了 Unnamed原因表头行判断错误这是最高频的问题。源文件第一行可能是标题、第二行是空行、第三行才是真正的表头。pandas 默认把第一行当表头于是空行和标题行都变成了列名。解决方式是先手动确认表头位置用header参数指定如果表头行不固定可以先headerNone读进来再用iloc定位表头行重新赋值columns。4.2 现象写入后日期变成数字原因Excel 序列号未转换用 openpyxl 直接写datetime对象时如果单元格格式没设成日期Excel 会显示成序列号。pandas 的to_excel一般会处理好但如果你手动用 openpyxl 写需要设置number_format。排查方法是写完后用 Excel 打开看显示格式或者用 pandas 再读一次看读出来是datetime还是int。4.3 现象文件被占用无法写入原因Excel 进程未释放Windows 下如果 Excel 还开着目标文件Python 写入会抛PermissionError。这不是代码问题是文件锁。解决方式是写入前确认文件已关闭或者在脚本里加异常捕获提示用户关闭文件后重试。我一般会在写入前先尝试重命名原文件成功说明没被占用失败就给出明确提示。4.4 现象中文列名写入后乱码原因编码或引擎不匹配xlsx 本身是 zip 包不存在传统编码问题但如果你输出的是 CSVto_csv默认 utf-8Excel 打开可能乱码。解决方式是写 CSV 时加encodingutf-8-sig让 Excel 正确识别 BOM。xlsx 写入一般不会乱码如果出现检查是不是引擎选错了xlsx 用 openpyxlxls 用 xlwt。4.5 现象公式单元格读出来是公式字符串原因未启用 data_onlyopenpyxl 读取时默认返回公式本身而不是计算结果。如果你需要的是值加载工作簿时加data_onlyTrue。但注意这个参数依赖 Excel 上次保存时缓存了计算结果如果文件是程序生成的、从未用 Excel 打开过可能读出来是 None。稳妥做法是让上游确保公式已计算并保存。5. 进阶技巧用 openpyxl 做 pandas 做不到的格式控制pandas 负责数据openpyxl 负责格式两者配合才能产出能直接发出去的报表。一个具体技巧是先用 pandas 把数据写好再用 openpyxl 加载输出文件对特定列加条件格式、对表头加底色、对数字列设千分位。这样既保留了 pandas 的清洗效率又补上了格式短板。from openpyxl import load_workbook from openpyxl.styles import Font, PatternFill, numbers # pandas 写完后用 openpyxl 二次加工 wb load_workbook(output.xlsx) ws wb[汇总] # 表头加粗、灰底 header_fill PatternFill(solid, fgColorDDDDDD) for cell in ws[1]: cell.font Font(boldTrue) cell.fill header_fill # 金额列设千分位格式 for row in ws.iter_rows(min_row2, min_col3, max_col3): for cell in row: cell.number_format numbers.FORMAT_NUMBER_COMMA_SEPARATED1 wb.save(output_formatted.xlsx)逻辑说明load_workbook重新打开 pandas 写出的文件此时数据已经就位只需要处理样式。ws[1]取第一行所有单元格批量设置字体和填充。number_format用 openpyxl 内置的常量避免手写格式字符串出错。参数怎么改如果表头不在第一行调整ws[1]的行号如果金额列位置变化改min_col和max_col。注意wb.save会覆盖原文件建议输出到新文件名保留一份原始数据文件作为后悔药。验证方法很简单写完后用 pandas 再读一次输出文件确认行数、列名、关键字段类型和源数据一致再用 Excel 打开看格式是否符合预期。我一般会写一个assert检查行数比如assert len(df_out) len(df_in)不通过就直接报错避免把错数据发出去。从那以后我每次处理 Excel 批处理都强制先跑一遍读取验证再写入宁可多花两分钟也不想到半夜被叫起来重跑。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑