欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python与Excle交互应用实践(openpyxl与xlwings裤)

程序员文章站 2024-02-23 18:40:22
...

0x00问题背景

前段时间在工作中遇到了一个需求,简单介绍就是需要在过去6个月中某市每天不同蔬菜的菜价中查找公司所采购特定蔬菜对应那天的价格,计算差值,看似简单但数据量庞大,光录入就花了不少时间,耗费了大家不少精力,当时想到用python解决这个问题,但是时间紧迫没有认真研究这几个交互Excle的库,依照当时搜索的部分资料和自己亲身的使用来看,主要有:

xlwt
xlrd
xlutils
xlwings
openpyxl

这几个库各有好处,也各有缺陷,综合来看,上次直接使用了openpyxl是一个比较正确的选择。

0x01python交互库介绍

关于这几个库的介绍网上很多了,安装也都非常简单,可以按照pip install XXX的方式来安装,我将在这次问题中遇到的几个重要方面做记录:

xlrd&&xlwt&&xlutils
  • 首先搜到的就是两个最简单的库xlwt和xlrd,两个库功能分开,一个负责读另一个负责写,但美中不足的就是只能支持对xls的写,所以不满足我们的使用需求,
import xlrd
import xlwt
from xlutils.copy import copy
book = xlrd.open_workbook() #打开一个表格文件,句柄传给book
count = book.sheets()#获取sheets对象,这时使用len()获得sheet对象个数
count = book.nsheets #共有多少个sheet

获取一个sheet有两种方式,通过名字或通过编号,对应方法为book.sheet_by_index(0)book.sheet_by_name,获得sheet对象后读取特定单元格值cell_value(0,10),括号内为行列值,均从0开始计。且同类型的单元格数值可以直接比较。

sheet1.nrows #获取行数,用来遍历

xlwt创建一个新的工作表并对其进行修改,虽然修改的功能强大,但不能对xlsx修改,也不能在已有的表中做修改,所以还是有很多的限制的。而使用了xlutils导入的copy方法复制一个新的表格再利用xlwt对其修改时,操作后发现生成的xlsx不可读了,文件损坏,也饶了不少弯路。

xlwings
  • 大家都说xlwings是最强大的excle交互库,包含了读写的全部功能,使用也比较简单,但是比起其他的库来说,操作的方式好像有呢么一丢丢不同,同样我们也了解一下打开文件、获取sheet、获取行数、获取单元格值这几个基本操作。
    导入库运行后发现还需要依赖库win32api
    1.可以使用pip install pypiwin32解决问题

    2.在https://sourceforge.net/projects/pywin32中下载对应自己python版本的win32包。安装前关闭占用python的进程,一路next。
import xlwings
book = xlwings.Book(strName) #
sheet1 = book.sheets[0]  #选择一个sheet对象,编号为0
sheet2 = book.sheet('9.17') #选择一个sheet对象,名称为9.17
print sheet1[0,0].value  #读取0,0单元格的内容以index形式索引
print sheet1.range('a1').value #以单元格名称为索引读取

读取简单,对应的写入也非常简单

sheet1[0,0].value = "XXX"
sheet1.range('a1').value = "XXX"

获取行列数,用来遍历

nrow = sheet1.api.UsedRange.Rows.count
ncol = sheet1.api.UsedRange.Columns.count

基本也只用到这些操作了,下面着重讲讲我所用的openpyxl。

openpyxl

这个库是在实践中所用的库,使用简单,功能强大,与xlwings很难比较孰强孰弱,都能满足我们的时间需求。

import openpyxl
work = openpyxl.load_workbook('Test.xlsx')  #打开一个工作簿
sheet_names = work.get_sheet_names() #获得sheet_name的数组
sheet1 = work.get_sheet_by_name('9.99') #以sheet名称获取sheet对象
sheet2 = work.get_sheet_by_name(sheet_names[0]) #获取名称数组后按索引,可以在不知道名称的情况下遍历
print sheet1.cell(1,1).value #需要注意的是单元格从1,1开始,而不是0
sheet1.cell(1,1).value = '111' #写单元格
print sheet1.max_row #总行数
print sheet1.max_column  #总列数
work.save('001T_ok.xlsx')#保存更名

0x02问题分析

接触这个任务时有这个想法是第一次将python运用到实际,想要解放生产力,所以还是遇到了很多的小问题,记录一下以备不时之需,整个实践可以细化为几个部分,这也是在遇到问题后的分析思路。

第一,操作方面:对需要修改表格的操作,包括打开,遍历,读写,然后保存。
第二,逻辑方面:首先从第一项菜品开始,在本市对应日期的所有菜品中查找,找到对应价格,填写上去;>其次是有名称不统一的情况出现,例如“大葱”,“葱”、“姜”,“生姜”等同类菜品的不同叫法。
第三,编码方面:名称均为汉字 ,分为打印输出的编码问题和日期比较的编码问题。
第四,库对文件格式的支持问题:选择xlwings和openpyxl这两个库来完成实践。

0x03代码实现

细化为四个问题后开始代码的实现,操作方面上文已经提到。
1.名称不一致问题又建了一个名称的更新表 Csql.xlsx,可以让查找不到的菜品在新的xlsx中替换名字查询,还可以随时追加新的内容,这时就再次遍历表就可以了。
2.日期问题在每个录入的表中做标记,使用excle中内容来互相比较,避免格式问题。
3.查询不到的使用try跳过。
4.使用flag位标记。
实现的代码也很简单,主要是记录一下使用的库和基本的操作。