概述
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(条形图)
在这个例子中,我们将从头开始创建一个工作表,添加一些数据,然后绘制它。我们还将探索一些有限的单元格样式和格式。
我们将在表格中输入的数据如下
| Species | Leaf Color | Height (cm) |
|---|---|---|
| Maple | Red | 549 |
| Oak | Green | 783 |
| Pine | Green | 1204 |
首先,让我们加载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)