十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Python操作Excel自动化:xlrd与xlwt读写.xls文件详解

Python操作Excel自动化:xlrd与xlwt读写.xls文件详解 在自动化办公场景里操作 Excel 是最常见、也最容易出成果的一类需求。日常工作里你可能会遇到用 Python 把几十个 Excel 文件里的数据合并成一张总表把接口返回的数据批量写入报表或者从一份老系统导出的 .xls 文件里读出成绩、名单、库存数据再加工。如果把读取、写入、批量处理、样式控制这些环节都打通很多重复劳动就能直接交给脚本完成。这一篇我们就把 xlrd 和 xlwt 这两个经典模块讲透包括模块参数、读 Excel、写 Excel、读写组合案例、批量任务、常见坑位排查以及新老格式 Excel 文件的边界问题。xlrd 解决的是“读取 Excel 文件”的问题xlwt 解决的是“写入 Excel 文件”的问题二者搭配使用可以在不打开 Excel 软件的情况下完成自动化读写。从标题可以看出这是“100天精通 Python”系列第 41 天的内容所以文章也会按“模块参数说明 代码实战”的结构来组织。阅读下面内容之前你需要先准备好 Python 环境并且理解基本的文件路径、for 循环、函数封装和类的基本用法。这里要先把结论放在前面如果你要处理的文件是.xlsx格式而且你准备安装最新版 xlrd那么会得到一行报错因为 xlrd 2.0 之后不再支持.xlsx只支持旧版.xls。xlwt 同样只能写出.xls格式文件。如果你的业务场景里全是新格式工作簿更合适的方案是 openpyxl 或 pandas。文章后面会解释为什么这个边界如此重要同时给出最稳妥的开源库选型建议。1. 核心能力速览能力项说明模块名称xlrd读 Excelxlwt写 Excel文件格式支持两者都围绕旧版.xls格式xlrd 2.0 不支持.xlsxxlwt 也不支持.xlsx主要功能读取工作表、单元格、行/列数据、日期单元格创建工作簿、工作表、写入数据、设置单元格样式读 Excel 的典型操作xlrd.open_workbook()、sheet_by_index()、row_values()、cell()写 Excel 的典型操作xlwt.Workbook()、add_sheet()、write()、save()支持的 Python 版本参考以官方 PyPI 兼容声明为准常规 Python 3.6 环境可安装使用是否需要网络安装时需要访问 pip 源之后在本地离线运行启动方式无 GUI通过 Python 脚本调用API 接口能力标准库函数式 API通过命令行脚本或业务代码调用批量任务能力支持用循环遍历多个文件、多个 Sheet 快速批量处理适用场景老系统导出.xls文件的数据清洗、Excel 报表生成、多文件汇总、非交互式自动化任务这两个库的最大优点是很轻量不依赖 Office 软件环境也不要求目标电脑安装了 Excel。正因如此xlrd 和 xlwt 非常适合放在服务器脚本、接口服务、批量任务系统里使用。缺点是功能整体偏基础复杂样式控制、图表、数据透视表这些能力有限需要配合办公软件或其他库解决。2. 适用场景与使用边界2.1 适合哪些场景xlrd xlwt 最常见的使用场景第一类是数据迁移和清洗。比如旧业务系统导出的历史 Excel 文件是.xls格式里面有几千行客户资料需要读取后写入数据库第二类是测试数据和报表生成把某个接口返回的数据变成一份可交付的 Excel 报表第三类是部门内部的 Excel 批量处理比如读取一个目录下所有成绩单筛选出指定分数区间后重新汇总。如果你是 Python 初学者使用 xlrd 和 xlwt 还有一层特殊价值它们代码思路非常直白“打开工作簿 - 找到工作表 - 按行列读取/写入”这个模型和 Excel 自身的视图高度一致适合用来建立对表格数据结构的直觉。很多涉及 Excel 自动化的经典面试题底层也是在考察这个数据模型。2.2 不适合哪些场景如果遇到.xlsx文件不建议继续用 xlrd 2.x 硬读直接用 openpyxl 更省心。如果你的 Excel 文件超过 65536 行xlwt 无法写入这也是旧版.xls格式的行数上限解决思路是改用 openpyxl 写.xlsx或科学计算类库。如果你需要执行复杂公式计算、大量图表、数据透视表、条件格式xlwt 能做的是有限度的静态样式复杂视觉效果需要评估后决定没有必要在旧库上死磕。如果文件很大且读取频繁xlrd 的性能虽可用但肯定不如专门针对.xlsx的现代库来得稳定需要根据实际文件规模先做小样本测试。2.3 使用边界与合规要求凡是涉及自动化读写 Excel都要注意三点。第一脚本处理的数据如果包含姓名、电话、身份证号、成绩、工资等个人信息必须确认数据来源和使用的授权范围不要在未经授权的情况下用脚本批量采集或转发。第二涉及爬虫数据的场景爬取前需要了解目标平台的使用条款导出到 Excel 只是下游操作不代表来源合法。第三办公网内批量处理文件时建议先用脱敏假数据在小范围试运行不要直接拿着生产库数据做第一次调试。下面的代码示例和演示文件也建议用虚构数据不涉及任何真实个人信息。3. 环境准备与前置条件3.1 检查 Python 版本在开始之前先确认电脑上是否已经安装了 Python。不同操作系统的检查方式差不多python --version如果你电脑里同时装了多个 Python 版本也可能是python3 --version。输出结果里能看到类似Python 3.10.11的版本号即可。如果还没有安装 Python可以参考 Python 官网或自己常用的 Python 安装教程完成部署安装时记得勾选“Add Python to PATH”。3.2 创建虚拟环境不推荐直接把第三方库装到系统 Python 环境中尤其是以后要写多个项目时依赖很容易互相干扰。建议用 venv 创建虚拟环境python -m venv excel_envWindows 下激活excel_env\Scripts\activatemacOS 或 Linux 下激活source excel_env/bin/activate激活后命令行提示符前面会多出(excel_env)之类的标识。3.3 安装 xlrd 和 xlwt激活虚拟环境后执行安装命令pip install xlrd xlwt如果想指定版本比如强制安装支持旧版 Excel 的兼容环境可以这样写pip install xlrd1.2.0 xlwt1.3.0这里需要特别说明一下版本策略xlrd 从 2.0 版本开始只支持.xls如果你明确要读取.xls用最新版问题不大但如果你还需要读取.xlsx用 xlrd 1.2.0 是最稳妥的旧方案。新手如果不确定自己在做什么最安全的做法是.xls用 xlrd.xlsx直接用 openpyxl不要混着猜。安装完成后可以检查版本pip show xlrd pip show xlwt3.4 准备测试文件为了方便后面的代码实战建议先手动创建一个成绩表.xls里面写 4 列数据学号、姓名、成绩、备注。不要用.xlsx保存请另存为 Excel 97-2003 工作簿格式。如果你手头只有.xlsx测试文件想快速体验 xlrd可以在 Excel 里执行“另存为 - Excel 97-2003 工作簿 (.xls)”。如果电脑里没有 Excel也可以用 LibreOffice 或在线表格工具导出旧格式文件但要注意不要使用来源不明的示例数据。一个推荐文件结构是excel_project/ ├── excel_env/ ├── read_demo.py ├── write_demo.py ├── 成绩表.xls └── output/output目录用于存放脚本输出的新文件这样源文件目录保持干净排查问题更方便。4. 用 xlrd 读取 Excel 文件的核心参数与操作4.1 open_workbook 方法参数读取的第一步是打开工作簿import xlrd workbook xlrd.open_workbook(成绩表.xls)xlrd.open_workbook()是核心入口它内部会打开工作簿文件并解析 Excel 结构。实际使用中常见参数如下参数作用使用建议filename文件路径建议使用绝对路径或基于脚本所在目录拼接的路径file_contents把文件内容以字节串形式传入适合从网络接口或数据库字段中读取文件内容不需要先落盘encoding_override覆盖编码识别遇到乱码时才使用老文件偶尔需要formatting_info是否读取格式信息默认 False只有需要使用某些格式功能时才打开on_demand是否按需加载 Sheet处理大型工作簿时可以减少内存占用ragged_rows是否允许每行单元格数量不一致某些不规范的 Excel 文件可能需要开启举一个file_contents的场景假设文件内容不是保存在本地磁盘而是从某个接口读取到内存中这时候就不必先写成临时文件可以直接把二进制内容交给file_contents。实际写法如下import xlrd # data 是二进制内容例如从接口返回或从数据库读取 # data response.content workbook xlrd.open_workbook(file_contentsdata)这种写法在自动化接口集成任务里很常见属于不需要落盘的技巧。4.2 获取工作簿和工作表信息打开工作簿后第一步是搞清楚里面有几张表、表名分别是什么import xlrd workbook xlrd.open_workbook(成绩表.xls) print(工作表数量, workbook.nsheets) print(工作表名称, workbook.sheet_names()) sheet workbook.sheet_by_index(0) print(工作表名, sheet.name) print(行数, sheet.nrows) print(列数, sheet.ncols)workbook.nsheets表示工作表数量sheet_names()返回全部工作表名称列表。sheet_by_index(0)表示按索引取第一张工作表sheet_by_name(Sheet1)表示按表名取。读取数据前先打印行数和列数可以帮助判断文件是否为空、表头占用几行。4.3 逐行逐列读取单元格数据读取整行数据用row_values()读取整列数据用col_values()import xlrd workbook xlrd.open_workbook(成绩表.xls) sheet workbook.sheet_by_index(0) # 读取第一行也就是表头 header_row sheet.row_values(0) print(表头, header_row) # 读取前 5 行所有列 for row_index in range(1, min(5, sheet.nrows)): row_data sheet.row_values(row_index) print(row_data)row_values()的行号和col_values()的列号都是从 0 开始。row_values(0)返回第一行的所有单元格组成的列表通常用于读取表头。循环遍历时可以根据表头所在行决定从第几行开始读取有效数据。读取单个单元格用cell()cell sheet.cell(1, 2) # 第 2 行第 3 列 print(单元格内容, cell.value) print(单元格类型, cell.ctype)cell.rowx和cell.colx对应单元格所在行列。返回值中的ctype是单元格数据类型Excel 单元格常见类型映射值如下ctype 值类型0空1文本2数字3日期4布尔值5错误6空白注意如果某一行数据缺失读取出来的可能不是完整的行。实际工作中判断“某列是否有值”更稳妥的做法是先用sheet.nrows和sheet.ncols判断范围再用cell_type()或cell().ctype判断类型。4.4 日期单元格的处理xlrd 读取日期时返回的往往是一个浮点数这是 Excel 内部存储日期的通用做法。直接使用很容易出错因此需要借助xlrd.xldate_as_datetime()或xlrd.xldate_as_tuple()转换import xlrd from datetime import datetime workbook xlrd.open_workbook(成绩表.xls) sheet workbook.sheet_by_index(0) # 假设第 0 行第 3 列是日期 cell sheet.cell(0, 3) if cell.ctype xlrd.XL_CELL_DATE: date_value xlrd.xldate_as_datetime(cell.value, workbook.datemode) print(日期, date_value.strftime(%Y-%m-%d))判断是否为日期要看cell.ctype xlrd.XL_CELL_DATE。如果你把日期单元格打印成浮点数字不要着急先用datemode参数配合转换函数处理。workbook.datemode表示日期系统的基准模式不同机器生成的.xls文件很可能不同所以转换时不能写死 0 或 1。4.5 一个完整的读取函数阅读数据可以封装成一个函数这样处理多个文件时只需调用函数即可。下面代码演示如何读取所有 Sheet 并返回字典结构import xlrd def read_xls_all_sheets(file_path): workbook xlrd.open_workbook(file_path) result {} for sheet_name in workbook.sheet_names(): sheet workbook.sheet_by_name(sheet_name) data [] for row_index in range(sheet.nrows): row sheet.row_values(row_index) data.append(row) result[sheet_name] data return result if __name__ __main__: data read_xls_all_sheets(成绩表.xls) for sheet_name, rows in data.items(): print(sheet_name, 共, len(rows), 行) for row in rows[:3]: print(row)这段代码适合中小型文件。如果是几百 MB 级别的大型工作簿把所有 Sheet 数据一次性读入内存并不理智可以按需只读取指定 Sheet或者用on_demandTrue延迟加载来降低内存压力。5. 用 xlwt 创建和写入 Excel 文件5.1 Workbook 与 Worksheet 创建写 Excel 的核心类是xlwt.Workbook。一个工作簿有若干工作表写入数据要经过“创建工作簿 - 添加工作表 - 向单元格写入数据 - 保存文件”四个步骤import xlwt workbook xlwt.Workbook(encodingutf-8) worksheet workbook.add_sheet(学生成绩) worksheet.write(0, 0, 学号) worksheet.write(0, 1, 姓名) worksheet.write(0, 2, 成绩) workbook.save(output/新成绩表.xls)上面的add_sheet(学生成绩)添加工作表并回传工作表对象write(r, c, label)把数据写入第r行第c列。保存前要注意output目录必须存在否则程序会报错。5.2 add_sheet 与 write 参数说明Workbook.add_sheet(sheetname, cell_overwrite_okFalse)的第二个参数cell_overwrite_ok很关键。默认情况下向同一个单元格写入两次会抛出Exception: Attempt to overwrite cell之类的错误。如果你的代码是通过循环多次调用write()而且逻辑上确实存在重复写入同一单元格的情况可以设置cell_overwrite_okTrue。但在实际项目中我建议保持默认值。因为默认值可以帮你提前暴露重复写入的问题这种报错往往是数据源重复导致而不是真的需要覆盖写入。先检查数据是否存在重复远比直接打开覆盖开关更合理。worksheet.write(r, c, label, styleNone)表示将数据写入第r行第c列。label可以是数字、字符串或日期style参数用于设置单元格样式。如果省略style则使用默认样式。5.3 设置常见单元格样式xlwt 的样式控制主要靠xlwt.XFStyle。一个样式对象可以组合字体、对齐方式、边框和背景色等属性。字体设置示例import xlwt font xlwt.Font() font.name 微软雅黑 font.height 12 * 20 # 字号单位是 twips12 磅对应的值是 240 font.bold True style xlwt.XFStyle() style.font font对齐方式示例alignment xlwt.Alignment() alignment.horz xlwt.Alignment.HORZ_CENTER alignment.vert xlwt.Alignment.VERT_CENTER style_alignment xlwt.XFStyle() style_alignment.alignment alignment边框示例borders xlwt.Borders() borders.left xlwt.Borders.THIN borders.right xlwt.Borders.THIN borders.top xlwt.Borders.THIN borders.bottom xlwt.Borders.THIN style_border xlwt.XFStyle() style_border.borders borders实际使用中往往需要组合多个样式import xlwt def make_header_style(): font xlwt.Font() font.name 微软雅黑 font.height 12 * 20 font.bold True alignment xlwt.Alignment() alignment.horz xlwt.Alignment.HORZ_CENTER alignment.vert xlwt.Alignment.VERT_CENTER borders xlwt.Borders() borders.left xlwt.Borders.THIN borders.right xlwt.Borders.THIN borders.top xlwt.Borders.THIN borders.bottom xlwt.Borders.THIN style xlwt.XFStyle() style.font font style.alignment alignment style.borders borders return style workbook xlwt.Workbook(encodingutf-8) worksheet workbook.add_sheet(学生成绩) header_style make_header_style() headers [学号, 姓名, 成绩] for col_index, header in enumerate(headers): worksheet.write(0, col_index, header, header_style) workbook.save(output/样式示例.xls)这里的核心理解是样式对象是整体生效的。定义一个XFStyle再给它的font、alignment、borders等属性分别赋值最后在write时作为第四个参数传入。如果要为普通数据行设置样式也可以定义第二个样式比如给总分字段加粗。5.4 写入多行数据和日期写入多行时直接在外层循环中调用write()。xlwt 写入日期需要先把 Python 的datetime或date对象转换成xlwt.easyxf支持的方式常见做法是使用xlwt.easyxf或手动设置单元格格式。下面是一个写入日期和数值的完整示例import xlwt from datetime import datetime workbook xlwt.Workbook() sheet workbook.add_sheet(考勤记录) sheet.write(0, 0, 日期) sheet.write(0, 1, 当天时长) sheet.write(1, 0, datetime(2025, 1, 1), xlwt.easyxf(, num_format_strYYYY-MM-DD)) sheet.write(1, 1, 8.5) workbook.save(output/考勤记录.xls)写日期时最容易踩的坑是写入后 Excel 打开是乱码数值而不是日期。问题通常出在没有设置日期格式因为 Excel 单元格需要知道这个数字按什么格式显示。上面代码中的num_format_strYYYY-MM-DD就是指定格式化方式。如果你发现写入后日期列显示为奇怪的数字第一排查点就是这里。5.5 一个完整的写入函数下面代码演示如何把内存中的二维数据一次性写入 Excel适合用来批量生成报表import xlwt def write_list_to_xls(file_path, sheet_name, headers, rows, header_styleNone): workbook xlwt.Workbook(encodingutf-8) sheet workbook.add_sheet(sheet_name) if headers: for col_index, header in enumerate(headers): if header_style: sheet.write(0, col_index, header, header_style) else: sheet.write(0, col_index, header) start_row 1 if headers else 0 for row_offset, row_data in enumerate(rows): row_index start_row row_offset for col_index, value in enumerate(row_data): sheet.write(row_index, col_index, value) workbook.save(file_path)这个函数把“表头书写”和“数据行书写”分成两步核心逻辑不会因为数据量增加而改变。只要rows是标准的二维列表就能稳定写入。6. 读写结合筛选成绩并生成新表学完读和写之后最值得练的实战是“读取一个 Excel按条件筛选后生成另一个 Excel”。这里演示一个贴近真实办公场景的任务读取成绩表.xls把成绩在 70 到 80 分之间的学生筛选出来写入新的 Excel。先准备输入文件。假设成绩表.xls内容如下学号姓名成绩备注001张三85良好002李四72及格003王五68及格004赵六79良好用来处理这个需求的脚本import xlrd import xlwt input_path 成绩表.xls output_path output/筛选结果.xls workbook xlrd.open_workbook(input_path) sheet workbook.sheet_by_index(0) # 读取所有数据 all_rows [] for row_index in range(sheet.nrows): all_rows.append(sheet.row_values(row_index)) if len(all_rows) 2: raise ValueError(文件中没有有效数据) header_row all_rows[0] score_col header_row.index(成绩) filtered_rows [header_row] for row in all_rows[1:]: # 成绩可能是浮点数先转成数字处理 try: score float(row[score_col]) except (TypeError, ValueError): continue if 70 score 80: filtered_rows.append(row) # 写入新文件 out_workbook xlwt.Workbook(encodingutf-8) out_sheet out_workbook.add_sheet(70到80分) for row_index, row_data in enumerate(filtered_rows): for col_index, value in enumerate(row_data): out_sheet.write(row_index, col_index, value) out_workbook.save(output_path) print(筛选完成共, len(filtered_rows) - 1, 条记录)运行成功后output/筛选结果.xls会包含表头和两条成绩 70 到 80 之间的记录即李四的 72 分和赵六的 79 分。这个例子虽然简单但很能说明 problem 的核心读文件时返回的数字可能是float写入时也会按浮点数写入后续如果要做字符串匹配需要事先统一类型。另外header_row.index(成绩)这种方法避免了写死成绩所在列号即使源文件在前面添加了列脚本依然能正常定位。可以进一步扩展的功能包括多条件筛选比如既要成绩在 70 到 80 之间又要求备注是“良好”、把姓名和电话分离后重新排版、把 Excel 中的字符串数据匹配后标记年份、把结果导出给下游系统导入数据库等。这些操作都可以在“读取二维列表 - 列表筛选/变换 - 写入新文件”这个模型里完成只是中间处理规则不同。7. 多文件批量汇总任务单个文件处理清楚后批量处理的价值才真正体现出来。自动化办公中经常遇到这样的需求某个目录下存放了几十个.xls文件每个文件结构相同需要把这些文件的所有数据汇总到一个总表里。批量汇总的思路如下用os.listdir()或glob.glob()获取目录下所有.xls文件。逐个用 xlrd 读取跳过空文件和表头行。把所有数据行累积到列表。最后用 xlwt 一次性写出。示例代码如下import glob import os import xlrd import xlwt def merge_xls_files(input_dir, output_path): workbook xlwt.Workbook(encodingutf-8) sheet workbook.add_sheet(汇总数据) current_row 0 file_count 0 for file_path in sorted(glob.glob(os.path.join(input_dir, *.xls))): print(处理文件, file_path) try: wb xlrd.open_workbook(file_path) ws wb.sheet_by_index(0) except Exception as e: print(f打开文件失败: {file_path}, 错误: {e}) continue if ws.nrows 0: continue # 每个文件的第一行作为表头只在总表为空时写入 if current_row 0: header ws.row_values(0) for col_index, value in enumerate(header): sheet.write(current_row, col_index, value) current_row 1 # 数据从第 1 行开始第 0 行视为表头 for row_index in range(1, ws.nrows): row_data ws.row_values(row_index) # 跳过完全为空的尾行 if not any(str(v).strip() for v in row_data): continue for col_index, value in enumerate(row_data): sheet.write(current_row, col_index, value) current_row 1 file_count 1 if current_row 0: print(没有找到可合并的数据文件) return workbook.save(output_path) print(f合并完成共处理 {file_count} 个文件总行数 {current_row - 1}) if __name__ __main__: merge_xls_files(data, output/合并结果.xls)这个函数里有几个值得学习的处理细节使用glob.glob(os.path.join(input_dir, *.xls))按目录拼接匹配避免因为斜杠/反斜杠导致路径拼接问题。单个文件读取异常时打印日志并继续不会因为一个坏文件中断整批任务。合并时只写入一次表头避免总表里出现几十次重复表头。判断空行时使用any(str(v).strip() for v in row_data)可以避免 Excel 尾部残留大量空行导致总表行数虚高。批量任务的通用建议是每次运行前先备份源文件输出到独立目录运行中打印处理进度运行结束后人工抽检前几行和总行数。只要做到这三点绝大多数批量场景都能稳定交付。8. 资源占用与性能观察xlrd 和 xlwt 都是轻量级库没有 GUI不依赖 Excel 进程因此常规文件处理时的 CPU 和内存占用都不会很高。但处理大量文件或超大表格时性能依然值得关注。第一个观察点是读取时的内存占用。sheet.row_values(row_index)会把一整行数据转成 Python 列表几十万行数据一次性存到字典或二维列表里内存消耗会快速上升。实际脚本里建议按“读取一行、处理一行、释放一行”的方式编写不要为了图方便把整个工作簿所有 Sheet 全部载入。上面第 4 节中的读取函数把所有 Sheet 读进了列表那只是为了演示方便真实处理大文件时需谨慎使用。可以用range(sheet.nrows)循环逐行读取处理完一行后丢弃该行引用。观察资源占用的方法很简单。在 Jupyter 里可以用%timeit统计单段代码耗时在命令行脚本里可以打印开始时间和结束时间或借助 Python 自带的时间模块记录处理耗时import time start time.time() # 执行读取或写入操作 print(耗时, time.time() - start, 秒)如果需要观察进程内存Windows 任务管理器可以看 python.exe 的内存macOS 和 Linux 可以使用top或ps。正常情况下几十 MB 的.xls文件处理起来不会出现离谱占用但如果文件很大最有效的优化不是死调 xlrd而是换用.xlsx方案或直接转成 CSV 再处理。第二个观察点是循环写入的性能。xlwt 在保存文件时会一次性把整个.xls内容写入磁盘因此在循环里频繁调用save()是低效的。最佳策略是先在内存中把所有单元格写完后最后只调用一次save()。批量汇总数据时如果数据量达到几万行内存中先构造二维列表再写入整体速度通常比每读一行就保存一次快很多。第三个观察点是磁盘输出。写入.xls文件后如果文件正被 Excel 打开再次运行脚本调用save()会报“文件被占用”类错误。自动化任务里这类原因非常常见因为用户习惯开着 Excel 检查输出文件。遇到这种情况先关闭 Excel 中对应的.xls文件再重新执行脚本即可。判断资源占用是否需要优化有两种直观信号。一种是程序运行时间超出你把它交给任务调度器的窗口另一种是内存占用随着处理文件数量增加而线性上涨涨到系统明显卡顿。出现这两种信号后优先检查是不是把所有历史文件内容都长期保存在列表中了。如果不确定可以在代码的关键节点打印当前行数确认数据量增长是否正常。9. Excel 自动化常见问题与排查方法问题现象可能原因排查方式解决方案ModuleNotFoundError: No module named xlrd未安装 xlrd 或安装到了其他 Python 环境执行pip show xlrd查看安装位置确认虚拟环境已激活执行pip install xlrd后重试XLRDError: Excel xlsx file; not supported用新版 xlrd 读取.xlsx文件查看文件后缀名确认是.xls还是.xlsx另存为.xls或改用 openpyxl日期列显示为数字日期单元格未正确转换或写入时未设置日期格式打印单元格ctype判断是否为日期单元格读取用xlrd.xldate_as_datetime写入时设置num_format_str单元格读取结果带.0后缀row_values()把数字读取为浮点数查看原单元格格式和值根据业务规则使用int()或Decimal()做类型转换汉字在写入后显示乱码工作簿创建时未指定 UTF-8 或在错误环境打开检查Workbook(encoding...)参数使用xlwt.Workbook(encodingutf-8)同一单元格重复写入报错源数据存在重复行或业务逻辑冲突打印关键索引查看写入路径中的循环变量优先清理重复数据确认需要覆盖时设置cell_overwrite_okTrue保存时报文件被占用输出文件已被 Excel 打开关闭 Excel 中的对应文件再运行脚本在脚本中检查进程占用给输出文件加上时间戳后缀批量处理时某个文件导致程序中断单个文件损坏或格式不标准打印文件名单独打开该文件排查捕获异常继续后续文件或单独修复坏文件pip 安装第三方库很慢或超时网络原因或默认源不稳定观察命令执行时间和错误信息更换 pip 镜像源并注意只在合规网络环境下操作读取到的单元格出现空字符串与 None 混杂Excel 空单元格边界情况打印cell.ctype判断空单元格类型根据类型统一做空值处理这些排查经验基本能覆盖日常 Excel 自动化任务的常见问题。还有一个建议不要在生产目录里直接执行测试脚本最好先在output目录或临时目录生成测试文件跑通确认逻辑后再放到真实数据目录执行。10. 最佳实践与下一步现在对 xlrd 和 xlwt 已经有完整操作路径下面可以落地到自己的自动化任务里最后这些实践经验值得额外记一下。第一个实践是保持工程目录清晰。输入文件、输出文件、脚本、虚拟环境分开存放。输入文件放data输出文件放output脚本直接在项目根目录运行。这样后续接入任务调度或交给同事使用时不会因为路径混乱翻车。第二个实践是先跑小样本。写批量汇总脚本前先复制两个小文件到data_demo目录测试运行确认表头、空行、异常数据都处理正确后再对完整目录执行。第一次处理生产数据前记得把原始文件备份一份防止误覆盖。第三个实践是处理数据时统一类型。从 Excel 读出来的数字往往是浮点数年月日可能变成数字身份信息列的文本可能因为单元格格式问题读不到完整内容。与其在业务逻辑里到处判断类型不如在读取后尽早规范成统一的内部类型比如数字统一转str或Decimal日期统一转成datetime.date。第四个实践是给批量任务加日志。脚本里至少打印正在处理的文件名、已处理行数、最终输出路径、总耗时。不要相信“程序没报错就说明处理成功”Excel 数据经常存在多空格、隐藏行、合并单元格、公式缓存值不一致等情况都是不报错但结果不符合预期的来源。手动抽检输出文件的前几行和总数是必要的 quality gate。如果你发现自己的业务越来越多地面对.xlsx文件或者需要复杂公式、图表、多级表头、数据透视表样式的输出下一步建议转向 openpyxl 或 pandas。它们对.xlsx格式支持更好openpyxl 还能控制更精细的单元格样式和图表对象。如果 Excel 文件只是一个数据中转格式最终目的是导入数据库或交付给下游也可以考虑把文件转成 CSV 处理处理更快也不会被 Excel 软件的格式问题干扰。如果是继续往“自动化操作 Excel”方向深入优先级可以参考优先级方向工具/主题高读取和写出.xlsxopenpyxl高表格数据分析pandas.read_excel中可视化图表openpyxl.chart / pandas 图表库中与数据库联动excel 导入数据库、数据库查询结果导出 Excel低老系统历史.xls维护本文 xlrd xlwt 方案中复杂字符串清洗Python 字符串方法、正则、拼音处理等xlrd 和 xlwt 虽然看起来“有些年头”但在老系统维护场景里仍然可用。遇到这类任务先把文件后缀看清楚再决定库路线不要盲目追新或死守旧版本。直接用本文的方法写一个读取脚本把 Sheet、行列数、关键单元格内容打印出来确认文件结构后后面的自动化任务就顺理成章了。
返回列表