前文介绍了openpyxl的基本用法,相信大家对这个库已经有了基本的认识,前面也提到了,openpyxl对excel软件环境不具有依赖,这更利于我们在web中使用它。这一篇着重对文件保存和交互进行剖析。
保存文件
Openpyxl的基本保存操作是使用save方法,将其存为文件,我们只需要为其提供一个文件名,就可以保存。
wb.save(123.xlsx')
对于Web网站来说,我们并不需要这个文件,我们需要的其实只是这个文件的二进制,比如django中有个字段类型是BinaryField,专门存储二进制,结合python自带的 zlib库进行压缩,存储起来并不需要很大的空间。
openpyxl的save方法中并没有将其保存为二进制的功能
但我们可以借助临时文件类进行转换。
此时的stream就是二进制,可以将其进行一番操作,存到数据库里面,或者通过响应返回给web请求的用户。
因为windows中临时文件不能在没被关闭的情况下又被读取,所以需要有delete=False参数,来保证文件不会在上下文管理器处理完后清理掉。只需要加上一个os.remove(tmp.name) ,即可清理临时文件,linux不受此限制。
如果你打印tmp.name的话,会是一个比较长的临时文件名称,且每次都不一样。
Windows C:\Users\ADMINI~1\AppData\Local\Temp\tmp17raove2
Ubuntu Linux /tmp/tmppj6yhzjr
读取文件
使用load_workbook函数来读取文件。常规的方式是读取一个文件名
wb_new = load_workbook(‘123.xlsx’)
对于已经存储的二进制数据stream,openpyxl依然借助NamedTemporaryFile类来实现读取。
with NamedTemporaryFile() as tmp2:
tmp2.write(stream)
wb_new = load_workbook(tmp2)
wb_new.save('222.xlsx')
在这种命名临时文件中,tmp2就相当于我们常用的with open(xxx) as f 中的f。load_workbook函数源代码中已经指出,这个文件是可以读一个二进制句柄的,所以这里给它传的是一个tmp2,而并非tmp2.name,后再保存的文件也可以正常打开。
如果非要读文件名的话,需要调整为如下:
with NamedTemporaryFile(suffix='.xlsx',delete=False) as tmp2:
print(tmp2.name)
tmp2.write(stream)
wb_new = load_workbook(tmp2.name)
wb_new.save('222.xlsx')
其中windows依然要考虑文件影响,还需要加文件名后缀,确保能被读取。
题外话
如果只需要读取文件的话,使用xlrd可以直接读取二进制,对于xlsx文件,需要限制版本为1.2.0,更新的版本反而不能读取,不知道是不是因为版权问题被限制住了。而且随着python版本更新,python3.9开始这个1.2.0版库直接就不能用了,需要依照网上一些教程更改源代码才行。
xlrd使用open_workbook函数来读取文件。
通过观察源代码可以得出,使用file_contents参数,可以直接读二进制数据(不是前面的文件操作句柄)。