openpyxl快速入门 文档翻译

165 阅读6分钟

概述

openpyxl是一个用于读写Excel 2010 xlsx/xlsm/xltx/xltm 文件的Python库。

快速入门

安装

使用pip安装openpyxl。

pip install openpyxl

注意:如果希望在openpyxl文件中包含图片(jpeg, png, bmp, ...),可以安装pillow库

pip install pillow

创建一个workbook

不需要在文件系统新建文件来入门openpyxl,只需要引用Workbook类并开始工作:

from openpyxl import Workbook
wb = Workbook()

一个被创建的workbook(工作簿文件)有至少一个worksheet(工作表)。你可以使用Workbook.active属性来获得它。

ws = wb.active

注意:默认设置是0。除非你修改它的值,否则你使用此方法会第一个worksheet

你可以使用Workbook.create_sheet()方法来创建新的worksheets。

ws1 = wb.create_sheet("Mysheet")  # 在末尾插入(默认设置)
ws2 = wb.create_sheet("Mysheet", 0)  # 在第一个位置插入
ws3 = wb.create_sheet("Mysheet", -1)  # 在倒数第二个位置插入

sheets在创建时会被自动命名。命名会按照数字顺序(Sheet, Sheet1, Sheet2, …)。你可以通过Worksheet.title属性在任何时间改变它的名字:

ws.title = 'New Title'

一旦你给一个worksheet命名,你就可以把它的名字当作一个键从workbook中提取出来:

ws3 = wb['New Title']

你可以通过Workbook.sheetname属性来查看workbook中全部worksheets的名字。

>>> print(wb.sheetnames)
['Sheet2', 'New Title', 'Sheet1']

你也可以通过循环来输出每个worksheet的名字:

for sheet in wb:
    print(sheet.title)

你也可以用Workbook.copy_worksheet()方法在同一个workbook内创建worksheets的副本:

source = wb.active
target = wb.copy_worksheet(source)

注意:只有cell(单元格)(包括values, styles, hyperlinks, comments)与某些worksheet属性(包括dimensions, format, properties)会被复制。其他workbook/worksheet的属性不会被复制,例如Images(图片)和Charts(图表)。

使用数据

访问一个cell(单元格)

现在我们知道如何得到一张worksheet,那么我们开始修改cell的内容。Cells可以利用worksheet的键值直接访问:

c = ws['A4']

这会返回位于A4的cell(单元格),如果单元格不存在则会创建一个cell。

可以直接给cell赋值:

ws['A4'] = 4

还有Worksheet.cell()方法,此方法提供了通过行和列的下标来访问cell:

d = ws.cell(row=4, column=2, value=10)

注意:当一个worksheet在内存中被创建出来,它不包含任何cells。访问一个cell时,它自身才会被创建。

警告:由于此特性,即使你没有给它们赋值,浏览cells而不是直接访问它们也会在内存中创建所有的cells。 例如:

for x in range(1, 101):
    for y in range(1, 101):
        ws.cell(row=x, column=y)

会在内存中创建100x100个无内容的cells。

访问多个cells(单元格)

可以使用给切片访问多个单元格的范围:

cell_range = ws['A1':'C2']

行和列的范围也可以用类似的方法得到:

colC = ws['C']
col_range = ws['C:D']

row10 = ws[10]
row_range = ws[5:10]

你也可以使用Worksheet.iter_rows()方法:

>>> for row in ws.iter_rows(min_row=1, max_col=3, max_row=3)
...     for cell in row:
...         print(cell)

<Cell Sheet1.A1>
<Cell Sheet1.B1>
<Cell Sheet1.C1>
<Cell Sheet1.A2>
<Cell Sheet1.B2>
<Cell Sheet1.C2>

同样Worksheet.iter_cols()方法会返回列:

>>> for col in ws.iter_cols(min_row=1, max_col=3, max_row=2):
...     for cell in col:
...         print(cell)

<Cell Sheet1.A1>
<Cell Sheet1.A2>
<Cell Sheet1.B1>
<Cell Sheet1.B2>
<Cell Sheet1.C1>
<Cell Sheet1.C2>

注意:由于性能原因,Worksheet.iter_cols()方法在read-only(只读)模式下不可用。

如果你需要迭代遍历一个文件的所有行或者列,你可以使用Worksheet.rows属性作为替代:

>>> ws = wb.active
>>> ws['C9'] = 'hello world'
>>> tuple(ws.rows)

((<Cell Sheet.A1>, <Cell Sheet.B1>, <Cell Sheet.C1>),
(<Cell Sheet.A2>, <Cell Sheet.B2>, <Cell Sheet.C2>),
(<Cell Sheet.A3>, <Cell Sheet.B3>, <Cell Sheet.C3>),
(<Cell Sheet.A4>, <Cell Sheet.B4>, <Cell Sheet.C4>),
(<Cell Sheet.A5>, <Cell Sheet.B5>, <Cell Sheet.C5>),
(<Cell Sheet.A6>, <Cell Sheet.B6>, <Cell Sheet.C6>),
(<Cell Sheet.A7>, <Cell Sheet.B7>, <Cell Sheet.C7>),
(<Cell Sheet.A8>, <Cell Sheet.B8>, <Cell Sheet.C8>),
(<Cell Sheet.A9>, <Cell Sheet.B9>, <Cell Sheet.C9>))

或者使用Worksheet.columns属性:

>>> tuple(ws.columns)

((<Cell Sheet.A1>,
<Cell Sheet.A2>,
<Cell Sheet.A3>,
<Cell Sheet.A4>,
<Cell Sheet.A5>,
<Cell Sheet.A6>,
...
<Cell Sheet.B7>,
<Cell Sheet.B8>,
<Cell Sheet.B9>),
(<Cell Sheet.C1>,
<Cell Sheet.C2>,
<Cell Sheet.C3>,
<Cell Sheet.C4>,
<Cell Sheet.C5>,
<Cell Sheet.C6>,
<Cell Sheet.C7>,
<Cell Sheet.C8>,
<Cell Sheet.C9>))

注意:由于性能原因,Worksheet.columns()方法在read-only(只读)模式下不可用。

只取值

如果你只想从一个worksheet中取值,你可以使用Worksheet.values属性。这会迭代worksheet中的所有行,但只返回cell的值。

Worksheet.iter_rows()Worksheet.iter_cols()都可以添加values_only参数来只返回cell的值:

>>> for row in ws.iter_rows(min_row=1, max_col=3, max_row=2, values_only=True):
...     print(row)

(None, None, None)
(None, None, None)

数据存储

一旦有了一个cell,就可以给它赋值:

>>> c.value = 'hello, world'
>>> print(c.value)
'hello, world'

>>> d.value = 3.14
>>> print(d.value)
3.14

保存到文件

保存一个workbook最简单方便的操作是使用Workbook对象的Workbook.save()方法。

wb.Workbook()
wb.save('balance.xlsx')

警告:此操作会直接覆盖已存在的文件,并且不会被警告。

注意:文件扩展名不强制为xlsx或xlsm,尽管如果不使用官方扩展名,您可能会在使用其他应用程序直接打开它时遇到一些问题。由于OOXML文件基本上是ZIP文件,您也可以使用您最喜欢的ZIP归档管理器打开它。

如果需要,可以指定属性wb.template=True,以将workbook另存为template(模板):

wb = load_workbook('document.xlsx')
wb.template = True
wb.save(document_template.xltx)

保存为stream(流)

如果你想将文件保存到流中,例如在使用Pyramid、Flask或Django等web应用程序时,你只需提供一个NamedTemporaryFile()

from tempfile import NamedTemporaryFile
from openpyxl import Workbook
wb = Workbook()
with NamedTemporaryFile() as tmp:
    wb.save(tmp.name)
    tmp.seek(0)
    stream = tmp.read()

警告:您应该监视数据属性和文档扩展名,以便在文档模板中保存文档,反之亦然,否则结果表引擎无法打开文档。

从文件加载

你可以用openpyxl.load_workbook()来打开一个存在的workbook:

>>> from openpyxl import load_workbook
>>> wb = load_workbook(filename='empty_book.xlsx')
>>> sheet_ranges = wb['ranges name']
>>> print(sheet_range['D18'].value)
3

注意:这里有几个flag可以在load_workbook中使用

  • data_only: 控制具有公式的单元格是否具有Excel上次读取工作表时存储的公式(默认值)或值。
  • keep_vba: 控制是否保留任何Visual Basic元素(默认值)。如果它们被保留,它们仍然不可编辑。

加载workbooks的错误

有时openpyxl将无法打开工作簿。这通常是因为文件有问题。如果是这种情况,那么openpyxl将尝试提供更多信息。Openpyxl严格遵循OOXML规范,并将拒绝不这样做的文件,因为它们是无效的。当这种情况发生时,您可以使用openpyxl中的异常来通知开发人员生成该文件的应用程序或库。由于OOXML规范是公开的,开发人员遵循它是很重要的。

您可以通过搜索ECMA-376来找到规范,大部分实现细节都在第4部分中。

简单使用

例子:创建一个简单的spreadsheet(电子表格)和bar chart(条形图)

在这个例子中,我们将从头开始创建一个工作表,添加一些数据,然后绘制它。我们还将探索一些有限的单元格样式和格式。

我们将在表格中输入的数据如下

SpeciesLeaf ColorHeight (cm)
MapleRed549
OakGreen783
PineGreen1204

首先,让我们加载openpyxl并创建一个新的workbook。并获取active sheet。我们还将输入tree data。

from openpyxl import Workbook

wb = Workbook()
ws = wb.active
treeData = [["Type", "Leaf Color", "Height"], 
            ["Maple", "Red", 549], 
            ["Oak", "Green", 783],
            ["Pine", "Green", 1204]]

接下来我们把数据添加进worksheet。因为treeData是一个嵌套列表的列表,我们可以简单地使用Worksheet.append()方法。

for row in treeData:
    ws.append(row)