用 openpyxl 操作 Excel:从单元格、公式到样式与图表

2026-07-23 29 预计阅读时间: 1 分钟
来源: realpython.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:8 分钟

Excel 自动化的难点不只是把数据写进表格,还包括保留公式、设置可读的格式,以及生成便于业务人员查看的图表。openpyxl 提供了一套直接操作 .xlsx 工作簿的 Python API,适合报表生成、批量修改和数据检查,也很适合通过小练习检验自己是否真正理解了单元格、工作表与工作簿之间的关系。

先弄清三个核心对象

使用 openpyxl 时,大部分代码围绕三个对象展开:

  • Workbook 表示整个 Excel 文件。
  • Worksheet 表示一个工作表,例如“销售明细”。
  • Cell 表示具体单元格,例如 B2

新建工作簿时,openpyxl 会自动创建一个活动工作表:

from openpyxl import Workbook

workbook = Workbook()
worksheet = workbook.active
worksheet.title = "销售明细"

worksheet["A1"] = "产品"
worksheet["B1"] = "数量"
worksheet.append(["键盘", 12])
worksheet.append(["鼠标", 20])

workbook.save("sales.xlsx")

worksheet["A1"] 适合定位已知坐标,append() 则适合按行写入表格数据。自动生成报表时,通常会先写表头,再循环调用 append() 写入记录。

读取现有文件时,可以通过 load_workbook() 打开工作簿:

from openpyxl import load_workbook

workbook = load_workbook("sales.xlsx")
worksheet = workbook["销售明细"]

for row in worksheet.iter_rows(min_row=2, values_only=True):
    print(row)

values_only=True 会返回单元格的值,而不是 Cell 对象。如果需要检查样式、坐标或数据类型,就不要启用这个参数。

公式不是计算结果

写公式和写普通文本非常接近,只要字符串以 = 开头即可:

worksheet["C1"] = "单价"
worksheet["D1"] = "金额"
worksheet["C2"] = 199
worksheet["D2"] = "=B2*C2"

需要注意,openpyxl 负责保存公式,但不会像 Excel 那样计算公式。工作簿在 Excel 或其他兼容软件中打开并重新计算后,结果才会更新。

读取公式文件时,data_only 参数决定看到公式还是缓存结果:

from openpyxl import load_workbook

formula_book = load_workbook("sales.xlsx", data_only=False)
print(formula_book["销售明细"]["D2"].value)  # =B2*C2

value_book = load_workbook("sales.xlsx", data_only=True)
print(value_book["销售明细"]["D2"].value)  # 最近一次保存的缓存结果,可能为 None

如果工作流依赖实时计算结果,需要让 Excel、LibreOffice 或专门的计算引擎执行重算,不能把 openpyxl 当成公式解释器。

一个可直接运行的销售报表示例

可以这样实践:下面的脚本创建销售数据、公式、表头样式和柱状图。运行前安装依赖:

python -m pip install openpyxl

将以下内容保存为 build_report.py,然后执行 python build_report.py

from openpyxl import Workbook
from openpyxl.chart import BarChart, Reference
from openpyxl.styles import Alignment, Font, PatternFill
from openpyxl.utils import get_column_letter

rows = [
    ("键盘", 12, 199),
    ("鼠标", 20, 89),
    ("显示器", 7, 1299),
    ("扩展坞", 9, 499),
]

workbook = Workbook()
worksheet = workbook.active
worksheet.title = "销售报表"
worksheet.append(["产品", "数量", "单价", "金额"])

for row_number, (product, quantity, price) in enumerate(rows, start=2):
    worksheet.append([product, quantity, price])
    worksheet.cell(row=row_number, column=4, value=f"=B{row_number}*C{row_number}")

header_fill = PatternFill(fill_type="solid", fgColor="1F4E78")
for cell in worksheet[1]:
    cell.font = Font(color="FFFFFF", bold=True)
    cell.fill = header_fill
    cell.alignment = Alignment(horizontal="center")

for row in worksheet.iter_rows(min_row=2, min_col=3, max_col=4):
    for cell in row:
        cell.number_format = '¥#,##0.00'

for column_cells in worksheet.columns:
    max_length = max(len(str(cell.value or "")) for cell in column_cells)
    column_letter = get_column_letter(column_cells[0].column)
    worksheet.column_dimensions[column_letter].width = min(max_length + 3, 30)

worksheet.freeze_panes = "A2"
worksheet.auto_filter.ref = worksheet.dimensions

chart = BarChart()
chart.title = "各产品销售数量"
chart.y_axis.title = "数量"
chart.x_axis.title = "产品"
chart.height = 7
chart.width = 12

values = Reference(worksheet, min_col=2, min_row=1, max_row=1 + len(rows))
categories = Reference(worksheet, min_col=1, min_row=2, max_row=1 + len(rows))
chart.add_data(values, titles_from_data=True)
chart.set_categories(categories)
worksheet.add_chart(chart, "F2")

workbook.save("sales_report.xlsx")
print("已生成 sales_report.xlsx")

这个例子同时覆盖了几个容易在练习中混淆的点:行号从 1 开始;公式必须引用实际写入的行;数字格式只影响显示,不会把数值变成字符串;图表数据区域需要显式指定表头和数据边界。

图片与大型工作簿的边界

工作表也可以插入图片。该能力通常需要 Pillow,并且更适合放置标志、产品缩略图或报告截图:

python -m pip install openpyxl pillow

假设当前目录存在 logo.png,可以这样实践:

from openpyxl import Workbook
from openpyxl.drawing.image import Image

workbook = Workbook()
worksheet = workbook.active

logo = Image("logo.png")
logo.width = 160
logo.height = 60
worksheet.add_image(logo, "A1")

workbook.save("report_with_logo.xlsx")

图片会增加文件体积,也可能在不同办公软件中出现尺寸或定位差异。对复杂模板,应在目标 Excel 客户端中进行实际验收。

大型文件则需要关注内存。常规模式会在内存中维护工作簿对象;如果只需连续输出大量数据,可以评估 Workbook(write_only=True)。但写入模式会限制随机访问和部分编辑方式,因此应先确认是否还需要回头修改单元格、样式或图表。

落地前的检查清单

openpyxl 用进生产任务前,可以检查以下事项:

  • 明确输入输出仅针对 .xlsx 等受支持格式,不把它当作旧版 .xls 的通用处理器。
  • 区分公式文本、缓存值和实际计算结果。
  • 为金额、日期和百分比设置 Excel 数字格式,同时保留底层数据类型。
  • 使用固定的工作表名称、表头和列映射,避免依赖容易变化的活动工作表位置。
  • 批量处理前保留原文件,并将结果写入新路径。
  • 用 Excel 或目标办公软件打开成品,检查公式、图表、图片、筛选器和冻结窗格。
  • 对超大工作簿测试运行时间、峰值内存和输出文件大小。

openpyxl 最适合结构清晰的 Excel 自动化:Python 负责组织数据和生成工作簿,Excel 负责交互查看与公式计算。掌握这条边界后,从一次性的表格脚本扩展到稳定的报表流水线会容易得多。


相关推荐