Python 办公自动化:Excel 文件处理(上)

Python 读写 Excel 文件(基础篇)

1. Excel 简介与技术选型

Excel 是商业数据处理领域的“通用协作语言”,几乎所有涉及报表、统计的岗位都会和它打交道。但重复的手工操作实在让人头疼——每周五手动合并 20 张子公司导出的 .xls 周报,或者月底在数千行旧版财务数据里筛选求和……这些场景在 Daoman Python AI 的实战辅导中反复出现,原因很简单:许多国企、中小型传统企业的内部系统、老旧的设备导出的报表,依然强制使用 Excel 97-2003 标准(.xls 格式)。新版的 openpyxl 对这类文件束手无策,因此掌握专门针对旧版 Excel 的库组合就成了办公自动化的必学技能。

工具链快速梳理

Python 生态对 .xls 文件有一套清晰的分工方案:

  • 读旧版 (.xls)xlrd —— 打开工作簿、定位单元格,还能处理日期、合并单元格等特殊格式。
  • 写旧版 (.xls)xlwt —— 新建工作簿、写入数据、设置字体/颜色/边框,甚至写入 Excel 公式。
  • 改旧版 (.xls)xlutils —— 通过 copy 功能把 xlrd 的只读对象转成 xlwt 的可写对象,实现“修改原有文件”。

环境一键安装

💡 敲黑板! xlrd 从 2.0.0 版本起彻底取消了对 .xlsx 格式的支持,为了确保能够正常读写旧版文件,安装时必须指定 1.2.0 这个经典版本。

pip install xlwt xlrd==1.2.0 xlutils

安装完成后,就可以正式开始我们的自动化之旅了。


2. 读取 Excel 文件

.xls 文件的读取逻辑和我们手动打开 Excel 软件的过程几乎一模一样:打开文件(Workbook) → 找到并切换到指定工作表(Sheet) → 定位单元格(Cell) → 处理单元格里的特殊格式。只要顺着这个思路走,代码会非常清晰。

实战:批量读取 2020 年阿里巴巴股票数据(简化版)

我们以一份简化的“阿里股票交易日”数据为例,文件名为 阿里巴巴2020年股票数据.xls,里面包含日期、开盘价、收盘价等字段。这个例子最核心的练习是日期格式的转换——这也是 xlrd 初学者最容易掉进去的坑:Excel 内部并不是用“2020‑01‑02”这样的字符串来存储日期,而是用一个纯数字,把 1900‑01‑01 记为 1,之后每过一天数字就加 1。

下面直接上代码:

import xlrd

# 1. 打开工作簿(记得加上 formatting_info=True,用以保留单元格格式)
wb = xlrd.open_workbook('阿里巴巴2020年股票数据.xls', formatting_info=True)

# 2. 获取并切换到我们要处理的工作表
# 方法1:按名称查找(推荐,不怕顺序变动)
# sheet = wb.sheet_by_name('Sheet1')
# 方法2:按索引查找(从0开始)
sheet_names = wb.sheet_names()
print(f"文件中的所有工作表:{sheet_names}")
sheet = wb.sheet_by_index(0)

# 3. 查看表格的基本信息
print(f"总行数:{sheet.nrows},总列数:{sheet.ncols}")
print("-" * 80)

# 4. 逐行读取,并针对日期列做转换处理
# 假设第0列是日期,第1列是开盘价,第2列是收盘价……
for row_idx in range(sheet.nrows):
    # 取出整行的值(原始格式)
    row_values = sheet.row_values(row_idx)

    # ---- 日期转换的关键步骤 ----
    # 判断第0列单元格的类型是否为日期类型
    if sheet.cell_type(row_idx, 0) == xlrd.XL_CELL_DATE:
        # cell_value 得到的是一个浮点数(如 43831),表示距离 1900-01-01 的天数
        date_value = sheet.cell_value(row_idx, 0)
        # 利用 xldate_as_tuple 转换为 (年, 月, 日, 时, 分, 秒) 元组
        date_tuple = xlrd.xldate_as_tuple(date_value, wb.datemode)
        # 格式化为易读的日期字符串(只取年月日)
        date_str = f"{date_tuple[0]}-{date_tuple[1]:02d}-{date_tuple[2]:02d}"
    else:
        # 如果不是日期类型,就直接用原始字符串
        date_str = str(row_values[0])

    # 打印处理后的结果
    print(f"{date_str:>12s} 开盘:{row_values[1]:>8.2f} 收盘:{row_values[2]:>8.2f}")

代码要点解析:

  • formatting_info=True:这个参数很关键,它让 xlrd 在打开文件时尽量保留原有的格式信息,当你后续可能需要判断单元格类型(如日期、带边框等)或使用 xlutils 修改文件时,一定要带上它。
  • cell_type(row_idx, col_idx):返回单元格的数据类型常量,比如 XL_CELL_DATE 就表示这个单元格是日期格式。
  • xldate_as_tuple(value, datemode):把 Excel 内部数字转换为真正的日期元组。datemode 参数由工作簿自动提供,用来区分 1900 年日期系统(常见)和 1904 年日期系统(Mac 上的一些老文件),直接用 wb.datemode 传入就不会出错。

运行这段代码,你就能看到整洁的日期和对应的股价数据了。至此,.xls 文件的读取脉络已经打通——无论表格里藏着多少日期、多少行数据,都能用这套思路自动化处理。


3. 本篇小结

通过本文,你掌握了:

  • .xls 格式的必要性及工具链 xlrd / xlwt / xlutils 的定位;
  • 使用 xlrd 打开工作簿、定位工作表、遍历所有单元格;
  • 处理 Excel 中最棘手的日期数字,转换为人类可读的格式。

这些读取技巧已经可以帮你应对大量报表自动化任务,比如批量汇总、按条件筛选、跨文件整合等。而在下一篇教程中,我们将继续使用 xlwt 创建新的 .xls 文件、写入数据,并定制漂亮的表格样式,真正打通“读‑写‑改”的闭环。