Python操作Excel工作簿的示例代码(*.xlsx)
本文对比了Python中处理Excel文件的几个主要库:xlrd、xlwt、xlutils、openpyxl和xlwings。重点介绍了功能更完善的xlwings库,涵盖创建、读写、行列增删及单元格格式设置。同时分析了.xls与.xlsx格式差异及文件体积问题,提供了各库的支持情况对比表,帮助开发者根据需求选择合适的库。
前言与测试环境
前言
Excel作为广泛使用的桌面数据处理工具,渗透于各行各业,在编程领域同样常见。Python生态中处理Excel格式文件的库众多,包括xlrd、xlwt、xlutils、openpyxl和xlwings等。然而,各库的操作机制存在差异,部分库在处理特定场景时具有局限性。
下文将对比上述几个库的差异,并重点记录xlwings库的使用心得。目前看来,xlwings是个人觉得较为便捷的库;其他库在使用过程中常遇到各类问题,不过在特定场景下仍具有不错的适用性。
Excel文件格式差异
EXCEL文件格式简介
Excel作为电子表格软件,支持多种保存格式,其中“Excel工作簿(*.xlsx)”和“Excel 97-2003工作簿(*.xls)”最为常用。通常认为,.xls格式是03版Excel之前常用的格式,而.xlsx则是03版之后,一般指07版Excel之后常用的格式。
大多数Excel程序均支持打开和编辑上述两种格式,并支持相互转换存储。不过,建议在没有特殊要求的情况下优先使用新版格式。一方面,新版稳定版本可能修复了旧版的某些Bug,另一方面也带来了性能优化。
在撰写本文前,笔者发现一个空白的.xlsx格式文件大小约为7KB,而空白的.xls格式文件大小约为24KB。当写入相同的汉字内容后,两个文件分别变为10KB和30KB,体积差异明显。此外,将.xlsx文件另存为.xls格式时,系统会弹出兼容性提示,警告部分设置可能丢失。因此,建议尽量使用新版本格式。
测试环境说明
由于应用程序和Python库不断迭代,不同版本可能存在差异。以下列出尽可能详细的版本号,供参考:
- 操作系统: Windows 10 随意版
- Python: 3.75
- xlrd: 1.2.0
- xlwt: 1.3.0
- xlutils: 2.0.0
- openpyxl: 3.0.3
- xlwings: 0.18.0
以上各程序库在使用前需自行安装,此处不再赘述安装方法。但可提供一个快速安装的镜像源命令,使用 pip install -i https://pypi.doubanio.com/simple 库名 可以尽可能解决下载安装缓慢的问题。
Python操作Excel的三种方案
Excel具体操作方法
Python操作Excel的方法大致可分为三组:第一组配合使用xlrd、xlwt、xlutils;第二组使用openpyxl库;第三组使用xlwings库。本文重点总结xlwings的使用,对其他两组仅作简要了解。
xlrd、xlwt、xlutils库
xlrd、xlwt、xlutils库的使用
这组库的名称形象地反映了功能:一个负责读,一个负责写,加上一个小工具,组合起来即可对Excel进行操作。下面通过一个小练习演示:打开一个Excel文件,修改第一个单元格的值,再另存为新文件。代码如下:
import xlrd
import xlwt
import xlutils.copy
def save_as_new_file(file_name, new_file_name):
# 打开Excel文件
rb = xlrd.open_workbook(file_name)
# 创建一个可写入的副本
wb = xlutils.copy.copy(rb)
# 获得第一个sheet页签
ws = wb.get_sheet(0)
# 第一个单元格写入测试值
ws.write(0, 0, 'test value')
# 另存为一个新文件
wb.save(new_file_name)
上述代码在操作.xlsx或.xls文件时均不会报错,但另存为.xlsx格式的文件可能无法打开;同时,正常存储的.xls文件打开后格式可能会丢失。解决方法是修改打开文件的参数,代码如下:
rb = xlrd.open_workbook(file_name, formatting_info=True)
其中参数formatting_info=True表示打开Excel时保留原有格式,但这仅针对.xls格式文件。对于.xlsx格式文件,直接抛出异常raise NotImplementedError("formatting_info=True not yet implemented")。由于无法处理.xlsx格式的格式保留,笔者暂未使用这几个库操作Excel。
此外需注意,这几个库在操作单元格时,行和列的索引均从0开始。
openpyxl库
openpyxl库的使用
该库主要用于操作.xlsx格式文件,无法打开.xls格式文件,会报错openpyxl does not support the old .xls file format。但可以存储为.xls格式,再次打开时会有格式不匹配的警告,不过基础数据仍在。因此,若需处理.xls格式,仍建议优先使用其他库或注意此限制。
创建新文件的常见用法如下:
from openpyxl import Workbook
from openpyxl import load_workbook
from openpyxl.styles import Font, Fill, Alignment, PatternFill
def write_new_excel(file_name):
# 创建一个excel文档
wb = Workbook()
# 获得当前激活的sheet对象
ws = wb.active
# 给A2单元格赋值
ws['A2'] = 'This is A2 cell'
# 一行添加多列数据
ws.append([1, 2, 'hello'])
# 添加新的sheet
ws = wb.create_sheet(title='NewInfo',index=0)
# 设置单元格的值
ws['A1'] = 'This is new sheet'
# 保存excel
wb.save(file_name)
读取并改写原有文件的常见用法如下:
def read_update_excel(file_name):
# 加载Excel表
wb = load_workbook(file_name)
# 打印sheet数量
print('sheet count:', len(wb.sheetnames))
# 打印所有sheet名字
print('sheet name list:', wb.sheetnames)
# 获取第一个sheet对象
ws = wb[wb.sheetnames[0]]
# 打印sheet表行数和列数
print('rows count:', ws.max_row, 'cols count:', ws.max_column)
# 更新单元格A1的内容
ws['A1'] = 'this is A1'
# 在第二行位置插入一行
ws.insert_rows(2)
# 删除第五行
ws.delete_rows(5)
# 获取单元格对象,对应B2单元格
cell = ws.cell(2,2)
# 设置单元格内容
cell.value = 'this is B2'
# 修改字体格式为粗体
cell.font = Font(bold=True)
# 修改单元格格式
cell.fill = PatternFill("solid", fgColor="F0CDCD")
# 保存原文件或另存一个文件
wb.save(file_name)
使用该库时,存储带有样式的数据未发现明显问题。但当加入计算公式后,另存为文件时文件尺寸明显变小,尽管数据和公式本身看似正常。
有资料指出该库处理速度较慢,因笔者处理的文件较小,未明显察觉此问题。另一个问题是Excel中的宏会全部丢失。测试中确实发现宏丢失,这与文件格式有关:保存宏需存储为.xlsm格式。但openpyxl主要用于操作.xlsx文件,存储时会导致宏丢失;强行存储为.xlsm格式会导致最终文件无法打开。
此外,该库在操作单元格时,行和列的索引从1开始。
xlwings库详解
xlwings库的使用
使用xlwings前需创建一个App对象,通过该App对象来操作Excel,这类似于将Excel的各种操作API封装在一起,再通过App对象调用。若在创建App时不设置隐藏参数,会正常打开Excel程序界面。
使用xlwings的基本方式如下:
import xlwings as xw
# 设置Excel程序不可见
app = xw.App(visible=False, add_book=False)
# 通过 app 操作 Excel文件
# app.bala bala bala .....
# app.bala bala bala .....
# 优雅的退出
app.quit()
创建一个新的Excel文件并写入数据的示例代码如下:
def write_new_excel(app, file_name):
# 创建新的 Excel 表
wb = app.books.add()
# 获取当前活动的sheet
ws = wb.sheets.active
# 初始化二维区域的值
arr_data = [[1, 2, 3], [4, 5, 6], [7, 8, 'end']]
# 设置到新建的Excel中
ws.range('A1:B3').value=arr_data
# 设置单独一个单元格的值
ws.range('A4').value='this is A4'
# 设置单独一个单元格的值
ws[3,1].value='this is B4'
# 保存Excel文件
wb.save(file_name)
wb.close()
需要注意的是,通过行索引和列索引修改单元格时,起始索引为0。
读入已有Excel表格并修改的示例代码如下:
def read_update_excel(app, file_name):
# 加载已有的表格
load_wb = app.books.open(file_name)
# 获取Excel表中第一个sheet
load_ws = load_wb.sheets[0]
# 打印sheet的名字
print(load_ws.name)
# 根据sheet名字获取sheet对象
load_ws = load_wb.sheets[load_ws.name]
# 获取当前活动的sheet
load_ws = load_wb.sheets.active
# 获取存在数据的行数和列数
rows = load_ws.api.UsedRange.Rows.count
cols = load_ws.api.UsedRange.Columns.count
print('rows count:', rows, 'cols count:', cols)
# 修改指定单元格数据(A1单元格)
load_ws[0,0].value='this is A1'
# 有空行或空列时获取准确的行列数量
print(load_ws.used_range.shape)
# 从A1单元格开始扩展到非空行空列,最后的行数和列数
print((load_ws.range('A1').expand().last_cell.row,
load_ws.range('A1').expand().last_cell.column))
# 从A1单元格开始扩展到非空行空列,最后的行数和列数
print((load_ws.range('A1').expand().last_cell.row,
load_ws.range('A1').expand().last_cell.column))
# 从A1单元格开始扩展到非空行空列,最后形状
print(load_ws.range(1,1).expand().shape)
# 从A1单元格开始扩展到非空行空列,最后的行数和列数
print((load_ws.range('A1').expand('table').rows.count,
load_ws.range('A1').expand('table').columns.count))
# 保存修改后的Excel
load_wb.save(file_name)
load_wb.close()
Excel中增加或删除行和列的示例代码如下:
def insert_delete_rowscols(app, file_name):
# 加载已有的表格
load_wb = app.books.open(file_name)
# 获取当前活动的sheet
load_ws = load_wb.sheets.active
# 从第2行开始插入4行,也就是说2-5行变成新插入的空行
load_ws.api.rows('2:5').insert
# 删除第6行和第7行
load_ws.api.rows('6:7').delete
# 插入一个单元格,实际测试效果是B列从B2开始向下移动,B2为新添加的单元格
load_ws.range('B2').api.insert
# 插入新的一列
load_ws.api.columns('B').insert
# 删除一列
load_ws.api.columns('C').delete
# 保存修改后的Excel
load_wb.save(file_name)
load_wb.close()
单元格宽高查询、设置与合并的示例代码如下:
def cell_operation(app, file_name):
# 加载已有的表格
load_wb = app.books.open(FILE_PATH_ROOT + file_name)
# 获取当前活动的sheet
load_ws = load_wb.sheets.active
# 合并单元格
load_ws.range('A2:A3').api.merge
#获取单元格
cell = xw.Range('B2')
# 打印单元格所在的行和列
print("row is:", cell.row, "col is:", cell.column)
# 打印当前格子的高度和宽度
print("cell.width:", cell.width, "cell.height:", cell.height)
# 设置当前格子的高度和宽度
cell.row_height = 32
cell.column_width = 64
# 指定单元格的高度和宽度自适应
cell.columns.autofit()
cell.rows.autofit()
# 再次打印当前格子的高度和宽度
print("cell.width:", cell.width, "cell.height:", cell.height)
# 保存修改后的Excel
load_wb.save(file_name)
load_wb.close()
库功能对比与总结
几个库的支持情况对比
尽管前文介绍了多种方法,但在实际遇到问题时仍会犹豫选择哪种方式。以下根据实验结果进行简单对比,若有不准确或错误之处,欢迎指正,笔者会尽快改正。
| 情景/库 | xlrd、xlwt、xlutils | openpyxl | xlwings |
|---|---|---|---|
| 读取.xls | 可以带有样式读取 | 不支持 | 可以读取 |
| 保存.xls | 可以带有样式保存 | 可以保存,但是提示文件扩展名不匹配,可以看到原始数据 | 可以保存,但是提示文件扩展名不匹配,可以看到原始数据 |
| 读取.xlsx | 可以读取,但没有样式 | 可以带有样式读取 | 可以带有样式读取 |
| 保存.xlsx | 保存后打不开 | 可以带有样式保存 | 可以带有样式保存 |
| 读取.xlsm | 可以读取,但没有样式和宏 | 可以读取,但没有宏 | 可以读取包含宏的表格 |
| 保存.xlsm | 保存后打不开,存成 .xls 格式宏丢失 | 保存后打不开,存成 .xls想 格式宏丢失 | 存储后宏还在 |
| 增删行和列 | 没有直接方法 | 支持 | 支持 |
| 另存后大小 | .xls 文件没有变化 | .xlsx 文件会变小 | .xls、.xlsx 文件没有变化 |
| 使用建议 | 只操作.xls文件可以考虑 | 只操作.xlsx文件可以考虑,不能带有宏 | 一个比较好的选择,使用时感觉速度稍微有点慢 |
总结
- Excel表格程序经过版本更替发生了巨大变化,出现了相同内容下.xls格式文件比.xlsx格式文件大得多的情况。
- 基于上述考虑,若能使用新版表格格式,建议放弃旧格式。
- 此外还有一个有趣的现象:包含少量数据的.xlsx格式表格,其体积有时比空表格还要小。具体原因尚不明确,恳知情的读者告知。
到此这篇关于Python操作Excel工作簿的示例代码(*.xlsx)的文章就介绍到这了,更多相关Python操作Excel工作簿内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













