Pandas导出Excel时长数字被截断是因未在读取和写入阶段强制设为字符串类型所致;需读取时用dtype=str、导出时结合openpyxl设置单元格格式为文本或改用xlsxwriter引擎并配置列格式。

导出Excel时长数字被截断成科学计数法或末尾变0
这是Pandas默认用openpyxl引擎写入时,对超过15位的数字(比如身份证号、订单号、长ID)自动转为浮点数导致的精度丢失。Excel本身只支持15位有效数字,但问题根源不在Excel——而在Pandas写入前没把这类字段当文本处理。
- 确认字段是否已转为
str类型:df["id"].dtype返回object不代表安全,得检查值是否仍是数字(如type(df.loc[0, "id"]) is int) - 导出前强制转字符串并补零(如有):
df["id"] = df["id"].astype(str).str.zfill(18) - 用
openpyxl引擎时,必须配合pd.ExcelWriter的engine_kwargs设置单元格格式,否则仅靠astype(str)不够——Excel仍可能双击后自动转回数字
用openpyxl手动设置单元格数字格式为文本
光靠to_excel()参数无法控制单列格式,必须用openpyxl底层API写入后修改样式。关键在获取工作表对象、遍历目标列、逐单元格设number_format和data_type。
- 导入:
from openpyxl.styles import Font,不用额外装包(openpyxl已含) - 写入后用
writer.sheets["Sheet1"]拿到worksheet对象 - 对A列(假设是长ID)循环设格式:
ws = writer.sheets["Sheet1"] for row in ws["A2:A{}".format(len(df)+1)]: for cell in row: cell.number_format = '@' cell.data_type = 's' - 注意起始行是2(跳过表头),且
data_type = 's'才能确保Excel不解析内容
用xlsxwriter引擎更简单地避免精度丢失
xlsxwriter比openpyxl更适合导出纯数据报表,它原生支持列格式定义,且写入即锁定文本类型,无需后期遍历单元格。
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
- 安装:
pip install xlsxwriter - 指定引擎并定义列格式:
writer = pd.ExcelWriter("out.xlsx", engine="xlsxwriter") workbook = writer.book id_format = workbook.add_format({"num_format": "@"}) worksheet = workbook.add_worksheet("Sheet1") writer.sheets["Sheet1"] = worksheet df.to_excel(writer, sheet_name="Sheet1", index=False) worksheet.set_column("A:A", 20, id_format) # 假设ID在A列 - 必须调用
set_column()并传入格式对象,仅to_excel()里用dtype=str无效 - 不支持追加写入(
mode="a"),只能新建文件
读取时就预防:用dtype控制长数字列不被自动转int/float
如果原始Excel里长数字已经显示为1.23E+17,再导出也救不回来。所以源头读取就得防住——否则后续所有导出都是错的。
立即学习“Python免费学习笔记(深入)”;
- 读取时显式指定列类型:
pd.read_excel("in.xlsx", dtype={"order_id": str}) - 若列名未知或批量处理,用
converters:converters={"col1": str, "col2": str} - 避免用
dtype=object,它会让数字列变成numpy.int64,依然会丢精度;必须用str - 读取后立刻检查:
df["order_id"].str.len().min()看是否全为预期长度(如18),不是则说明读取阶段已失真
实际中最容易被忽略的是读取阶段——很多人导出出问题才回头改写逻辑,但此时数据在内存里早已是浮点近似值,转str只是把错误数字“固化”成字符串,本质没救。务必从read_excel第一行就开始守门。

















