openpyxl库 工作簿对象

一、openpyxl库与模块导入。

二、工作簿相关知识。

三、工作表相关知识,其中包含了今天的第一个重难点,iter_rows()及其相应的参数。

四、单元格相关知识,第二个重难点就是获取单元格的方式,我会讲三种不同的方式,你要注意它们之间的异同。

五、样式和图形设置相关知识

openpyxl库与模块导入
你应该了解过,要使用Python处理Excel表格,需要借助一个非常厉害的第三方库——openpyxl。
openpyxl是Eric Gazoni和Charlie Clark联合开发,用来处理Excel电子表格的Python第三方库。因为它是第三方库,所以需要根据系统环境,在本地使用正确的命令来安装这个库,命令如下所示:

Windows系统:pip install openpyxl
MacOS系统:pip3 install openpyxl

openpyxl库可以处理Excel2010以后的电子表格格式,包括:xlsx/xlsm/xltx/xltm,由于今后的课程和工作中常用到的就是xlsx格式的表格,所以我们的课程也是关于处理xlsx格式表格的相关内容。
要使用openpyxl库,需要先导入,一起来看看下面的代码。
import openpyxl

通过文件路径,打开工作簿

wb1 = openpyxl.load_workbook('./demo_excel.xlsx')

用 Workbook() 创建新工作簿

wb2 = openpyxl.Workbook()

在上面的代码里,我们先用import直接导入了openpyxl库,然后用openpyxl.load_workbook()打开已有工作簿,用openpyxl.Workbook()创建新工作簿。

但是每次使用我们都要带openpyxl.,这样就有点儿麻烦。

为了方便,今天我教你一个新的导入方式:from…import…。

from…import…是import语句的一个变体,可以导入库或模块中的函数、方法、类或变量。

语法为:from 库/模块 import 函数/方法/类/变量
可以用from…import…一行导入多个名字,不同名字间用逗号分隔
例如:from 库/模块 import 函数1, 类1

所以上面的代码就可以被改写为:

from openpyxl import load_workbook, Workbook

通过文件路径,打开已有工作簿

wb1 = load_workbook('./demo_excel.xlsx')

用 Workbook() 创建新工作簿

wb2 = Workbook()

注意第一行代码,写为from openpyxl import load_workbook, Workbook,接下来就可以直接使用被导入的函数/方法/类/变量。
两种写法对比一下,同样是打开三个工作簿和创建三个新的工作簿,下面的写法明显更简单,更高效一些。


image.png
  1. 工作簿
    通常,手动操作的顺序可以被总结为:
    1.打开工作簿
    2.确认工作表
    3.操作单元格

我会按照手动操作的顺序来讲解openpyxl的相关知识,可参考下图。


image.png

根据openpyxl的定义,一个.xlsx格式的Excel文件就代表了一个工作簿对象,那么我们先来学习获取工作簿对象的方式,然后再学习工作簿对象的一些基本操作。
4.1 如何获取工作簿对象
获取工作簿对象的第一种方式你肯定不陌生,需要使用openpyxl库中的一个函数load_workbook(filename),参数filename代表了工作簿的路径,即.xlsx文件的路径。这个函数会返回一个工作簿对象,你可以运行下面的代码,看看代码的输出结果。

from openpyxl import load_workbook

打开【公司人员名单.xlsx】工作簿

staff_wb = load_workbook('./codes/material/公司人员名单.xlsx')

打印工作簿对象

print(staff_wb)

运行代码后,我们得到了打印出来的工作簿对象:
<openpyxl.workbook.workbook.Workbook object at xxxxxxxx>。

结果中的Workbook object(Workbook对象)就是工作簿对象,出现这样的结果,也就意味着我们已经成功使用代码打开了【公司人员名单.xlsx】这个文件,并且获得代表它的工作簿对象。

用图片来简单总结一下:


image.png

我们还可以通过实例化Workbook类来获取工作簿对象,更准确地来说,这是一种创建工作簿对象的方式。

语法很简单,写为Workbook()即可,括号里面不需要写任何参数。运行下面的代码,观察代码的输出结果。
from openpyxl import Workbook

新建工作簿

new_wb = Workbook()

打印工作簿对象

print(new_wb)
输出结果中同样显示<openpyxl.workbook.workbook.Workbook object at xxxxxxxx>,证明工作簿对象已经被成功创建。
以上就是获取工作簿对象的两种途径,下面来介绍工作簿对象的相关基本操作。

4.2 工作簿对象的基本操作
刚才,我们通过实例化Workbook类成功新建了一个工作簿对象,如果要把新建的工作簿对象保存到本地,就需要使用工作簿对象的方法save()。

语法为:工作簿对象.save(filename),参数filename表示新工作簿的文件路径,这里我推荐以.xlsx作为新工作簿的路径结尾。
你可以参考下方的示例代码。

from openpyxl import Workbook

新建工作簿

new_wb = Workbook()

将新建的工作簿保存为【new_excel.xlsx】

new_wb.save('./new_excel.xlsx')
如果你在本地运行这段代码的话,就可以在当前工作目录下看到新生成的Excel文件【new_excel.xlsx】。
值得一提的是,通过load_workbook(filename)获取到的工作簿对象也可以使用方法save(filename)。

如果参数filename不变,即保存在原有路径,相当于修改原文件;若参数filename变化,即保存在新的路径,相当于另存为新的文件。


image.png

工作簿对象还有一个比较常用的属性active,语法为工作簿对象.active,这个属性可以获取到工作簿中活动的工作表对象,至于什么是工作表对象,我马上就会讲。

4.3 总结
有关工作簿对象的常用知识就这么多,相对来说比较简单,看下图快速总结后,就开始这部分的练习吧。

image.png
  1. 工作表


    image.png

    工作表就是工作簿中,位于下方的标签。在实际操作中,我们可以通过点击不同的标签,来选择不同的工作表。


    image.png

    现实中的工作表,在openpyxl中对应着工作表对象(Worksheet对象)。

一个工作表对象(Worksheet对象)就表示工作簿中的一张工作表。那么如何用代码来获取工作表对象呢?
5.1 如何获取工作表对象
常用的获取工作表的方式有两种,第一种就是刚才提到的通过工作簿对象的属性active。

active会获取到活动的工作表,何为活动的工作表呢?

通常情况下,活动工作表是指当前正在操作的工作表,打开一个.xlsx文件后,默认显示的工作表即为活动工作表。如下图中的活动工作表就是:下半年公司名单。

image.png

from openpyxl import load_workbook

打开【公司人员名单.xlsx】工作簿

staff_wb = load_workbook('./codes/material/公司人员名单.xlsx')

获取活动工作表

active_ws = staff_wb.active

打印工作簿对象

print(staff_wb)

打印工作表对象

print(active_ws)
代码分别打印了工作簿对象(Workbook)和工作表对象(Worksheet),要注意区分它们。


image.png

另一种获取工作表的方式为:按表名取表。

如果我们已知工作表的名称,就可以以表名为索引,用工作簿对象['表名']的方式取到指定的工作表对象。一般情况下,如果工作簿中存在多张工作表,且我们知道这些工作表的名称,就可以采用按表名取表这种方式。

运行下面的代码,注意代码第6、7行的写法。

from openpyxl import load_workbook

打开【公司人员名单.xlsx】工作簿

staff_wb = load_workbook('./codes/material/公司人员名单.xlsx')

按表名取表

fhy_ws = staff_wb['上半年公司名单'] # fhy为first half year(上半年)的缩写
shy_ws = staff_wb['下半年公司名单'] # shy为second half year(下半年)的缩写

打印工作簿对象

print(staff_wb)

打印工作表对象

print(fhy_ws)
print(shy_ws)

对比以下两种获取工作表对象的方式,你可以根据实际需要自行决定使用哪一种写法。


image.png

有了工作表对象后,我们就可以学习一些它的基本操作了。

5.2 工作表对象的基本操作
获取单行或单列

先从最简单的获取单行或单列操作开始。

众所周知,在Excel表格中,使用数字表示行数,用英文字母表示列名。


image.png

在openpyxl中,我们可以通过工作表对象[行数]或工作表对象['列名']的方式获取到一个元组,这个元组中包含了指定行或列中的所有数据。

实际体验一下吧。
from openpyxl import load_workbook

打开【公司人员名单.xlsx】工作簿

staff_wb = load_workbook('./codes/material/公司人员名单.xlsx')

获取活动工作表

active_ws = staff_wb.active

打印获取到的第五行数据

print(active_ws[5])

打印获取到的第二列数据

print(active_ws['B'])

bash:root$ python /home/python-class/root/main10.py
(<Cell '下半年公司名单'.A5>, <Cell '下半年公司名单'.B5>, <Cell '下半年公司名单'.C5>, <Cell '下半年公司名单'.D5>)
(<Cell '下半年公司名单'.B1>, <Cell '下半年公司名单'.B2>, <Cell '下半年公司名单'.B3>, <Cell '下半年公司名单'.B4>, <Cell '下半年公司名单'.B5>, <Cell '下半年公司名单'.B6>, <Cell '下半年公司名单'.B7>, <Cell '下半年公司名单'.B8>, <Cell '下半年公司名单'.B9>, <Cell '下半年公司名单'.B10>)

观察上方的输出结果可以发现,输出结果确实为元组,但元组中的每一个元素均为<Cell '工作表名称'.坐标>的形式,提前预告一下Cell是单元格对象,我们学完工作表对象以后马上就会讲到单元格对象(Cell)。
单行单列数据可以获取了,那么多行数据应该怎么获取呢?接下来要介绍的方法是本节课的重点之一,要用心。

获取多行数据

我们可以借助工作表对象的方法iter_rows()来得到表格中指定范围内的多行数据。
iter_rows()的语法如下图所示


image.png

参数min_row和max_row分别表示最小行索引和最大行索引,最小行索引的值默认为1,最大行索引的值默认为表格中有数据的最下面一行的行数;

参数min_col和max_col分别表示最小列索引和最大列索引,最小列索引的值默认为1,最大列索引的值默认为表格中有数据的最右面一列的列数;

参数values_only决定是否返回单元格的值,如果为True则返回单元格的值,如果为False则返回单元格对象。通常情况下,只读数据时,需要将该参数设置为True,要写入数据时,保持其为默认的False就好。

工作表对象的方法iter_rows()会返回一个可迭代对象,该对象中有n个元组,n为参数中指定的行数,每一个元组都代表了表格中的一行。

因此,通常情况下,iter_rows()会和for循环结合使用,从而使得我们取出其返回的可迭代对象中的每一个元组,即表格中指定范围内的每一行数据。

运行下面的代码,然后仔细观察代码的运行结果。

from openpyxl import load_workbook

打开【公司人员名单.xlsx】工作簿

staff_wb = load_workbook('./codes/material/公司人员名单.xlsx')

获取【'上半年公司名单'】工作表

fhy_ws = staff_wb['上半年公司名单']

返回第2行至第12行,第2列(B列)至第3列(C列)这个范围的单元格内的所有数据(值)

for row in fhy_ws.iter_rows(min_row=2, max_row=12, min_col=2, max_col=3, values_only=True):
print(row)
如果你仔细观察输出结果的话,你会发现其最后一行为(None, None),这是因为iter_rows()方法规定,如果指定的行中没有数据,就会返回一个空的元组。

第12行为空行,没有任何数据,所以返回了空的元组


image.png

当参数values_only保持其默认的False时,iter_rows()方法会返回指定范围内的单元格对象,我会在后面的单元格对象部分为你详细介绍。

今天要介绍的最后一种工作表的操作是添加一行数据。

添加数据
我们可以使用工作表对象的append()来添加一行数据,相信这个方法你一点都不陌生。

该方法可将部分可迭代对象(常见的如列表、元组)添加到工作表对象中,即给表格的末尾追加一行数据。语法也很简单,写为工作表对象.append(列表/元组)即可。

不过需要注意的是,使用append()添加完数据后,如果想要在本地的Excel文件中看到添加后的数据,就一定要将工作簿保存下来,即使用工作簿对象的方法save()。

具体的写法你可以参考下面的代码。

from openpyxl import load_workbook

打开【公司人员名单.xlsx】工作簿

staff_wb = load_workbook('./公司人员名单.xlsx')

获取活动工作表

active_ws = staff_wb.active

info_list = ['S1911', '萧爵瑟', 3000, '内容']
info_tuple = ('S1912', '吴琐薇', 5000, '销售')

active_ws.append(info_list)
active_ws.append(info_tuple)

保存工作簿为【append_demo.xlsx】

staff_wb.save('./append_demo.xlsx')

上面的代码中,添加了两行数据,两行数据分别为列表和元组,并且它们确实是被添加到了工作表的最后。如果你在本地运行了上面的代码,就会生成对应的xlsx文件【append_demo.xlsx】。


image.png

5.3 总结
工作表的相关知识是本节课的重难点,尤其是iter_rows()那部分,虽然你可能之前对某些知识有所涉猎,但系统性的学习还是有必要的,下面我就来总结一下。

image.png
  1. 单元格
    掌握了工作表相关知识后,就到了最后的重头戏——单元格对象。
image.png

你应该注意到了,在工作表对象的相关知识中,我提到了单元格对象这一概念,下面就来系统性地介绍这一对象。

顾名思义,单元格对象代表工作表中的一个单元格


image.png

目前为止,基本上所有对于行列的操作,最终都可以回归为对单元格的操作。和之前一样,我们先来学习获取单元格对象的方式,然后再学习单元格对象取值赋值的相关知识。

6.1 如何获取单元格对象
我会介绍三种常见的获取单元格对象的方式,这是本节课最后的重难点了,你要花点时间理解下面的内容。

第一种方式你刚才学过,就是通过for row in 工作表对象.iter_rows()来获取指定范围的行,当参数values_only为默认的False时,我们得到的row就是一个个由单元格对象组成的元组,可以通过索引或者for循环遍历的方式来获取单独的单元格对象。
还是使用上面的例子,不过这次我们不写参数values_only,让其保持为默认的False,这样iter_rows()就会返回指定的单元格对象了。

运行下面的代码,然后观察其结果与之前values_only=True时有何不同。


image.png

image.png

一句话总结下第一种方式:通过iter_rows()来获取指定范围的行,再通过索引从行中取出单元格对象。

第二种方式和第一种大同小异,可以写为:

for cell in 工作表对象[行数]
for cell in 工作表对象['列名']
下面的代码分别取出了第三行和第三列的所有单元格对象,你可以运行后查看代码的结果。

from openpyxl import load_workbook

打开【公司人员名单.xlsx】工作簿

staff_wb = load_workbook('./codes/material/公司人员名单.xlsx')

获取活动工作表

staff_ws = staff_wb.active

for循环遍历,取出第三行的所有单元格对象

for row_cell in staff_ws[3]:
print(row_cell)

for循环遍历,取出第三列(C列)的所有单元格对象

for col_cell in staff_ws['C']:
print(col_cell)
显而易见,代码输出了指定行列的所有单元格对象。

image.png

一句话总结下第二种方式:通过行数或者列名来指定具体的行或列,然后通过for循环遍历获取指定行或列中的每一个单元格对象。
第三种方法其实最简单明了,直接通过工作表对象['单元格坐标']来获取具体的单元格对象。

比如工作表对象['A1']就会获取到表格中,A1那个单元格对应的单元格对象。运行下面的代码来证明我所言非虚。
from openpyxl import load_workbook

打开【公司人员名单.xlsx】工作簿

staff_wb = load_workbook('./codes/material/公司人员名单.xlsx')

获取活动工作表

staff_ws = staff_wb.active

打印单元格对象A1

print(staff_ws['A1'])
是不是直截了当,一句话总结下获取单元格对象的第三种方式:通过单元格坐标来指定具体的单元格,从而获取到对应的单元格对象。
看到刚才的代码运行结果,都是输出了单元格对象,但是单元格内的具体数据并没有显示出来。如果要获取单元格对象的具体数据,应该怎么写?

6.2 单元格对象的基本操作
借助单元格对象的属性value,我们就可以得到具体的数据;同时,我们也可以通过这个属性给单元格对象赋值(修改单元格的值或给单元格添加值)。

具体的写法如下:

获取单元格的值

单元格对象.value

给单元格对象赋值

单元格对象.value = 值

运行下面的代码,看看代码运行后的结果。
from openpyxl import load_workbook

打开【公司人员名单.xlsx】工作簿

staff_wb = load_workbook('./codes/material/公司人员名单.xlsx')

获取活动工作表

staff_ws = staff_wb.active

打印单元格对象C2的值

print(staff_ws['C2'].value)

修改单元格对象C2的值为10000

staff_ws['C2'].value = 10000

打印修改后的单元格对象C2的值

print(staff_ws['C2'].value)

将结果保存为【公司人员名单_new.xlsx】

staff_wb.save('./codes/material/公司人员名单_new.xlsx')
通过第8行代码,我们打印出了单元格C2原有的值8000。
第11至15行,我们通过单元格对象.value将10000赋值给单元格C2,改变了其原有的值,并将修改后的结果打印了出来。
效果如下图所示:


image.png

6.3 总结
获取单元格对象的三种方式,是本节课的重难点,需要你多花点时间去理解,多动手写一写这部分的代码。下面先来总结单元格对象这部分的内容,然后再做道练习题巩固相关知识。


image.png

最后稍微扩展一下,我们平时在使用Excel的时候,需要经常设置样式或者根据选中的数据来画图,这些都可以使用openpyxl库来实现。我会在过几天的课程中为你讲解。
image.png
  1. 总结与练习
    7.1 知识总结
    好啦,今天学习的内容就这么多了。

用思维导图总结一下。


image.png

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

推荐阅读更多精彩内容