python处理excel总结

工作中,大家经常会使用excel去处理数据以及展示,但是对于部分工作我们可以借助程序帮忙实现,达到高效解决问题的效果,比如将接口返回的json解析并保存结果到excel中,按一定规律处理excel中的数据然后写入到新的excel文件中,汇总来自多个文件的内容到一个excel中,等等。
平时在工作中遇到比较繁琐的数据需要写入到excel中,除非excel的内置公式可以处理,我会第一时间想到使用python处理。在这个过程中,研究并尝试了一些工具,闲着没事,我整理并记录下来。



各个工具对比

  XlsxWriter xlrd&xlwt&xlutils OpenPyXL Microsoft Excel API
介绍 可以创建和写Excel 2007+ XLSX文件 xlrd、xlwt、xlutils三大模块分别提供读、写和其他功能 可以读、写Excel 2007+ /xlsm/xltx/xltm文件 直接通过COM组件与Microsoft Excel进程通信调用各种功能实现对excel文件操作
修改 ⚠️
.xls
.xlsx
      xlrd: 0.8.0+ √

    * xlwt:✘
大文件
功能 一般 超强
速度 超慢

|系统|无限制|无限制|无限制|Windows + excel|

|使用场景|* 需要创建xlsx文件
* 不需要读取已有文件
* 需要实现比较复杂的功能
* 数据量可能会比较大
* 需要跨平台|* 需要读取xls或者xlsx文件
* 要生成xls文件
* 需要对文件处理的功能不太复杂
* 需要跨平台|* 需要处理xlsx文件
* 需要修改已有文件或者在写入过程中不断修改
* 需要对文件处理的功能比较复杂
* 数据量可能会很大
* 需要跨平台|* 需要处理各种文件格式
* 需要用到特别复杂功能
* 在修改文件时不希望对原有信息造成任何意外破坏
* 数据量很小,或者愿意等待
* 仅在Windows中使用|

一、XlsxWriter

XlsxWriter是我最终选择的用于写操作的工具。顾名思义,它只能用来写文件。
这应该是个比较新的项目,在GitHub上看它最早的提交是在2013年1月份。

其官方文档中宣称它支持(See the full documentation at: https://xlsxwriter.readthedocs.io):

  • 100% compatible Excel XLSX files.
  • Full formatting.
  • Merged cells.
  • Defined names.
  • Charts.
  • Autofilters.
  • Data validation and drop down lists.
  • Conditional formatting.
  • Worksheet PNG/JPEG images.
  • Rich multi-format strings.
  • Cell comments.
  • Memory optimisation mode for writing large files.

优点

  • 功能比较强
    相对而言,这是除Excel自身之外功能最强的工具了。比如我就用到了它提供的:字体设置、前景色背景色、border设置、视图缩放(zoom)、单元格合并、autofilter、freeze panes、公式、data validation、单元格注释、行高和列宽设置等等。
    最让我惊奇的是,用它生成的带有单元格注释的Excel文件,不论是Excel 2007还是Excel 2013都可正常打开。
  • 支持大文件写入
    如果数据量非常大,可以启用constant_memory,这是一种顺序写入模式,得到一行数据就立刻写入一行,而不会把所有的数据都保持在内存中。

缺点

  • 不支持读取和修改
    作者并没有打算做一个XlsxReader来提供读取操作。不能读取,也就无从修改了。它只能用来创建新的文件。我是利用xlrd把需要的信息读入后,用XlsxWriter创建全新的文件。
    另外,即使是创建到一半Excel文件,也是无法读取已经创建出来的内容的(信息应该在,但是并没有相应的接口)。因为它的主要方法是write而不是set。当你在某个单元格写入数据后,除非你自己保存了相关的内容,否则还是没有办法读出已经写入的信息。从这个角度看,你无法做到读出->修改->写回,只能是写入->写入->写入。
  • 不支持XLS文件
    XLS是Office 2013或更早版本所使用的格式,是一种二进制格式的文件。XLSX则是用一系列XML文件组成的(最后的X代表了XML)一个压缩包。如果非要创建低版本的XLS文件,就请移步xlwt吧。
  • 暂时不支持透视表(Pivot Table)
    透视表是非常麻烦的东西,除了自身复杂的结构外,还需要一套数据缓存。

举例

  1. import xlsxwriter
  2. # Create an new Excel file and add a worksheet.
  3. workbook = xlsxwriter.Workbook('demo.xlsx')
  4. worksheet = workbook.add_worksheet()
  5. # Widen the first column to make the text clearer.
  6. worksheet.set_column('A:A', 20)
  7. # Add a bold format to use to highlight cells.
  8. bold = workbook.add_format({'bold': True})
  9. # Write some simple text.
  10. worksheet.write('A1', 'Hello')
  11. # Text with formatting.
  12. worksheet.write('A2', 'World', bold)
  13. # Write some numbers, with row/column notation.
  14. worksheet.write(2, 0, 123) # 第二3行第1列
  15. worksheet.write(3, 0, 123.456) # 第四行第1列
  16. # Insert an image.
  17. worksheet.insert_image('B5', 'logo.png')
  18. workbook.close()

二、xlrd&xlwt&xlutils

xlrd&xlwt主要是针对Office 2013或更早版本的XLS文件格式。xlutils使用需要依赖xlrd和xlwt,扩充这两个库的功能。(更多信息请见:http://www.python-excel.org/)

优点

支持XLS格式
XlsxWriter和OpenPyXL都不支持XLS格式,从这个角度看,xlrd&xlwt仍然有一定的不可替代性。

缺点

  • 对XLSX支持比较差
    目前xlrd0.8.0+版本已经可以读取XLSX文件了,有限地支持。至于xlwt还仅仅只支持xls文件。
  • 对修改的支持比较差
    xlrd和xlwt是两个相对独立的模块,虽然xlutils提供方法帮助你把xlrd.Book对象复制到xlwt.Workbook对象,但跟XlsxWriter类似,只是提供write方法,使得你无法很容易地获取当前已经写入的数据并进行有针对性的修改。如果非要这样做,你要不断地保存,然后再用新的xlrd.Book对象读取你要的信息,还是比较麻烦的。
  • 功能很弱
    除了最基本的写入数据和公式,xlwt所提供的功能非常少(Excel 2013本身支持的功能也就很少)。对于读取也是一样的,很多信息在读入时就丢失掉了。

举例

写数据到xls文件

  1. import xlwt
  2. from datetime import datetime
  3. style0 = xlwt.easyxf('font: name Times New Roman, color-index red, bold on',
  4. num_format_str='#,##0.00')
  5. style1 = xlwt.easyxf(num_format_str='D-MMM-YY')
  6. wb = xlwt.Workbook()
  7. ws = wb.add_sheet('A Test Sheet')
  8. ws.write(0, 0, 1234.56, style0)
  9. ws.write(1, 0, datetime.now(), style1)
  10. ws.write(2, 0, "hello world")
  11. ws.write(3, 0, 1)
  12. ws.write(3, 1, 3)
  13. ws.write(3, 2, xlwt.Formula("A4+B4"))
  14. wb.save('example.xls')

读取文件内容

  1. import xlrd
  2. # 打开文件
  3. workbook = xlrd.open_workbook('example.xls')
  4. sheet2_name = workbook.sheet_names() # 获取所有sheet名称
  5. print(sheet2_name)
  6. # 根据sheet索引或者名称获取sheet内容
  7. sheet1 = workbook.sheet_by_index(0) # sheet索引从0开始
  8. # sheet1 = workbook.sheet_by_name('sheet2')
  9. # sheet1的名称,行数,列数
  10. print(sheet1.name, sheet1.nrows, sheet1.ncols)
  11. # 获取整行和整列的值(数组)
  12. rows = sheet1.row_values(2) # 获取第三行内容
  13. cols = sheet1.col_values(0) # 获取第1列内容
  14. print(rows)
  15. print(cols)
  16. # 获取单元格内容
  17. print(sheet1.cell(2, 0).value.encode('utf-8'))
  18. print(sheet1.cell_value(2, 0).encode('utf-8'))
  19. print(sheet1.row(2)[0].value.encode('utf-8'))
  20. # 获取单元格内容的数据类型
  21. print(sheet1.cell(2, 0).ctype)

输出:
['A Test Sheet']
A Test Sheet 4 3
['hello world', '', '']
[1234.56, 43262.66097222222, 'hello world', 1.0]
b'hello world'
b'hello world'
b'hello world'
1

三、OpenPyXL

OpenPyXL是比较综合的一个工具,能读能写能修改,功能还算可以但网上有人说有很大的缺陷。(更多信息请见:http://www.python-excel.org/, https://openpyxl.readthedocs.io/en/stable/index.html)

优点

  • 能读能写能修改
    OpenPyXL的工作模式跟XlsxWriter和xlwt有很大的区别,它用的是getter/setter模式。你可以随时读取某个单元格的内容,并根据其内容进行相应的修改,OpenPyXL会帮你记住每个单元格的状态。
    特别需要注意的一点:虽然它支持修改已有文件,但由于其所支持的功能有限,读入文件时会忽略掉它所不支持的内容,再写入时,这些内容就丢失了。因此使用时一定要慎重。比如下面的缺点中提到它无法读入公式,那如果你修改一个带有公式的文件,保存之后,所有的公式就都没有了。
  • 功能还算可以
    整体来讲,它所支持的功能介于XlsxWriter和xlwt之间。

缺点

  • 不支持XLS
    这件事情只能让xlrd和xlwt去做。
  • 不支持读取公式
    这其实是个不太简单的事情,虽然我没尝试过,但相信xlrd也做不好这件事。
    Excel的单元格如果是一个公式,它内部会同时保存公式本身和运算结果的缓存。用OpenPyXL读取单元格内容,它不会告诉你这个单元格的公式是什么,甚至不会告诉你这个单元格存的是公式,它只会拿到这个缓存的运算结果。我本来想利用它判别单元格是不是用了公式,然后做出不同的处理。结果遇到了这个问题,最后只好采取了其他变通的方式去做。

举例

简单例子

  1. from openpyxl import Workbook
  2. wb = Workbook()
  3. # grab the active worksheet
  4. ws = wb.active
  5. # Data can be assigned directly to cells
  6. ws['A1'] = 42
  7. # Rows can also be appended
  8. ws.append([1, 2, 3])
  9. # Python types will automatically be converted
  10. import datetime
  11. ws['A2'] = datetime.datetime.now()
  12. # Save the file
  13. wb.save("sample.xlsx")

写入数据到文件

  1. from openpyxl import Workbook
  2. from openpyxl.compat import range
  3. from openpyxl.utils import get_column_letter
  4. wb = Workbook()
  5. dest_filename = 'book.xlsx'
  6. ws1 = wb.active
  7. ws1.title = "range names"
  8. for row in range(1, 5):
  9. ws1.append(range(0, 10))
  10. ws2 = wb.create_sheet(title="Pi")
  11. ws2['F5'] = 3.14
  12. ws3 = wb.create_sheet(title="Data")
  13. for row in range(2, 10):
  14. for col in range(27, 40):
  15. _ = ws3.cell(column=col, row=row, value="{0}".format(get_column_letter(col)))
  16. wb.save(filename=dest_filename)

读取数据

  1. from openpyxl import load_workbook
  2. wb = load_workbook(filename='book.xlsx')
  3. sheet_ranges = wb['range names']
  4. print(sheet_ranges['D2'].value)

输出:
3

四、Microsoft Excel API

大部分Windows环境的开发人员都会选择Microsoft Excel API。实际上不仅仅是Python,几乎各种语言都有相应的方法使用它,因为核心的逻辑完全是由Microsft Excel自身提供的。语言相关的部分只是负责跟Windows的COM组件进行通信。
在Python中首先需要安装Python for Windows extensions(pywin32),具体的文档可以查阅Win32 ModulesPython COM
当然你还必须要安装某一个版本的Microsoft Office Excel,它内部的DLL负责实际的操作。

优点

  • 最大的优点:强大无极限
    因为直接与Excel进程通信,你可以做任何在Excel里可以做的事情。
  • 文档丰富
    MSDN上的文档绝对是世界上最优秀的文档。没有之一。
  • 调试方便
    你完全可以直接在Excel里面用宏先调试你想要的效果。甚至如果你不清楚怎么用程序实现某个操作,你可以通过宏录制的方法得到该操作的处理代码。

缺点

  • 致命的缺点:慢到死
    因为需要与Excel进程通信,其效率是非常低的。
    如果让Excel窗口可见,随着程序的运行,你可以看到每一句程序所带来的变化,单元格的内容一个一个地改变。如果要写入的数据很多,那速度是无法忍受的。
  • 平台限制
    目前还没有发现可以在非Windows系统使用它的方法。
    另外,基于它的程序能做什么事情,很大程度上依赖于当前系统所安装的Excel版本。不同的版本在功能上有很大的差异,API也会有差异。用起来会比较麻烦。
  • Excel自身bug导致的问题
    和Python没有任何关系,可以完全在Excel中手动复现。在Excel 2007中随便创建一个文件,给某个单元格添加注释,保存。换台电脑,用Excel 2013打开,就会报错,然后注释就消失了。同样如果你的程序在一台装有Excel 2007的机器上创建一个带有注释的Excel文件,把这个文件拿到Excel 2013中打开也会报错,也看不到注释。反过来也一样。

五、pyexcel工具

一个包装器,他提供了一个接口去读、写、操作数据。通过该包装器可以根据场景下载安装不同的插件(比如前面提到的:xlrd、xlwt、OpenPyXL、XlsxWriter),然后使用该包装器可以使用相同的一套api去操作excel。

不过该工具如果是公司使用需要支付一定费用,大概$10,个人使用的话是免费的。(详情可参见:https://pypi.org/project/pyexcel/)。

可用插件如下:

举例(以xls文件为例,xlsx文件下载相应插件即可,api一致)

保存数据

  1. import pyexcel as p # make sure you had pyexcel-xls installed
  2. a_list_of_dictionaries = [
  3. {
  4. "Name": 'Adam',
  5. "Age": 28
  6. },
  7. {
  8. "Name": 'Beatrice',
  9. "Age": 29
  10. },
  11. {
  12. "Name": 'Ceri',
  13. "Age": 30
  14. },
  15. {
  16. "Name": 'Dean',
  17. "Age": 26
  18. }
  19. ]
  20. pyexcel.save_as(records=a_list_of_dictionaries, dest_file_name="your_file.xls")

读取数据

  1. import pyexcel as p # make sure you had pyexcel-xls installed
  2. records = p.iget_records(file_name="your_file.xls")
  3. for record in records:
  4. print("%s is aged at %d" % (record['Name'], record['Age']))
  5. p.free_resources()

输出:
Adam is aged at 28
Beatrice is aged at 29
Ceri is aged at 30
Dean is aged at 26

猜你喜欢

转载自www.cnblogs.com/paul-liang/p/9187503.html