使用Python工具包Openpyxl进行Excel处理
目录
1 背景
前两天家里人有一个工作要做:把一张从系统里导出来的excel表分割成多个长度不统一的部分,而且分割以后需要提取里面的姓名等分别分发给对应的人。观察表格以后我发现每一个分割部分都有重复的标题,而且需要提取的姓名等信息的位置相对标题是固定的,于是想到写代码来识别标题进行分割,然后再提取姓名分别导出。
先是查到excel自带的VBA,但是感觉不太习惯这个代码风格,又查到在python里用pandas,xlrd,openpyxl等可以处理excel,于是进行尝试。最后选定了调用比较方便、交互很人性化的openpyxl,大概花了两个多小时解决了问题,把每个人的表格都分别导出,而且姓名等信息作为文件名,结果还不错。
下面就稍微总结一下。
2 相关资料
看相关资料前我建议我们先把excel的结构回顾一下,这样操作起来会更得心应手。
3 Excel结构
之所以说openpyxl交互人性化是因为它的结构就是根据excel的结构进行设计的。首先来回顾一下excel:
图中是一个新建excel文件打开后的样子,我们可以把它想象成一本账本:
每一个excel文件是一个workbook(一本账本)
每一个workbook里可以创建多个worksheet(在每一本账本里有很多页)
每一个worksheet里有很多行rows和很多列columns,行标用数字表示,列标用字母表示
行与列的交叉处是一个单元格cell(一条记账),每个cell有很多的属性:
编号:用cell所处行列唯一表示,即column+row
值:每个cell中记录的内容
数据类型:字符、数字、日期等
样式:底色、字体等
4 Openpyxl的总结
4.1 搭建环境
因为阅读的对象可能不是专业编程人员,所以介绍一下基本环境的搭建,搭环境一共三步:
第一步装环境的时候可以顺便安装一个IDE(集成开发环境),比如Pycharm,Anaconda等,这样安装工具包可以直接在IDE里进行。
4.2 导入工具包
首先在python文件中导入openpyxl进行使用,导入workbook对于大多情况已经够用了
import openpyxl as xl
from openpyxl import workbook
4.3 读取文件
将.xlsx文件转化为workbook变量wb,并提取workbook中的第一个sheet存到变量ws,这样可以对worksheet做很多我们在excel里的操作了
filename = "full/path/of/xlsx"
# load file
wb = xl.load_workbook(filename)
# get the first sheet
ws = wb1.worksheets[0]
4.4 按行读取,按列读取
用worksheet的iter_rows()和iter_cols()方法可以读取出每一行/列,再在每一行/列中循环读取就可以获取每一个cell,这时候print出来的是该cell的编号信息。
# read by row
for row in ws.iter_rows():
for cell in row:
print(cell)
# read by column
for col in ws.iter_cols():
for cell in col:
print(cell)
4.5 读取值
获取cell后只用调用cell的方法_value就可以获取cell中的内容
# read by row
for row in ws.iter_rows():
for cell in row:
print(cell._value)
# read by column
for col in ws.iter_cols():
for cell in col:
print(cell._value)
4.6 访问和修改cell
可以直接通过给出序号的方式直接访问和编辑单元格,序号的规范是列号(字母)+行号(数字),如"A1"
# c1 get A1
c1 = ws['A1']
# c2 get A1
c2 = ws.cell(row=1, column=1)
# eidt A2
ws['A2'] = 1
4.7 合并单元格
合并单元格也是excel中非常常见的操作,在excel中只需要拖选中要合并的框然后点击合并即可;openpyxl同理,拖动的步骤由切片完成,切片方法是'起始cell编号:终止cell编号 ',合并调用的是worksheet的函数merge_cells
# merge A1 to F1
ws.merge_cells('A1:F1')
4.8 存储
存储的对象是workbook,当对worksheet进行操作后直接存储其所属的workbook,存储的格式仍然是xlsx
filename_save = "path/of/save"
wb.save(filename_save)
4.9 其它
还有两点想要补充说明一下:
4.9.1 文件格式
目前Openpyxl可以读取的是office2003以后的excel格式即.xlsx,因此如果表格是旧格式.xls的需要将文件另存一下,切记不要直接修改后缀名,可能导致文件不可用。
4.9.2 拷贝值和样式
这个问题是我在做的时候遇到的,当从一个worksheet拷贝value到另一个worksheet时,其样式不会跟随拷贝。如果要连带样式一起拷贝需要加入如下语句:
from copy import copy
# copy 1 to 10
start = 1
end = 10
# max column
mc = ws.max_column
#
for i in range(start, end + 1):
for j in range(1, mc + 1):
# reading cell value from source excel file
source_cell = worksheet.cell(row=i, column=j)
# writing the read value to destination excel file
target_cell = ws_save.cell(row=i-start+1, column=j)
# copy style, comment and hyperlink
if source_cell.has_style:
target_cell._style = copy(source_cell._style)
target_cell.font = copy(source_cell.font)
target_cell.border = copy(source_cell.border)
target_cell.fill = copy(source_cell.fill)
target_cell.number_format = copy(source_cell.number_format)
target_cell.protection = copy(source_cell.protection)
target_cell.alignment = copy(source_cell.alignment)
if source_cell.hyperlink:
target_cell._hyperlink = copy(source_cell.hyperlink)
if source_cell.comment:
target_cell.comment = copy(source_cell.comment)
# copy value
target_cell.value = source_cell._value
target_cell.data_type = source_cell.data_type
请注意的是cell无法拷贝列宽和行高,列宽行高要通过worksheet的column_dimensions和row_dimensions属性来修改,可以参考这篇文章,另外可以查到一些自适应宽高的方法。
欢迎交流和指正。