相信很多小伙伴学Python都是奔着自动化办公来的,特别是对每天都要和excel打交道的小伙伴们来说。
之后山月也会给大家分享一些python处理excel的知识,希望大家多多支持~
如果看过山月之前的文章:自学Python一年后,我有这些想说,会知道python处理excel的库有很多,比如xlrd,xlwt,xlwings,openpyxl,pandas等。
虽然山月一直用的是openpyxl,但是考虑到很多小伙伴是刚开始学习这方面的内容。
因此山月会先通过一个更简单的库--xlrd,来给大家介绍一下excel的一些基本知识,以及python如何处理excel。
希望大家能跟着文章把知识点的代码手动输一遍,把xlrd库掌握透~
01
准备工作
1.1 xlrd基本介绍
xlrd作为python处理excel最简单最基本的一个库,它只能用来读取excel数据,不能用来写和修改excel数据。
官方文档:https://xlrd.readthedocs.io/en/latest/
1.2 安装xlrd
1)到python官网下载相应的版本手动安装,比如xlrd 2.0.1版本:
官网:https://pypi.org/project/xlrd/
2)推荐使用:在cmd命令提示符窗口用pip install xlrd进行安装,如果想安装指定版本比如1.2.0,则输入:pip install xlrd==1.2.0。
1.3 查看xlrd版本
在cmd窗口输入pip show xlrd,查看安装的xlrd版本:
山月安装的是1.2.0的版本。因为现在最新版本的xlrd只支持.xls文件,所以如果需要读取.xlsx文件的话,需要安装旧版本。
02
Excel的介绍
既然要处理excel,首先我们得了解一下excel。
2.1 工作薄与工作表
大家在日常使用里肯定听过工作薄与工作表,但也有些小伙伴可能至今还弄不清楚工作薄与工作表的区别。
工作薄:一个excel文件就是一个工作薄,一个工作簿由一个或多个工作表所组成,工作簿中最多可建立255个工作表。
工作表:是真正意义上我们常说的表格,每张工作表都是由单元格组成的。
2.2 单元格
单元格是由行(row)和列(column)交叉构成的,它是组成表格的最小单位,也可进行可合并和拆分。我们对单个数据的输入和修改都是在单元格中进行的。
每个单元格都有一个固定的编号,由所在行列的位置来决定。比如B3,指的是“B”列与第3行交叉位置上的单元格。
2.3 创建一个表格
山月创建了一个excel文件【xlrd实例文件.xlsx】,也就是一个工作薄:
我们打开这个工作薄:
它一共有两个工作表:绩效成绩工作表、绩效工资工作表。
其中我们可以看到页面下方有两个工作表名称,其中工作表绩效成绩的名称是绿色的,这表明绩效成绩工作表是我们的目前正在操作的工作表,也就是活动工作表。
下面我们会基于这个excel文件来对xlrd进行深入的学习。
如果大家需要这个excel源文件的话,可以在公众号后台发送:【xlrd表格】。
03
xlrd的详解
import xlrd #导入模块
3.2 打开excel文件
#如果excel文件在当前py文件的同一目录下,直接输入excel文件名打开
data= xlrd.open_workbook("xlrd实例文件.xlsx")
#如果excel文件不在py文件目录下,用excel文件的绝对路径打开
data= xlrd.open_workbook("H:\\临时文件夹\\xlrd实例文件.xlsx")
由于山月的excel文件就在py文件的同一目录下,因此在下面的解说里,山月都是直接使用第一种方法打开。
大家在学习的过程里按照自己的环境来选择方法哈。
我们来看看data运行的结果是什么,代码:
import xlrd #导入模块
data= xlrd.open_workbook("xlrd实例文件.xlsx") #打开excel文件
print(data)
运行结果:
xlrd.book.Book object at 0x0000013C076207F0
也就是说我们返回了一个xlrd.book.Book对象。下面我们基于这个对象来具体的看看xlrd怎么操作excel。
3.3 获取工作表
1)获取工作薄里所有工作表信息
如果你想了解一个excel文件,第一件事应该干什么?是不是看看这个工作薄里有多少个工作表?又有哪些工作表?
import xlrd #导入模块
data= xlrd.open_workbook("xlrd实例文件.xlsx") #打开excel文件
work_sheets = data.nsheets #返回工作薄中所有工作表的数量
work_names = data.sheet_names() #返回工作薄中所有工作表的名字
print(work_sheets)
print(work_names)
运行结果:
2
['绩效成绩', '绩效工资']
我们可以得出【xlrd实例文件.xlsx】文件里一共有两个工作表,它们的名字分别是:绩效成绩和绩效工资。
也许好学的你立马有了疑问:但是我处理文件的时候一般都是在具体的工作表上进行操作呀~
别着急,我们就来看看怎么获取具体的工作表。
2)获取具体工作表
一共有两种方法可以用来获取具体的工作表:
通过工作表的索引顺序(sheet_index)来获取,或者通过工作表的名称(sheet_name)来获取,其中通过索引顺序有两种表达方式。
work_sheet = data.sheets()[sheet_index] #通过工作表的索引顺序获取
work_sheet = data.sheet_by_index(sheet_index) #通过工作表的索引顺序获取
work_sheet = data.sheet_by_name(sheet_name) #通过工作表的名称获取
工作表索引也就是这个工作表在工作薄的位置(从0开始),比如我们绩效成绩工作表的索引是0,绩效工资工作表的索引是1。
我们来具体的看看怎么获得绩效成绩这个工作表:
import xlrd #导入模块
data= xlrd.open_workbook("xlrd实例文件.xlsx") #打开excel文件
work_sheet_1 = data.sheets()[0]
work_sheet_2 = data.sheet_by_index(0)
work_sheet_3 = data.sheet_by_name('绩效成绩')
print(work_sheet_1)
print(work_sheet_2)
print(work_sheet_3)
运行结果:
返回的结果是一个xlrd.sheet.Sheet对象。
另外如果我们工作表的内容很多的话,我们应该要检查一下这个工作表是否已经完全导入了。检查的方法如下:
check = data.sheet_loaded(sheet_name) #通过工作表名称指定工作表进行检查
check = data.sheet_loaded(sheet_index) #通过工作表索引顺序指定工作表进行检查
比如我们需要检查绩效成绩这个工作表是否导入:
import xlrd #导入模块
data= xlrd.open_workbook("xlrd实例文件.xlsx") #打开excel文件
check = data.sheet_loaded('绩效成绩') # 检查绩效成绩工作表是否导入完毕,完毕则返回true
print(check)
运行结果:
True
好啦,我们要处理的工作表已经得到啦,恭喜大家接下来就是看具体的表格操作了~
注意:山月是以【绩效成绩】工作表为例来给大家分享,它的内容如下:
1)获取工作表名称
我们先来看看现在的工作表是不是我们想要的绩效成绩工作表:
import xlrd #导入模块
data= xlrd.open_workbook("xlrd实例文件.xlsx") #打开excel文件
work_sheet = data.sheet_by_name('绩效成绩') #获取工作表
sheet_name = work_sheet.name #获取工作表名称
print(sheet_name)
运行结果:
绩效成绩
没错,就是我们要的结果。
2)工作表里行(row)的操作
①获取工作表中的有效行数
all_rows = work_sheet.nrows
②获取指定行所有单元格对象组成的列表
有两种表达方式:其中row_number是指定的行数(从0开始计算),返回的列表里是键值对。
row_object = work_sheet.row(row_number)
row_object = work_sheet.row_slice(row_number)
③获取指定行单元格内容组成的列表
获取指定行所有单元格内容组成的列表,row_number为行数(从0开始计算):
row_content = work_sheet.row_values(row_number)
也可以用切片的方式获取指定行里指定从开始列(start_colx,包括)到结束列(end_colx,不包括)的内容组成的列表。
如果没有设置,默认start_colx=0,end_colx=None,end_colx为None表示结束没有限制。
row_content = work_sheet.row_values(row_number, start_colx=0, end_colx=None)
④获取指定行单元格数据类型组成的列表
其中:row_number为行数(从0开始计算),返回的列表是个逻辑值列表,同样可以用切片方式指定列数范围。
row_type = work_sheet.row_types(row_number)
至于逻辑值是什么,我们首先来了解一下常用的单元格的数据类型。
0:empty
1:text
2:number
3:date
4 :boolean
5:error
也就是说若单元格数据类型为empy(空)则逻辑值为0。
⑤获取指定行有效单元格的长度
即获取这一行有多少个数据,row_number为行数(从0开始计算)。
row_length = work_sheet.row_len(row_number)
⑥获取工作表所有行的生成器
rows_generator = work_sheet.get_rows()
知识点:生成器对象是一个可迭代的一个对象,可以用list函数把它转换成列表。
⑦实例
import xlrd #导入模块
data= xlrd.open_workbook("xlrd实例文件.xlsx") #打开excel文件
work_sheet = data.sheet_by_name('绩效成绩') #获取工作表
all_rows = work_sheet.nrows #获取工作表中的有效行数
print(all_rows)
row_object = work_sheet.row_slice(1) #获取第2行所有单元格对象组成的列表
print(row_object)
row_content = work_sheet.row_values(1) #获取第2行所有单元格内容组成的列表
print(row_content)
row_content = work_sheet.row_values(1, start_colx=1, end_colx=2) #获取第2行里第2列单元格内容组成的列表
print(row_content)
row_type = work_sheet.row_types(1) #获取第2行单元格数据类型组成的列表
print(row_type)
row_length = work_sheet.row_len(1) #获取第2行有效单元格的长度
print(row_length)
rows_generator = work_sheet.get_rows() #获取工作表所有行的生成器对象
print(rows_generator)
list_generator = list(rows_generator) #把生成器转换成列表
print(list_generator)
运行结果:
11
[text:'小红', number:2021001.0, number:98.0]
['小红', 2021001.0, 98.0]
[2021001.0]
array('B', [1, 2, 2])
3
. at 0x00000242CFE988B8>
[[text:'姓名', text:'工号', text:'成绩'], [text:'小红', number:2021001.0, number:98.0], [text:'小橙', number:2021002.0, number:100.0], [text:'小黄', number:2021003.0, number:90.0], [text:'小绿', number:2021004.0, number:72.0], [text:'小青', number:2021005.0, number:88.0], [text:'小蓝', number:2021006.0, number:60.0], [text:'小紫', number:2021007.0, number:86.0], [text:'小黑', number:2021008.0, number:60.0], [text:'小白', number:2021009.0, number:76.0], [text:'小彩', number:2021010.0, number:100.0]]
3)工作表里列(column)的操作
列的操作和行的操作是类似的,只是列的操作由row变成了col,我们直接来看例子:
import xlrd #导入模块
data= xlrd.open_workbook("xlrd实例文件.xlsx") #打开excel文件
work_sheet = data.sheet_by_name('绩效成绩') #获取工作表
all_cols = work_sheet.ncols #获取工作表中的有效列数
print(all_cols)
col_object = work_sheet.col_slice(1) #获取第2列所有单元格对象组成的列表
print(col_object)
col_content = work_sheet.col_values(1) #获取第2列所有单元格内容组成的列表
print(col_content)
col_content = work_sheet.col_values(1, start_rowx=1, end_rowx=2) #获取第2列里第2行单元格内容组成的列表
print(col_content)
col_type = work_sheet.col_types(1) #获取第2列单元格数据类型组成的列表
print(col_type)
运行结果:
3
[text:'工号', number:2021001.0, number:2021002.0, number:2021003.0, number:2021004.0, number:2021005.0, number:2021006.0, number:2021007.0, number:2021008.0, number:2021009.0, number:2021010.0]
['工号', 2021001.0, 2021002.0, 2021003.0, 2021004.0, 2021005.0, 2021006.0, 2021007.0, 2021008.0, 2021009.0, 2021010.0]
[2021001.0]
[1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
4)工作表里单元格的操作
①获取指定单元格内容
cell_value = work_sheet.cell(rowx, colx).value
cell_value = work_sheet.cell_value(rowx, colx)
cell_value = work_sheet.row(rowx)[colx].value
其中rowx为指定行,colx为指定列,(rowx, colx)为rowx+1行和colx+1列构成的单元格。
比如(1,1)是第2行第2列这个位置的单元格(B2单元格),即下图红框所示位置。
②获取指定单元格对象
返回的是一个列表,列表里是键值对:
cell_object = work_sheet.cell(rowx, colx)
③获取指定单元格数据类型
数据类型同上:
0 - empty, 1 - text, 2 - number, 3 - date, 4 - boolean, 5 - error
cell_type = work_sheet.cell_type(rowx, colx)
④获取指定单元格内容的类型
注意这是单元格内容的类型,比如内容是数值,则是判断这个数值的类型:
cell_content_type = type(work_sheet.cell_value(rowx, colx))
⑤实例
我们以B2这个单元格为例来综合看看:
import xlrd #导入模块
data= xlrd.open_workbook("xlrd实例文件.xlsx") #打开excel文件
work_sheet = data.sheet_by_name('绩效成绩') #获取工作表
cell_value = work_sheet.cell_value(1, 1) #获取B2单元格内容
print(cell_value)
cell_object = work_sheet.cell(1, 1) #获取B2单元格对象
print(cell_object)
cell_type = work_sheet.cell_type(1, 1) #获取B2单元格数据类型
print(cell_type)
cell_content_type = type(work_sheet.cell_value(1, 1)) #获取B2单元格内容的类型
print(cell_content_type)
运行结果:
2021001.0
number:2021001.0
2
04
实例
1、文件
用我们之前创建的:xlrd实例文件.xlsx,文件内容:
2、目标
我们如果认真看了文件的话,会发现每个员工的绩效工资是其对应的绩效成绩的10倍。100分的绩效成绩就是1000的绩效工资。
假如我们现在只有绩效成绩这一个表,要如何得出绩效工资表的内容?可以自己先想想你要如何做哦~
山月的想法:
读取绩效成绩工作表除表头以外的数据
把绩效成绩*10得到绩效工资
把绩效工资和对应的员工信息组成一组新的数据
写入表头后继续把新得到的数据写入,得到一个新的工作表,然后保存。
我们这篇文章只谈读取数据,写入数据的话下一篇文章再见。因此,我们只来看前三步。
3、代码实现
import xlrd #导入模块
data= xlrd.open_workbook("xlrd实例文件.xlsx") #打开excel文件
work_sheet = data.sheet_by_name('绩效成绩') #获取绩效成绩工作表
# 获取除表头外全部行内容
rows_generator = list(work_sheet.get_rows())[1:]
#创建个列表来储存名字、工号、绩效工资数据
row_list=[]
#利用for循环,得到名字、工号、绩效成绩
for rows in rows_generator:
name, number, score = rows[0].value, rows[1].value, rows[2].value
#利用绩效成绩得出绩效工资
money = score*10
#把名字、工号和新得的绩效工资一起组成一个元组
row_tuple=(name,number,money)
#把元组添加到之前建的列表里
row_list.append(row_tuple)
print(row_list) #打印列表
运行结果:
[('小红', 2021001.0, 980.0), ('小橙', 2021002.0, 1000.0), ('小黄', 2021003.0, 900.0), ('小绿', 2021004.0, 720.0), ('小青', 2021005.0, 880.0), ('小蓝', 2021006.0, 600.0),
('小紫', 2021007.0, 860.0), ('小黑', 2021008.0, 600.0), ('小白', 2021009.0, 760.0), ('小彩', 2021010.0, 1000.0)]
05
问题集锦
5.1 实战问题
不知道大家有没有发现一个问题:如果单元格里是数值类型,那返回的值自带小数点。比如小红的工号是2021001,返回的值为2021001.0。
那要怎么办呢?山月提供了两个解决方法:
1)在表格里是数值的单元格内容前加一个英文的单引号,把它变成以文本形式储存的数字。
2)通过代码判断单元格内容是否为浮点型
比如针对工号,解决代码:
import xlrd #导入模块
data= xlrd.open_workbook("xlrd实例文件.xlsx") #打开excel文件
work_sheet = data.sheet_by_name('绩效成绩') #获取绩效成绩工作表
col_content = work_sheet.col_values(1)[1:] #获取第2列除表头外的所有单元格数据组成的列表
print(col_content)
print('解决后的结果:')
for i in range(len(col_content)):
if col_content[i] % 1 == 0.0: #判断数据是否为浮点型
col_content[i] = int(col_content[i]) # 浮点转成整型
print(col_content)
运行结果:
[2021001.0, 2021002.0, 2021003.0, 2021004.0, 2021005.0, 2021006.0, 2021007.0, 2021008.0, 2021009.0, 2021010.0]
解决后的结果:
[2021001, 2021002, 2021003, 2021004, 2021005, 2021006, 2021007, 2021008, 2021009, 2021010]
5.2 拓展问题
这个问题我们本次例子中没有遇到,但这是一个非常常见的问题,山月在学习得时候就遇到过。
问题:如果遇到日期格式的数据,xlrd不能直接读取。我们来看看例子。
有一个表格,它的内容如下:
我们直接按照之前讲的方法来读取看看:
import xlrd #导入模块
data= xlrd.open_workbook("日期.xlsx") #打开excel文件
work_sheet = data.sheet_by_index(0) #获取工作表
col_content = work_sheet.col_values(0) #获取第1列所有单元格数据组成的列表
print(col_content)
col_type = work_sheet.col_types(0) #获取第1列所有单元格数据类型组成的列表
print(col_type)
运行结果:
['日期', 44541.0, 44542.0, 44543.0, 44544.0, 44545.0, 44546.0, 44547.0, 44548.0]
[1, 3, 3, 3, 3, 3, 3, 3, 3]
根据结果来看,除了表头外,单元格的数据类型都是3,也就是日期格式,这个没有问题。
但是内容却不对了,比如A2这个单元格是2021-12-11,读出来却是44541.0。
这是因为Excel的日期是相对于基准日期(1900-01-01)为起点的天数数值。也就是说1900-01-01是1,1900-01-02是2...相应的2021-12-11是44541。
知识点:在python里一共有两个时间基准。0代表以1900-01-01为基准,1代表以1904-01-01为基准,一般使用1900-01-01为基准。
而对于日期的读取,xlrd有两种解决方法。
方法一:xlrd.xldate_as_tuple(xldate,datemode)
参数 xldate表示要处理的单元格值
参数 datemode 表示时间基准,也就是0或1。
date_cell = xlrd.xldate_as_tuple(work_sheet.cell_value(rowx, colx), 0) #以基准1900-01-01读取指定单元格,rowx为指定单元格行数,colx为指定单元格列数
它会返回一个元组:(年, 月, 日, 时, 分, 秒)。
当然,我们最终是要得到日期,所以要把自动填补的时间去掉。由于它是个元组,所以我们能利用索引轻易的得到对应的日期。
以A2单元格为例:
import xlrd #导入模块
data= xlrd.open_workbook("日期.xlsx") #打开excel文件
work_sheet = data.sheet_by_index(0) #获取工作表
date_cell = xlrd.xldate_as_tuple(work_sheet.cell_value(1, 0), 0) #读取A2单元格
print(date_cell)
date_cell_finally = '%d-%d-%d' %(date_cell[0],date_cell[1],date_cell[2]) #利用索引得到对应的年月日,并用-连接
print(date_cell_finally)
运行结果:
(2021, 12, 11, 0, 0, 0)
2021-12-11
同样,它的参数 xldate表示要处理的单元格值,参数 datemode 表示时间基准,也就是0或1。
date_cell = xlrd.xldate.xldate_as_datetime(work_sheet.cell(rowx,colx).value, 0) #以基准1900-01-01读取指定单元格,rowx为指定单元格行数,colx为指定单元格列数
它会返回一个datetime对象,格式是:年-月-日 时:分:秒。
对于这个对象,我们可以用strftime来处理,把它转化成指定格式的字符串。
对日期和时间进行格式化的符号:
同样对于A2单元格,我们想得到它对应的日期:
import xlrd #导入模块
data= xlrd.open_workbook("日期.xlsx") #打开excel文件
work_sheet = data.sheet_by_index(0) #获取工作表
date_cell = xlrd.xldate.xldate_as_datetime(work_sheet.cell(1,0).value, 0) #读取A2单元格
print(date_cell)
date_cell_finally = date_cell.strftime("%Y/%m/%d") #利用strftime转化成年/月/日
print(date_cell_finally)
运行结果:
2021-12-11 00:00:00
2021/12/11
好啦,今天的分享就到这,希望大家都能熟练的掌握xlrd的用法,以及通过这个学习,了解python处理excel的方法思路。
我们下次再见!
已经到底啦~(≧▽≦*)/~
自学Python一年后,我有这些想说
2021-12-04
建议收藏:68个Python内置函数详解
2021-12-05
初识Tkinter:一些必须掌握的基础知识
2021-12-09