Python 读写 Excel 文件-2 (openpyxl 进阶)

Python 读写 Excel 文件(进阶篇)

1. openpyxl 简介:现代办公自动化的首选

在上一章我们搞定了旧版 .xls 的读写,但现在谁还用 .xls 存日常数据呢?主流报表、统计表格现在都用 **Office 2007+ 引入的 **.xlsx XML 格式对吧?那处理它的 Python 生态「头牌非 openpyxl 莫属——读写合一、功能全、语法还特别贴合 Excel 原生习惯!

对比旧工具 xlrd/xlwt 组合的痛点——它们各自管读/写不同格式,openpyxl 直接把这些功能全整合,优势太直观:

  • 一键保存无割裂:读的时候可以原地改,同一个工作簿对象,既能读也能改也能删,操作完全顺
  • 坐标爽歪歪:直接敲 A1C4 这种日常 Excel 坐标定位,不用再记行列换算
  • 功能天花板:原生支持字体边框对齐等全样式编辑、公式直接写进去 Excel 公式(不是文本!是能重新计算的)、数据透视图表(哦对还有数据透视表这里先预告基础图表)

⚠️ 格式限制 只认 .xlsx/.xlsm.xls 请戳上一章的工具哦!别白忙活!

安装指令

pip install openpyxl
# 如果国内网络卡,加个清华镜像源
pip install openpyxl -i https://pypi.tuna.tsinghua.edu.cn/simple

2. 读取 Excel 文件:灵活的坐标定位

读取灵活得离谱!

除了普通的行列索引,Excel 原生坐标字符串绝对是 openpyxl 最香的地方——不用每次拿纸笔算行列对应的数字索引,写出来的代码自己下次看也秒懂!

实战:读取股票历史数据

import datetime
import openpyxl

# 1. 加载工作簿:read_only=False(默认)可读写,只读模式处理百万行级可开=True
wb = openpyxl.load_workbook('阿里巴巴2020年股票数据.xlsx')
# 获取第一个工作表:worksheets[0]/active(如果第一个一般是第一个打开的
sheet = wb.active

# 快速扫一眼表的基本属性(避免白写死范围
print(f"有效区域范围范围:{sheet.dimensions}") # 输出类似 A1:G255
print(f"行数:{sheet.max_row}, 列数:{sheet.max_column}")

# 花式读单元格:三种常用方式任你选
# ✅ 推荐方式1:Excel 坐标字符串(最直观)
open_price = sheet['C2'].value
# 📌 注意:方式2:cell 方法(行列索引从 **1** 开始!别踩 xlrd 的 0 搞混!
close_price = sheet.cell(row=2, column=5).value
# ⚙️ 方式3:直接遍历切片读整列/整行(返回是单元格对象列表,values_only=True 直接取纯值省内存!
c_col_cells = sheet['C']
dates = sheet['A2:A10']

# 正式遍历处理混合类型数据遍历:股票数据里的日期自动转成 datetime 对象,直接格式化输出更友好
for row in sheet.iter_rows(min_row=2, values_only=True):
    for idx, value in enumerate(row):
        if isinstance(value, datetime.datetime):
            print(value.strftime('%Y-%m-%d'), end='\t')
        else:
            # 对齐下格式,比如数字保留2位小数
            if idx >= 2:
                print(f"{value:.2f}\t", end='')
            else:
                print(f"{value}\t", end='')
    print()

3. 写入与样式定制:报表好看才是专业

openpyxl 把样式拆成了一个个小模块,按需拼接,像搭积木一样调报表!

插一句:**样式都是对「日常的字体、对齐、边框等模块都能单独保存复用,不用每次写一大串!

import openpyxl
from openpyxl.styles import Font, Alignment, Border, Side, PatternFill

# 新建工作簿:默认有个叫 Sheet 的工作表
wb = openpyxl.Workbook()
sheet = wb.active
sheet.title = '高一1班期中成绩'

# ✨ 先搭好「积木」样式模板,后面重复用
header_font = Font(size=14, bold=True, color='FFFFFF', name='微软雅黑')
header_fill = PatternFill(fill_type='solid', fgColor='4472C4') # Excel 经典表头蓝
center_align = Alignment(horizontal='center', vertical='center', wrap_text=True) # 自动换行也加上
thin_side = Side(style='thin', color='000000')
full_border = Border(left=thin_side, top=thin_side, right=thin_side, bottom=thin_side)

# 1. 写表头 + 直接应用模板
headers = ['姓名', '语文', '数学', '英语', '总分']
for col_idx, header_text in enumerate(headers, 1):
    cell = sheet.cell(1, col_idx, header_text)
    cell.font = header_font
    cell.fill = header_fill
    cell.alignment = center_align
    cell.border = full_border

# 2. 写学生成绩
students = [
    ['张三', 92, 88, 95],
    ['李四', 85, 96, 90],
    ['王五', 78, 82, 87]
]
for row_idx, student_data in enumerate(students, 2):
    for col_idx, score in enumerate(student_data, 1):
        cell = sheet.cell(row_idx, col_idx, score)
        cell.alignment = center_align
        cell.border = full_border
        # 顺便给低分(<80分)加个红色背景提醒
        if isinstance(score, int) and score < 80:
            cell.fill = PatternFill(fill_type='solid', fgColor='FFC7CE')

# 3. 写 Excel 原生公式!=开头就行,不是文本哦!打开 Excel 会自动算
for row_idx in range(2, 5):
    sheet.cell(row_idx, 5).value = f'=SUM(B{row_idx}:D{row_idx})'
    # 公式单元格也加边框对齐
    sheet.cell(row_idx, 5).alignment = center_align
    sheet.cell(row_idx, 5).border = full_border

# 4. 自动调整列宽(简单版,复杂版可以用库或手动算字符数)
for col in sheet.columns:
    max_length = 0
    column = col[0].column_letter # 获取列字母
    for cell in col:
        try:
            if len(str(cell.value)) > max_length:
                max_length = len(str(cell.value))
        except:
            pass
    adjusted_width = (max_length + 2) * 1.2 # 中文占2个字符位,加2的边距
    sheet.column_dimensions[column].width = adjusted_width

wb.save('高一1班期中成绩_美化版.xlsx')

4. 生成专业原生 Excel 图表:不是图片!不是图片!不是图片!

敲黑板!这是 openpyxl 最吸引办公党、报表党的杀招——生成的是原生 Excel 可交互图表对象!打开 Excel 后可以拖动图表看数据源、改配色、改类型(从柱状图换折线图分分钟的事!

from openpyxl import Workbook
from openpyxl.chart import BarChart, LineChart, Reference, Series

wb = Workbook()
sheet = wb.active
sheet.title = '电商周销榜'

# 1. 先准备点「周销数据」
week_sales = [
    ['商品', '销量'],
    ['无线蓝牙耳机', 2100],
    ['智能手环', 1850],
    ['降噪耳机', 3200],
    ['笔记本支架', 2700]
]
for row in week_sales:
    sheet.append(row)

# 2. 做个「主图:柱线结合?或者先做个**带渐变填充的柱状图(最常用)
bar_chart = BarChart()
bar_chart.title = "本周热销榜TOP4"
bar_chart.y_axis.title = '销量'
bar_chart.x_axis.title = '商品'
bar_chart.style = 10 # Excel 预设的好看的第10种渐变柱形图样式

# 3. 引用数据!titles_from_data=True 会把第一行「销量」当 Y 轴标题
values = Reference(sheet, min_col=2, min_row=1, max_row=5)
categories = Reference(sheet, min_col=1, min_row=2, max_row=5)

bar_chart.add_data(values, titles_from_data=True)
bar_chart.set_categories(categories)

# 4. 插入到表格的 E2 位置(图表左上角在 E2)
sheet.add_chart(bar_chart, "E2")

wb.save('电商周销榜_带原生图.xlsx')

5. 总结与避坑建议

总结一句话:**处理 .xlsx 非 Pandas 补基础交互(样式/原生图/小批量数据,用 Pandas 底层也是用 openpyxl 存,但纯数据百万行级计算/清洗 Pandas 快!

避坑建议:

  1. 行列索引:从 1 开始!别搞混旧工具的 0!
  2. 值模式读写:百万行级纯数据读一定要开 read_only=True,写开 write_only=True,省内存!
  3. 公式:写公式一定要用 英文标点!中文标点会报错!