pandas.concat()合并多Sheet需先统一列名和顺序,否则数据错位;读取时禁用自动类型推断、显式指定sheet名防内存溢出;保留格式须用openpyxl逐单元格操作。

用 pandas.concat() 合并多张Sheet,但必须统一列名和顺序
直接读取多个Sheet再拼接,pandas.concat() 会按列名对齐,如果某张表缺列、列名拼错、或顺序不一致,结果会出现大量 NaN 或错位。不是“合并失败”,而是“合并了但数据串行”。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 先用
pd.ExcelFile(file_path).sheet_names获取所有Sheet名,避免硬编码漏表 - 逐个读取时强制指定
usecols和dtype=object(防数字被自动转成float/int导致后续类型不一致) - 读完立刻用
df.columns = standardized_cols统一列名,别依赖原始表头——哪怕看起来一样,空格、全角半角、隐藏字符都可能不同 - 最后 concat 前检查:所有 df 的
columns.tolist()必须完全相等
保留原始格式?openpyxl 是唯一可行路径,但不能和 pandas 混用写入
pandas.to_excel() 只能输出纯数据,字体、边框、合并单元格、列宽全部丢失。想保留格式,必须用 openpyxl 手动操作 —— 但它不支持直接追加 DataFrame 到现有工作簿的某张表末尾,更不支持跨文件复制样式。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 用
openpyxl.load_workbook()逐个打开源文件,遍历每个worksheet,用.iter_rows()读值 +.cell(row, col).font等属性读样式 - 新建一个目标
Workbook,用.create_sheet()添加新表,再用.cell().value = ...和.cell().font = ...逐单元格写入(注意行列索引从1开始) - 列宽要单独设:
ws.column_dimensions['A'].width = src_ws.column_dimensions['A'].width,且必须在写入后、保存前设置 - 别试图用
pandas.ExcelWriter(engine='openpyxl', mode='a')追加带样式的表——它只支持追加纯数据,样式会被清空
read_excel(sheet_name=None) 一次读全所有Sheet,但内存和类型推断会出问题
传 sheet_name=None 确实返回 dict{sheet_name: DataFrame},看似省事。但 pandas 默认对每张表独立做 dtype 推断,同一列在不同Sheet里可能被识别为 int64、float64、object,后续 concat 时自动升为 object,数值计算失效,排序错乱。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 禁用自动类型推断:
read_excel(..., dtype=str)或dtype={col: str for col in all_cols} - 若需数值运算,合并后再统一用
pd.to_numeric(df[col], errors='coerce')转换,比放任 pandas 自动推断更可控 - 大文件慎用
sheet_name=None:它会把所有Sheet全加载进内存,哪怕你只用其中2张 - 用
pd.read_excel(file, sheet_name=['Sheet1', 'Sheet2'])显式指定需要的表名,更安全
合并后导出Excel时,index=False 不够,还要关掉 header=True 的默认行为
很多人发现导出的Excel第一行多出一排“Unnamed: 0”或数字索引,其实是 pandas.DataFrame 的 index 被当成了列。设 index=False 能解决,但还有个隐形坑:to_excel() 默认写入列名(header=True),如果原始数据本身不含表头(比如纯数值块),这一行就纯属多余。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 确认数据是否含列名:若原始Sheet无表头,读取时加
header=None,导出时加header=False - 若数据有表头但想自定义,读取后改
df.columns = ['ID', 'Name', 'Amount'],导出时保持header=True - 用
ExcelWriter时,记得writer.close()再退出,否则文件可能损坏、打不开


















