Python openpyxl 插入Excel柱状图步骤详解
用openpyxl.chart.BarChart在Excel里插入柱状图:指定数据源、类别轴、标题、图例位置,支持簇状/堆积柱形,图表随数据更新自动变化,不用手动插图表。
场景痛点
每次做完数据表,都要选中数据、点"插入-柱状图"、调标题、挪图例、改颜色。表一改图就得重新选一遍。更烦的是周报里要同时出三张图,复制粘贴图表格式半天。用Python把数据和图一起生成,图表数据源直接绑在表格上,业务方改数字,图自动跟着变,连图都不用手插。
用到的库
pip install openpyxl
完整代码
# -*- coding: utf-8 -*-
"""
openpyxl 在 Excel 里插入柱状图(簇状 + 堆积)
"""
from openpyxl import Workbook
from openpyxl.chart import BarChart, Reference
from openpyxl.chart.label import DataLabelList
def build_chart_demo(path: str):
wb = Workbook()
ws = wb.active
ws.title = "季度销售"
# 数据:行=季度,列=产品线
ws.append(["季度", "产品线A", "产品线B", "产品线C"])
ws.append(["Q1", 120, 80, 60])
ws.append(["Q2", 150, 95, 70])
ws.append(["Q3", 180, 110, 90])
ws.append(["Q4", 210, 130, 110])
# ===== 图1:簇状柱状图(默认) =====
chart1 = BarChart()
chart1.type = "col" # col=竖直柱状,bar=水平条形
chart1.grouping = "clustered" # 簇状
chart1.title = "各季度产品线销售额对比(簇状)"
chart1.y_axis.title = "销售额(万元)"
chart1.x_axis.title = "季度"
# 数据区域:B1:D5,包含表头(第一行当系列名)
data = Reference(ws, min_col=2, max_col=4, min_row=1, max_row=5)
# 类别(X 轴标签):A2:A5
cats = Reference(ws, min_col=1, min_row=2, max_row=5)
chart1.add_data(data, titles_from_data=True)
chart1.set_categories(cats)
# 显示数据标签
chart1.dataLabels = DataLabelList()
chart1.dataLabels.showVal = True
chart1.width = 18 # 图表宽度(厘米)
chart1.height = 10 # 高度
ws.add_chart(chart1, "A8")
# ===== 图2:堆积柱状图 =====
chart2 = BarChart()
chart2.type = "col"
chart2.grouping = "stacked" # 堆积
chart2.overlap = 100
chart2.title = "各季度销售额堆积图"
chart2.y_axis.title = "合计(万元)"
chart2.add_data(data, titles_from_data=True)
chart2.set_categories(cats)
chart2.width = 18
chart2.height = 10
ws.add_chart(chart2, "A28")
wb.save(path)
print("图表已生成:", path)
def main():
build_chart_demo("chart_demo.xlsx")
if __name__ == "__main__":
main()
代码讲解
from openpyxl.chart import BarChart, Reference:BarChart 负责柱形图,Reference 用来描述"数据区域在哪"。chart1.type = "col"是竖直柱子(最常见的柱状图);改成"bar"就是横向条形图。chart1.grouping:"clustered"是簇状(并排),"stacked"是堆积(一根柱子堆起来),"percentStacked"是百分比堆积。add_data(Reference(ws, min_col=2, max_col=4, min_row=1, max_row=5), titles_from_data=True):把 B1:D5 作为数据区。titles_from_data=True表示第一行(B1:D1 的"产品线A/B/C")当作系列名字,不再当成数据点。set_categories(Reference(ws, min_col=1, min_row=2, max_row=5)):把 A2:A5 当 X 轴标签(Q1~Q4)。DataLabelList(showVal=True)在每根柱子顶上显示数值,做月报时非常直观。chart1.width/height单位是厘米,不是像素;默认宽 15 高 7.5,按需放大。ws.add_chart(chart1, "A8")把图表锚定到 A8 单元格,再放第二张图时挪到 A28 避免重叠。- 图表是"活"的:改 B2:D5 里的数字,打开 Excel 图自动更新,不需要重新跑脚本。
运行结果
生成 chart_demo.xlsx。打开后上半部分是数据表格,A8 位置第一张簇状柱状图:四个季度并排三根柱子,每根柱子顶标数值;A28 位置第二张堆积图:每季度一根总柱,按产品线堆叠。图例自动在右侧。
注意事项
titles_from_data=True一定要和 Reference 的 min_row 对应好。如果数据区第一行不是表头,这个参数要 False,否则会把表头数字当成一个系列。- 类别轴 Reference 不要把表头 A1 包进去,否则 X 轴会多出一列奇怪标签。
- openpyxl 只支持生成"原生 Excel 图表",不支持 matplotlib 那种自由绘图。要做复杂配色、3D 效果,得用 matplotlib 出图后用 openpyxl 把图片插进 Excel(
ws.add_image(...))。 - 中文标题、中文坐标轴在 Excel 里正常显示;但某些老版本 WPS 对 openpyxl 生成的图表兼容一般,发出去前用 Excel 本体打开看一眼。
- 图表锚点是单元格坐标,不是像素。表格内容一多,图表会盖住下面的数据;像本例一样把图放到数据下方空行。
- 想做折线图、饼图,把
BarChart换成LineChart、PieChart,用法几乎一样,都在openpyxl.chart里。

更新时间:2026-09-15 09:02:29