openpyxl 用于读取/写入Excel 的 Python库

我这里学习openpyxl的原因是,xlwt库(一个excel写入库) 无法实现 读取模版文件(有一定的模版内容),进行修改,并将修改后的内容保存到新的sheet表(原模版sheet保持不变)。 使用copy_worksheet功能。

安装

pip3 install openpyxl
为了能够将图像(jpeg,png,bmp等)包含到openpyxl文件中,您还需要安装pillow库(非必须):
pip3 install pillow

开始教程

1. 创建一个工作簿(在内存中创建,可以理解为内存中的excel文件对象)
In [1]: from openpyxl import Workbook
   ...: wb = Workbook()
2. 创建一个工作表sheet

注意:第一次创建完 Workbook 后默认会有一个名为Sheet 的工作表。
获取这个工作表

ws = wb.active

使用 Workbook.create_sheet(title: str=None, index: int=None) 方法创建新的工作表
title:sheet的名字
index:sheet在excel的位置,默认最后一个

# 默认位置在最后一个
In [2]: ws1 = wb.create_sheet("Mysheet1")
# 在第一个
In [3]: ws2 = wb.create_sheet("Mysheet2", 0)
# 在倒数第二个
In [4]: ws3 = wb.create_sheet("Mysheet3", -1)

sheet 创建时会自动为其命名。它们按顺序编号(Sheet,Sheet1,Sheet2等)。您可以随时通过 Worksheet.title 属性更改此名称:

# 将名字由 'Mysheet1' 改成 'New Title'
ws1.title = "New Title"

默认情况下,包含该标题的选项卡的背景颜色为白色。您可以更改此属性RRGGBB,为Worksheet.sheet_properties.tabColor属性提供颜色代码 :

ws.sheet_properties.tabColor = "1072BA"

给工作表(sheet)命名后,就可以将其作为工作簿(Workbook)的键,来获取指定sheet:

new_title = wb["New Title"]

您可以使用 Workbook.sheetname 属性查看工作簿中所有工作表的名称

In [24]: wb.sheetnames
Out[24]: ['Mysheet2', 'Sheet', 'Mysheet3', 'New Title']
3. 遍历工作表
In [25]: for sheet in wb:
    ...:     print(sheet)
    ...: 
<Worksheet "Mysheet2">
<Worksheet "Sheet">
<Worksheet "Mysheet3">
<Worksheet "New Title">
4. 在单个工作簿中创建工作表的副本

copy_worksheet(from_worksheet)
from_worksheet:复制哪个工作表

In [30]: target = wb.copy_worksheet(wb["New Title"])

In [31]: target
Out[31]: <Worksheet "New Title Copy">

注意:

仅复制单元格(包括值,样式,超链接和注释)和某些工作表属性(包括尺寸,格式和属性)。不复制所有其他工作簿/工作表属性-例如图像,图表。

您也不能在工作簿之间复制工作表。如果工作簿以只读或仅写 模式打开,则不能复制工作表。

5. 访问一个单元

单元格可以直接作为工作表的键进行访问:

In [34]: c = ws['A4']

In [35]: c
Out[35]: <Cell 'Sheet'.A4>

这将返回A4处的单元格,或者如果尚未存在则创建一个单元格。可以直接分配值:

In [36]: ws['A4'] = 4

Worksheet.cell() 方法可以使用行和列表示法访问单元格:

In [38]: d = ws.cell(row=4, column=2, value=10)

In [39]: d
Out[39]: <Cell 'Sheet'.B4>

在内存中创建工作表时,它不包含任何单元格。它们是在首次访问时创建的。

6. 访问多个单元

可以使用切片访问单元格范围:

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

In [41]: cell_range
Out[41]: 
((<Cell 'Sheet'.A1>, <Cell 'Sheet'.B1>, <Cell 'Sheet'.C1>),
 (<Cell 'Sheet'.A2>, <Cell 'Sheet'.B2>, <Cell 'Sheet'.C2>))

行或列的范围可以类似地获得:

In [42]: colC = ws['C']

In [43]: colC
Out[43]: (<Cell 'Sheet'.C1>, <Cell 'Sheet'.C2>, <Cell 'Sheet'.C3>, <Cell 'Sheet'.C4>)

In [44]: col_range = ws['C:D']

In [45]: col_range
Out[45]: 
((<Cell 'Sheet'.C1>, <Cell 'Sheet'.C2>, <Cell 'Sheet'.C3>, <Cell 'Sheet'.C4>),
 (<Cell 'Sheet'.D1>, <Cell 'Sheet'.D2>, <Cell 'Sheet'.D3>, <Cell 'Sheet'.D4>))

In [46]: row10 = ws[10]

In [47]: row10
Out[47]: 
(<Cell 'Sheet'.A10>,
 <Cell 'Sheet'.B10>,
 <Cell 'Sheet'.C10>,
 <Cell 'Sheet'.D10>)

In [48]: row_range = ws[5:10]

In [49]: row_range
Out[49]: 
((<Cell 'Sheet'.A5>, <Cell 'Sheet'.B5>, <Cell 'Sheet'.C5>, <Cell 'Sheet'.D5>),
 (<Cell 'Sheet'.A6>, <Cell 'Sheet'.B6>, <Cell 'Sheet'.C6>, <Cell 'Sheet'.D6>),
 (<Cell 'Sheet'.A7>, <Cell 'Sheet'.B7>, <Cell 'Sheet'.C7>, <Cell 'Sheet'.D7>),
 (<Cell 'Sheet'.A8>, <Cell 'Sheet'.B8>, <Cell 'Sheet'.C8>, <Cell 'Sheet'.D8>),
 (<Cell 'Sheet'.A9>, <Cell 'Sheet'.B9>, <Cell 'Sheet'.C9>, <Cell 'Sheet'.D9>),
 (<Cell 'Sheet'.A10>,
  <Cell 'Sheet'.B10>,
  <Cell 'Sheet'.C10>,
  <Cell 'Sheet'.D10>))

您也可以使用以下Worksheet.iter_rows()方法:
iter_rows(min_row=None, max_row=None, min_col=None, max_col=None, values_only=False):

# 1-2行,最大3列
In [50]: for row in ws.iter_rows(min_row=1, max_col=3, max_row=2):
    ...:     for cell in row:
    ...:         print(cell)
    ...: 
<Cell 'Sheet'.A1>
<Cell 'Sheet'.B1>
<Cell 'Sheet'.C1>
<Cell 'Sheet'.A2>
<Cell 'Sheet'.B2>
<Cell 'Sheet'.C2>

同样,该Worksheet.iter_cols()方法将返回列:
iter_cols(min_col=None, max_col=None, min_row=None, max_row=None, values_only=False)

In [51]: for col in ws.iter_cols(min_row=1, max_col=3, max_row=2):
    ...:     for cell in col:
    ...:         print(cell)
    ...: 
<Cell 'Sheet'.A1>
<Cell 'Sheet'.A2>
<Cell 'Sheet'.B1>
<Cell 'Sheet'.B2>
<Cell 'Sheet'.C1>
<Cell 'Sheet'.C2>

如果需要遍历文件的所有行或列,则可以使用 Worksheet.rows 属性:

# 第一行,第二行,第三行 ......
In [52]: ws.rows
Out[52]: <generator object Worksheet._cells_by_row at 0x116121f20>

In [53]: tuple(ws.rows)
Out[53]: 
((<Cell 'Sheet'.A1>, <Cell 'Sheet'.B1>, <Cell 'Sheet'.C1>, <Cell 'Sheet'.D1>),
 (<Cell 'Sheet'.A2>, <Cell 'Sheet'.B2>, <Cell 'Sheet'.C2>, <Cell 'Sheet'.D2>),
 (<Cell 'Sheet'.A3>, <Cell 'Sheet'.B3>, <Cell 'Sheet'.C3>, <Cell 'Sheet'.D3>),
 (<Cell 'Sheet'.A4>, <Cell 'Sheet'.B4>, <Cell 'Sheet'.C4>, <Cell 'Sheet'.D4>),
 (<Cell 'Sheet'.A5>, <Cell 'Sheet'.B5>, <Cell 'Sheet'.C5>, <Cell 'Sheet'.D5>),
 (<Cell 'Sheet'.A6>, <Cell 'Sheet'.B6>, <Cell 'Sheet'.C6>, <Cell 'Sheet'.D6>),
 (<Cell 'Sheet'.A7>, <Cell 'Sheet'.B7>, <Cell 'Sheet'.C7>, <Cell 'Sheet'.D7>),
 (<Cell 'Sheet'.A8>, <Cell 'Sheet'.B8>, <Cell 'Sheet'.C8>, <Cell 'Sheet'.D8>),
 (<Cell 'Sheet'.A9>, <Cell 'Sheet'.B9>, <Cell 'Sheet'.C9>, <Cell 'Sheet'.D9>),
 (<Cell 'Sheet'.A10>,
  <Cell 'Sheet'.B10>,
  <Cell 'Sheet'.C10>,
  <Cell 'Sheet'.D10>))

Worksheet.columns 属性:

# A列,B列,C列 ......
In [54]: tuple(ws.columns)
Out[54]: 
((<Cell 'Sheet'.A1>,
  <Cell 'Sheet'.A2>,
  <Cell 'Sheet'.A3>,
  <Cell 'Sheet'.A4>,
  ...
  <Cell 'Sheet'.D7>,
  <Cell 'Sheet'.D8>,
  <Cell 'Sheet'.D9>,
  <Cell 'Sheet'.D10>))
7. 仅获取值

如果只需要工作表中的值,则可以使用该 Worksheet.values 属性。这将遍历工作表中的所有行,但仅返回单元格值:

In [55]: for row in ws.values:
    ...:    for value in row:
    ...:      print(value)
    ...: 
None
...
None
4
10
None
None
...
None
None

Worksheet.iter_rows()Worksheet.iter_cols()方法中也可以采用 values_only 参数,只返回单元格的值:

In [56]: 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)
8. 数据存储

一旦有了Cell,我们可以为其分配一个值:

In [61]: c.value = 'hello, world'

In [62]: c.value
Out[62]: 'hello, world'

In [63]: d.value = 3.14

In [64]: d.value
Out[64]: 3.14
  1. 保存到文件
    保存工作簿的最简单,最安全的方法是使用对象的 Workbook.save() 方法:
wb.save('test.xlsx')

此操作将覆盖现有文件,而不会发出警告。

  1. 保存到流
    如果要将文件保存到流中,例如在使用Web应用程序(例如Pyramid,Flask或Django)时,只需提供以下命令即可 NamedTemporaryFile()
In [83]: from tempfile import NamedTemporaryFile

In [84]: with NamedTemporaryFile() as tmp:
    ...:     wb.save(tmp.name)
    ...:     tmp.seek(0)
    ...:     stream = tmp.read()
    ...: 
9. 从文件中加载数据

您可以使用openpyxl.load_workbook()打开现有的工作簿

from openpyxl import load_workbook
wb2 = load_workbook('test.xlsx')
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容