Python办公06:图表量产——根据表格数据自动生成 50 张趋势图并插入 Excel

目录

专栏导读

🌸 欢迎来到Python办公自动化专栏---Python处理办公问题,解放您的双手
🏳️‍🌈 个人博客主页:请点击------> 个人的博客主页 求收藏
🏳️‍🌈 Github主页:请点击------> Github主页 求Star⭐
🏳️‍🌈 知乎主页:请点击------> 知乎主页 求关注
🏳️‍🌈 CSDN博客主页:请点击------> CSDN的博客主页 求关注
👍 该系列文章专栏:请点击------>Python办公自动化专栏 求订阅
🕷 此外还有爬虫专栏:请点击------>Python爬虫基础专栏 求订阅
📕 此外还有python基础专栏:请点击------>Python基础学习专栏 求订阅
文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏
❤️ 欢迎各位佬关注! ❤️

06:图表量产------根据表格数据自动生成 50 张趋势图并插入 Excel

第一阶段:Excel / 数据表高效处理(1-8)

场景引入

月度经营分析会上,领导要求每个部门出一份带趋势图的报告。你有 12 个部门 × 4 个指标 = 48 张图需要制作。在 Excel 中手动插入图表、选择数据源、调整格式,每张图至少 2 分钟,全部做完要一个半小时。

本节教你用 Python 的 openpyxl 图表模块,一行代码生成一张图,48 张图只需几秒。


技术原理

openpyxl 提供了完整的图表 API,支持以下图表类型:

图表类型 类名 适用场景
柱状图 BarChart() 分类对比
折线图 LineChart() 趋势变化
饼图 PieChart() 占比分布
面积图 AreaChart() 累计趋势
散点图 ScatterChart() 相关性分析

工作流程:

复制代码
数据表 → 创建图表对象 → 设置数据引用 → 指定放置位置 → 保存

环境准备

bash 复制代码
pip install openpyxl

完整代码

python 复制代码
import os
import pandas as pd
from openpyxl import load_workbook
from openpyxl.chart import BarChart, LineChart, PieChart
from openpyxl.chart.series import DataPoint
from openpyxl.chart.label import DataLabelList
from openpyxl.chart.reference import Reference
from openpyxl.chart.series import Series

def create_chart_in_excel(input_file, output_file=None, chart_type='bar',
                         x_column='A', y_columns=None, start_row=1, end_row=None,
                         title="图表", position="F2"):
    """
    在 Excel 中自动插入图表

    参数:
        input_file: 数据所在的 Excel 文件
        output_file: 输出文件名(默认原文件名+_图表)
        chart_type: 图表类型 'bar'(柱状图), 'line'(折线图), 'pie'(饼图)
        x_column: X 轴的列字母(如 'A')
        y_columns: Y 轴的列字母列表(如 ['B', 'C'])
        start_row: 数据起始行(含标题行)
        end_row: 数据结束行(自动检测)
        title: 图表标题
        position: 图表放置位置(单元格地址)
    """
    if output_file is None:
        base_name = os.path.splitext(input_file)[0]
        output_file = f"{base_name}_图表.xlsx"

    wb = load_workbook(input_file)
    ws = wb.active

    # 自动检测最后一行
    if end_row is None:
        end_row = ws.max_row

    # 创建数据引用
    # X 轴数据(类别轴)
    x_data = Reference(ws, min_col=ord(x_column) - ord('A') + 1,
                       min_row=start_row + 1, max_row=end_row)

    # 创建图表
    if chart_type == 'bar':
        chart = BarChart()
    elif chart_type == 'line':
        chart = LineChart()
    elif chart_type == 'pie':
        chart = PieChart()
    else:
        raise ValueError(f"不支持的图表类型: {chart_type}")

    chart.title = title
    chart.style = 10

    # 设置 X 轴类别
    chart.set_categories(x_data)

    # 添加 Y 轴数据系列
    if y_columns is None:
        y_columns = ['B']

    for y_col in y_columns:
        y_data = Reference(ws, min_col=ord(y_col) - ord('A') + 1,
                          min_row=start_row, max_row=end_row)
        chart.add_data(y_data, titles_from_data=True)

    # 设置图表大小(柱状图和折线图)
    if chart_type in ('bar', 'line'):
        chart.width = 20   # 厘米
        chart.height = 12  # 厘米

    # 显示数据标签
    chart.dataLabels = DataLabelList()

    # 将图表插入指定位置
    from openpyxl.chart.marker import Marker
    ws.add_chart(chart, position)

    wb.save(output_file)
    print(f"图表已插入: {output_file} (位置: {position})")


# ==================== 批量生成图表 ====================
def batch_generate_charts(data_dict, output_file="批量图表.xlsx"):
    """
    根据多组数据批量生成图表

    参数:
        data_dict: 字典,键为图表标题,值为 DataFrame
        output_file: 输出文件名
    """
    from openpyxl import Workbook

    wb = Workbook()
    ws = wb.active
    ws.title = "汇总数据"

    current_row = 1

    for chart_title, df in data_dict.items():
        # 写入数据
        row_offset = current_row + 1

        # 写入表头
        for col_idx, col_name in enumerate(df.columns, 1):
            ws.cell(row=current_row, column=col_idx, value=col_name)

        # 写入数据
        for row_idx, row_data in enumerate(df.values, current_row + 1):
            for col_idx, value in enumerate(row_data, 1):
                ws.cell(row=row_idx, column=col_idx, value=value)

        # 创建图表
        chart = BarChart()
        chart.title = chart_title
        chart.style = 10
        chart.width = 20
        chart.height = 12

        # X 轴
        last_col = len(df.columns)
        last_row = current_row + len(df)
        x_data = Reference(ws, min_col=1, min_row=current_row + 1, max_row=last_row)
        chart.set_categories(x_data)

        # Y 轴(假设数值列从第 2 列开始)
        for y_col in range(2, last_col + 1):
            y_data = Reference(ws, min_col=y_col, min_row=current_row, max_row=last_row)
            chart.add_data(y_data, titles_from_data=True)

        # 放置位置在数据右侧
        from openpyxl.utils import get_column_letter
        chart_position = f"{get_column_letter(last_col + 3)}{current_row}"
        ws.add_chart(chart, chart_position)

        # 下一组数据的起始行
        current_row = last_row + 3  # 留 2 行间距

    wb.save(output_file)
    print(f"批量生成完成: {output_file} (共 {len(data_dict)} 张图表)")


# ==================== 使用示例 ====================
if __name__ == "__main__":
    # ========== 示例 1:为已有 Excel 文件添加图表 ==========
    # create_chart_in_excel(
    #     input_file="月度销售数据.xlsx",
    #     x_column='A',        # 月份列
    #     y_columns=['B', 'C'], # 销售额和利润列
    #     chart_type='line',
    #     title="月度销售趋势",
    #     position="F2"
    # )

    # ========== 示例 2:批量生成多张图表 ==========
    # 模拟数据
    months = [f'{i}月' for i in range(1, 13)]
    data = {
        "华东区销售趋势": pd.DataFrame({
            '月份': months,
            '销售额': [120, 135, 148, 160, 155, 170, 180, 195, 188, 175, 165, 190],
            '利润': [30, 35, 40, 45, 42, 48, 52, 55, 50, 46, 43, 53]
        }),
        "华北区销售趋势": pd.DataFrame({
            '月份': months,
            '销售额': [90, 95, 110, 120, 115, 130, 140, 145, 138, 125, 120, 150],
            '利润': [20, 22, 28, 32, 30, 35, 38, 40, 36, 33, 31, 42]
        }),
    }
    batch_generate_charts(data, output_file="各区销售图表汇总.xlsx")

代码逐行解析

1. 创建数据引用

python 复制代码
x_data = Reference(ws, min_col=1, min_row=2, max_row=13)

Reference 告诉 openpyxl 图表的数据范围:

  • min_col:起始列(1 = A 列)
  • min_row:起始行(跳过标题行)
  • max_row:结束行

2. 添加数据系列

python 复制代码
y_data = Reference(ws, min_col=2, min_row=1, max_row=13)
chart.add_data(y_data, titles_from_data=True)
  • titles_from_data=True:第一行作为图例标题
  • 可以多次调用 add_data() 添加多组数据

3. 放置图表

python 复制代码
ws.add_chart(chart, "F2")

将图表的左上角放在 F2 单元格。


进阶技巧

技巧 1:饼图显示百分比标签

python 复制代码
chart = PieChart()
chart.title = "各部门占比"

# 添加数据后显示百分比
from openpyxl.chart.series import DataPoint
from openpyxl.chart.label import DataLabelList

chart.dataLabels = DataLabelList()
chart.dataLabels.showPercent = True
chart.dataLabels.showCatName = True

技巧 2:折线图添加数据标记

python 复制代码
from openpyxl.chart.marker import Marker

chart = LineChart()
series = chart.series[0]
series.marker = Marker(symbol='circle')
series.graphicalProperties.line.width = 25000  # 线条粗细(EMU 单位)

技巧 3:用 matplotlib 生成图片再嵌入

如果需要更复杂的图表样式:

python 复制代码
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
df.plot(x='月份', y=['销售额', '利润'], ax=ax, kind='bar')
fig.savefig('chart.png')

# 然后插入到 Excel
from openpyxl.drawing.image import Image
ws.add_image(Image('chart.png'), 'F2')

常见问题

Q1:图表生成后是空白的?

原因:数据引用的范围不正确。

排查

python 复制代码
print(f"数据范围: A{start_row}:{get_column_letter(last_col)}{end_row}")
# 手动检查这个范围是否有数据

Q2:中文字符显示为方框?

openpyxl 的图表字体默认使用 Calibri,在某些系统上可能不支持中文。

解决:手动在 Excel 中修改图表字体为微软雅黑,或在代码中设置:

python 复制代码
from openpyxl.chart.text import RichText
from openpyxl.drawing.text import Font

font = Font(typeface='微软雅黑')

Q3:如何生成组合图(柱状图+折线图)?

python 复制代码
from openpyxl.chart import BarChart, LineChart

bar = BarChart()
line = LineChart()

# 分别设置数据
bar.add_data(bar_data)
line.add_data(line_data)

# 合并
bar += line
ws.add_chart(bar, "F2")

总结

图表类型 关键设置
柱状图 BarChart() set_categories()
折线图 LineChart() set_categories()
饼图 PieChart() dataLabels.showPercent
数据系列 add_data() titles_from_data=True
放置位置 ws.add_chart() 单元格地址

本节掌握了在 Excel 中自动生成图表的能力,从手动一张张做图变成了代码批量产出。

下一节预告:07:数据透视自动化------用脚本一键生成多维度 Pivot Table 报告!

结尾

希望对初学者有帮助;致力于办公自动化的小小程序员一枚
希望能得到大家的【❤️一个免费关注❤️】感谢!
求个 🤞 关注 🤞 +❤️ 喜欢 ❤️ +👍 收藏 👍
此外还有办公自动化专栏,欢迎大家订阅:Python办公自动化专栏
此外还有爬虫专栏,欢迎大家订阅:Python爬虫基础专栏
此外还有Python基础专栏,欢迎大家订阅:Python基础学习专栏