使用Python的openpyxl包操作Excel文件

一、Excel表的相关术语

在正式介绍如何使用openpyxl包来操作Excel表之前,需要简单了解以下若干个和Excel相关的术语:

术语 解释
工作簿(Spreadsheet或Workbook) 工作簿就是用户创建的一个以.xlsx或.xls为后缀的文件
工作表(Worksheet或Sheet) 工作表是一个工作簿中的一页,一个工作簿可能有多个工作表
列(Column) 列,一般以大写字母表示,如:A
行(Row) 行,一般以数字表示,如:1
单元格(Cell) 列和行的交汇处,一般以字母数字表示,如:A1

二、安装openpyxl包

使用如下命令可以安装openpyxl包:

pip install openpyxl

实际上,笔者尝试在Windows10平台上使用上述命令安装openpyxl包时,遇到了以下两个问题,并通过对应方式得到了解决:

  • 安装速度很慢pip包管理工具默认从境外的源下载,可以在命令后加选项-i 境内镜像源地址进行换源安装;
  • 无法安装至期望路径:笔者的计算机上先在D盘安装过了Anaconda,所以默认后续所有的包都安装到了Anaconda的路径下,导致无法导入openpyxl包,于是又在命令后加上--target=期望指定的路径

因此,笔者通过下列命令快速完成了openpyxl包的安装,并使之可以被正确导入使用:

pip install openpyxl -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com --target=C:\Users\Administrator\AppData\Local\Programs\Python\Python38\Lib\site-packages

为了验证openpyxl包的确被正确安装,并且可以正常使用,下面代码使用openpyxl包创建一个简单的Excel表:

from openpyxl import Workbook


workbook = Workbook()
sheet = workbook.active

sheet['A1'] = 'Hello'
sheet['B1'] = 'openpyxl'

workbook.save(filename='hello_openpyxl.xlsx')

在这里插入图片描述

三、用openpyxl读取Excel

为了更好演示如何使用openpyxl操作Excel,本文使用了阿里云天池的一个数据集,原数据格式为CSV,此处将其复制后转到了Excel中,原始数据集可以从此处下载得到

下面在ipython中演示如何使用openpyxl读取Excel:

>>> from openpyxl import load_workbook
>>> workbook = load_workbook(filename='sam_tianchi_mum_baby.xlsx')
>>> print(workbook.sheetnames)  # 查看工作簿中的所有工作表
['Sheet 1', 'Sheet 2', 'Sheet 3']

>>> sheet = workbook.active  # 获取活动的工作表,一般为第一个或最后一次修改的那个表
>>> sheet
<Worksheet "Sheet 1">
>>> sheet.title  # 工作表的title属性可显示其名称
'Sheet 1'

在打开工作簿后,你就可以使用如下方式方便地从中获取想要的值:

>>> sheet['A1']  # 获取A1单元格对象
<Cell 'Sheet 1'.A1>

>>> sheet['A1'].value  # 获取A1单元格的值
'user_id'

你也可以用.cell()方法,通过行列的索引来获取某个单元格对象,进而使用.value来获取单元格的值:

>>> sheet.cell(row=10, column=2)
<Cell 'Sheet 1'.B10>

>>> sheet.cell(row=10, column=2).value
20090708

需要指出的是,load_workbook()函数的还有其他可选参数,这些参数可以改变Excel文件被导入后的行为,其中比较重要的有以下两个Bool类型参数:

  • read_only:可以只读模式导入一个Excel文件,这样就可以方便地打开较大的Excel文件;
  • data_only:导入时忽略Excel文件中的公式,只导入通过公式计算出的值。

1. 遍历Excel表中数据

openpyxl提供多种遍历Excel表的方式,你可以根据自身需求选择使用:

  • 使用类似切片的方式遍历Excel工作表:
>>> sheet['A1:C2']
((<Cell 'Sheet 1'.A1>, <Cell 'Sheet 1'.B1>, <Cell 'Sheet 1'.C1>),
 (<Cell 'Sheet 1'.A2>, <Cell 'Sheet 1'.B2>, <Cell 'Sheet 1'.C2>))
  • 获取某一或几列的所有单元格对象:
>>> # 获取某一列的所有的单元格
>>> sheet['A']
(<Cell 'Sheet 1'.A1>, 
 <Cell 'Sheet 1'.A2>, 
 <Cell 'Sheet 1'.A3>,
 ...
 <Cell 'Sheet 1'.A954>)
>>> # 获取某几列的所有单元格
>>> sheet['A:B']
((<Cell 'Sheet 1'.A1>,
  <Cell 'Sheet 1'.A2>,
  ...
  <Cell 'Sheet 1'.A954>),
 (<Cell 'Sheet 1'.B1>,
  <Cell 'Sheet 1'.B2>,
  ...
  <Cell 'Sheet 1'.B954>))
  • 获取某一或几行的所有单元格对象:
>>> # 获取某一行的所有单元格对象
>>> sheet[5]
(<Cell 'Sheet 1'.A5>, <Cell 'Sheet 1'.B5>, <Cell 'Sheet 1'.C5>)

>>> # 获取某几行的所有单元格对象
>>> sheet[5:6]
((<Cell 'Sheet 1'.A5>, <Cell 'Sheet 1'.B5>, <Cell 'Sheet 1'.C5>),
 (<Cell 'Sheet 1'.A6>, <Cell 'Sheet 1'.B6>, <Cell 'Sheet 1'.C6>))
  • 使用生成器迭代获取数据:

通过openpyxl包,使用迭代器遍历Excel中的数据也有多种方式,其中常用的有封装好的两个工作表对象方法:

  • .iter_rows():按行进行迭代;
  • .iter_cols():按列进行迭代。

上述两个方法均支持以下四个参数:

  • min_row:指定迭代起始行号;
  • max_row:指定迭代终止行号;
  • min_col:指定迭代起始列号;
  • max_col:指定迭代终止列号。
>>> for row in sheet.iter_rows(min_row=1, max_row=2, min_col=1, max_col=3):
>>> 	print(row)
(<Cell 'Sheet 1'.A1>, <Cell 'Sheet 1'.B1>, <Cell 'Sheet 1'.C1>)
(<Cell 'Sheet 1'.A2>, <Cell 'Sheet 1'.B2>, <Cell 'Sheet 1'.C2>)

>>> for column in sheet.iter_cols(min_row=1, max_row=2, min_col=1, max_col=3):
>>> 	print(column)
(<Cell 'Sheet 1'.A1>, <Cell 'Sheet 1'.A2>)
(<Cell 'Sheet 1'.B1>, <Cell 'Sheet 1'.B2>)
(<Cell 'Sheet 1'.C1>, <Cell 'Sheet 1'.C2>)

由上述代码可知,当使用.iter_rows()时,程序以元组形式按行返回单元格对象,而当使用.iter_cols()时,程序以元组形式按列返回单元格对象。

上述两种方法还支持一个Bool类型的参数values_only,当将其设置为True时,则迭代时返回的是单元格的值而非对象:

>>> for value in sheet.iter_cols(min_row=1, max_row=2, min_col=1, max_col=3, values_only=True):
>>> 	print(value)
('user_id', 2757)
('birthday', 20130311)
('gender', 1)

需要指出的是,此处使用iter_rows()iter_cols()方法得到的均为一个生成器,而使用生成器每次进行迭代产生的元素是元组形式的每一行或每一列,而不是每一个单元格的值。

需要注意的是,如果你尝试使用参数values_only时程序报如下错误:

iter_rows() got an unexpected keyword argument 'values_only'

说明你的openpyxl版本低于2.6,可以通过以下命令升级openpyxl包的版本(你可以使用openpyxl.__version__来查看其版本):

pip install -U openpyxl

另外:

  • 如果你在多个位置安装了openpyxl包,则你还可以在上述命令后加上--target参数指定升级对象位置的openpyxl
  • 如果你使用了交互式Python来学习使用openpyxl包,则升级完该包之后,你需要重新使用import语句导入openpyxl包,否则系统仍然使用老版本的包。

如果你希望迭代整个Excel文件,你还可以直接使用工作表的rows或columns属性,这等价于直接调用iter_rows()iter_cols()方法且不指定任何参数。

2. 使用內置容器处理数据

上述已经可以使用openpyxl包将数据从Excel文件中读取出来,如果希望在别的程序中使用这些数据,则可以考虑使用Python內置的容器,如:字典,来将从Excel文件读取出的数据进行序列化:

import json
from openpyxl import load_workbook


workbook = load_workbook(filename='sam_tianchi_mum_baby.xlsx')
sheet = workbook.active

# 使用列表生成式获取表头,即每一列的名称
table_headers = [table_header.value for table_header in sheet['1']]

users = dict()

for row in sheet.iter_rows(min_row=2, max_row=3, min_col=1, max_col=3, values_only=True):
    user_id = row[0]
    user_info = {
        table_headers[1]: row[1],
        table_headers[2]: row[2]
    }
    users[user_id] = user_info

# 使用json模块将数据序列化
print(json.dumps(users))

上述程序的运行结果为:

{
	"2757": {
		"birthday": 20130311,
		"gender": 1
	},
	"415971": {
		"birthday": 20121111,
		"gender": 0
	}
}

3. 转换数据为Data Class

四、用openpyxl向Excel写入数据

Excel文件支持写入文本、数字值、公式、图表,甚至是图片,而openpyxl包强大之处在于,它可以支持所有这些操作。

1. 创建一个Excel

为了演示方便,此处沿用文章开头使用openpyxl创建Excel表的代码:

from openpyxl import Workbook


workbook = Workbook()
sheet = workbook.active

sheet['A1'] = 'Hello'
sheet['B1'] = 'openpyxl'

workbook.save(filename='hello_openpyxl.xlsx')

2. 基本操作

  • 修改单元格的值:

前面我们知道可以通过以下方式修改单元格的值:

>>> from openpyxl import load_workbook
>>> workbook = load_workbook(filename='hello_openpyxl.xlsx')
>>> sheet = workbook.active
>>> sheet['A1'] = 'value'
>>> sheet['A1'].value
'value'

实际上,你还可以先选中一个单元格,然后再修改单元格的值:

>>> cell = sheet['A1']
>>> cell
<Cell 'Sheet'.A1>

>>> cell.value
'value'

>>> cell.value = 'hey'
>>> cell.value
'hey'

需要注意的是,上述修改单元格的操作只会在你调用workbook.save()之后才会把值保存到Excel文件中。

3. 操作行或列

增删行和列可以使用以下几个方法:

方法名 方法用途
insert_rows 插入行
delete_rows 删除行
insert_cols 插入列
delete_cols 删除列

上述方法均支持两个参数:

  • idx:插入、删除的行列位置;
  • amount:插入、删除行列的数量。
>>> # 对Excel工作表进行增删之前,表中数据:
>>> for row in sheet.iter_rows(values_only=True):
>>> 	print(row)
('hey', 'openpyxl')

>>> # 在第1列('A')之前插入一列:
>>> sheet.insert_cols(idx=1)
>>> for row in sheet.iter_rows(values_only=True):
>>> 	print(row)
(None, 'hey', 'openpyxl')

>>> # 在第2列('B')和第3列('C')之间插入5列:
>>> sheet.insert_cols(idx=3, amount=5)
>>> for row in sheet.iter_rows(values_only=True):
>>> 	print(row)
(None, 'hey', None, None, None, None, None, 'openpyxl')

>>> 在Excel工作表开始处插入4行:
>>> sheet.insert_rows(idx=1, amount=4)
>>> for row in sheet.iter_rows(values_only=True):
>>> 	print(row)
(None, None, None, None, None, None, None, None)
(None, None, None, None, None, None, None, None)
(None, None, None, None, None, None, None, None)
(None, None, None, None, None, None, None, None)
(None, 'hey', None, None, None, None, None, 'openpyxl')

>>> 删除Excel工作表的前4行:
>>> sheet.delete_rows(idx=1, amount=4)
>>> for row in sheet.iter_rows(values_only=True):
>>> 	print(row)
(None, 'hey', None, None, None, None, None, 'openpyxl')

五、参考资料

猜你喜欢

转载自blog.csdn.net/weixin_37780776/article/details/107273705