pandas无法直接导出带图表的excel,需先用to_excel写入数据,再用openpyxl加载文件并手动插入图表;xlsxwriter虽支持图表但与pandas.excelwriter不兼容。

用 pandas 写入数据,但图表得靠 openpyxl 手动插入
Python 本身没有“一键导出带图表的 Excel”函数。pandas.DataFrame.to_excel() 只能写入表格数据,不支持嵌入图表。真正实现图表导出,必须先用 pandas 或 matplotlib 生成数据,再用 openpyxl 加载已写入数据的工作簿,手动创建图表对象并绑定到对应单元格区域。
常见错误是试图在 to_excel() 中传入 chart=True 这类不存在的参数,或误以为 xlsxwriter 能直接画图——它确实支持图表,但和 pandas 的 ExcelWriter 配合时限制极多(比如不支持追加写入、不能读取已有文件)。
- 推荐组合:用
pandas写入原始数据 → 用openpyxl加载该文件 → 插入BarChart/LineChart等对象 -
openpyxl图表依赖坐标系(如'A1:B10'),必须确保数据已写入且区域准确;空行/空列会导致Reference构造失败 - 若数据含中文列名,图表横坐标可能显示为
#REF!,需显式设置series.xvalues = Reference(...)并指定data_type='str'
用 openpyxl 插入柱状图的最小可行步骤
假设你已有 df(含两列:'month' 和 'sales'),目标是把柱状图插在 'D2' 位置:
from openpyxl import load_workbook
from openpyxl.chart import BarChart, Reference
from openpyxl.utils import get_column_letter
<p>wb = load_workbook('output.xlsx')
ws = wb.active</p><h1>定义数据区域:假设 month 在 A 列,sales 在 B 列,共 13 行(含标题)</h1><p>data = Reference(ws, min_col=2, min_row=1, max_col=2, max_row=len(df)+1)
categories = Reference(ws, min_col=1, min_row=2, max_col=1, max_row=len(df)+1)</p><p>chart = BarChart()
chart.add_data(data, titles_from_data=True)
chart.set_categories(categories)
chart.width = 12
chart.height = 6
ws.add_chart(chart, 'D2')</p><p>wb.save('output_with_chart.xlsx')</p>
注意点:
-
min_row=1包含标题行,但categories从第 2 行开始(跳过标题),否则横坐标会把“month”当一个数据点 -
get_column_letter()不需要在这里用,但如果你动态算列号(比如第 27 列),就得靠它转成'AA' - 图表尺寸单位是“字符宽/行高”,不是像素;
width=12≈ 8.5 cm,太小会挤压图例
为什么不用 xlsxwriter?它报 NotImplementedError: Charts are not supported with the default writer
这个错误出现在你用 pandas.ExcelWriter(engine='xlsxwriter') 后,又试图调用 openpyxl 的图表 API——两个库不兼容。而 xlsxwriter 自身虽支持图表,但 pandas 的 ExcelWriter 接口不暴露其图表对象,你无法在写入后“追加”图表。
可行但麻烦的替代路径:
- 完全弃用
pandas.to_excel,改用xlsxwriter.Workbook手动写入所有数据 + 手动 add_chart(适合简单固定结构) - 用
pandas写入临时文件 → 用xlsxwriter读取时报错,所以只能重写全量数据,无法复用已有格式(如合并单元格、条件格式) - 性能上,
xlsxwriter写大数据快,但加图表逻辑比openpyxl更冗长(要反复调用add_series())
导出带样式的图表:字体、颜色、坐标轴标题怎么设
openpyxl 的图表样式控制粒度较细,但 API 不直观。比如改横坐标标题文字,不能直接 chart.x_axis.title = '月份',而要先启用标题对象:
chart.x_axis.title = '月份' chart.x_axis.title.tx.rich.p[0].r.t = '月份' # 强制刷新文本内容 chart.y_axis.title = '销售额(万元)' <h1>改柱子颜色(对第一个序列)</h1><p>s = chart.series[0] s.graphicalProperties.solidFill = '4472C4' # 十六进制色值 s.dLbls = DataLabelList() # 显示数值标签 s.dLbls.showVal = True</p>
容易被忽略的坑:
- 坐标轴标题赋值后必须触发底层文本对象更新,否则 Excel 打开时显示空白
- 颜色值必须是 6 位十六进制字符串(如
'FF6B6B'),传入rgb=(255,107,107)会报错 - 数据标签默认不显示,且
showVal=True必须挂在具体series上,而非chart级别
实际跑通的关键在于:先让数据稳稳落进 Excel,再用 openpyxl 当“后期制作工具”补图表——它不擅长写数据,但专精于读、改、增图表和样式。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











