如何用xlrd、xlwt、xlutils带完整格式复制Excel工作表?
关于使用xlrd/xlwt/xlutils实现带格式复制xls工作表的方案
可行性说明
xlrd+xlwt+xlutils组合可以实现xls文件的带格式复制,针对你需要的合并单元格、行高列宽、边框、单元格格式等需求,大部分能覆盖,但对格式的支持存在一定局限性,不像openpyxl对xlsx格式的支持那么全面。
核心实现思路
- 用xlrd打开xls文件时开启
formatting_info=True,读取原工作表的所有数据和格式信息 - 通过xlutils.copy生成可编辑的工作簿对象
- 手动补充复制xlutils默认未处理的格式细节(如合并单元格、行高列宽)
- 结合已实现的排序逻辑(按Q12单元格排序)后保存新工作簿
示例代码实现
import xlrd from xlutils.copy import copy as xl_copy import pathlib def copy_and_sort_xls(file, save_path): # 开启formatting_info=True以读取格式信息 rb = xlrd.open_workbook(file, formatting_info=True) # 生成可写入的工作簿副本 wb = xl_copy(rb) for sheet_idx in range(rb.nsheets): rs = rb.sheet_by_index(sheet_idx) ws = wb.get_sheet(sheet_idx) sheet_name = rs.name # 复制合并单元格 if rs.merged_cells: for (rlow, rhigh, clow, chigh) in rs.merged_cells: ws.write_merge(rlow, rhigh-1, clow, chigh-1, rs.cell_value(rlow, clow)) # 复制列宽 for col_idx in range(rs.ncols): col_info = rs.colinfo_map.get(col_idx) if col_info: ws.col(col_idx).width = col_info.width # 复制行高 for row_idx in range(rs.nrows): row_info = rs.rowinfo_map.get(row_idx) if row_info: ws.row(row_idx).height = row_info.height # 复制单元格格式(字体、对齐、边框、填充) for row_idx in range(rs.nrows): for col_idx in range(rs.ncols): cell_xf = rb.xf_list[rs.cell_xf_index(row_idx, col_idx)] ws.write(row_idx, col_idx, rs.cell_value(row_idx, col_idx), style=cell_xf) # 插入你的排序逻辑(按Q12单元格,对应xlrd索引为行11、列16) # 示例:sort_key = rs.cell_value(11, 16) # 执行排序操作... # 保存新文件 new_name = pathlib.Path(file).name wb.save(f"{save_path}/sorted_{new_name}")
关键注意事项
- xlrd仅支持
.xls格式,不兼容.xlsx;若需处理xlsx文件,建议优化现有openpyxl代码 - 格式支持限制:条件格式、图表、宏等复杂元素无法通过xlutils复制,若原文件包含此类内容需调整方案
- 排序时需同步格式:排序后重新写入单元格时,要确保对应单元格的格式也同步复制,避免格式丢失
- 性能优势:xlrd/xlwt的底层实现更轻量化,处理大量数据时速度通常优于openpyxl
优化openpyxl的备选方案
若不想切换工具链,可通过以下方式提升现有openpyxl代码速度:
- 采用只读模式读取原文件:
openpyxl.load_workbook(file, read_only=True) - 批量处理数据,减少逐单元格循环的开销
- 跳过空单元格的格式复制,仅处理有数据或自定义格式的单元格
内容的提问来源于stack exchange,提问作者kayotin
相关产品推荐
相关产品推荐

