对excel文件进行操作python(Python其实很简单第十八章)
对excel文件进行操作python(Python其实很简单第十八章)数学语文姓名年级班级
虽然Excel有很多函数,可以进行数据处理,但要想做到灵活、方便、个性化却比较困难。如果运用比较熟练,用Python处理Excel中的数据也很方便,并且将程序保存起来,一直可以解决相同的问题。
在本章中,将以如下Excel文件student.xlsx(表18-1)为例进行探讨。
| 
     序号  | 
     学号  | 
     姓名  | 
     年级  | 
     班级  | 
     语文  | 
     数学  | 
     英语  | 
     总分  | 
     名次  | 
| 
     1  | 
     070101  | 
     王博宇  | 
     84  | 
     71  | 
     93  | ||||
| 
     2  | 
     070102  | 
     陈冠涛  | 
     89  | 
     89  | 
     89  | ||||
| 
     3  | 
     070103  | 
     李文博  | 
     89  | 
     72  | 
     76  | ||||
| 
     4  | 
     070204  | 
     姜海燕  | 
     89  | 
     89  | 
     89  | ||||
| 
     5  | 
     070205  | 
     林若溪  | 
     91  | 
     95  | 
     83  | ||||
| 
     6  | 
     070206  | 
     贾梦瑶  | 
     72  | 
     60  | 
     64  | ||||
| 
     7  | 
     070207  | 
     陈怡彤  | 
     77  | 
     74  | 
     87  | ||||
| 
     8  | 
     070208  | 
     王星辰  | 
     79  | 
     87  | 
     89  | ||||
| 
     9  | 
     070301  | 
     马美玲  | 
     90  | 
     71  | 
     58  | ||||
| 
     10  | 
     070302  | 
     蒋倩颖  | 
     96  | 
     88  | 
     68  | ||||
| 
     11  | 
     070303  | 
     侯宇博  | 
     97  | 
     100  | 
     95  | ||||
| 
     12  | 
     080304  | 
     陈琳娜  | 
     69  | 
     52  | 
     59  | ||||
| 
     13  | 
     080305  | 
     焦可菲  | 
     80  | 
     59  | 
     64  | ||||
| 
     14  | 
     080306  | 
     王思晨  | 
     54  | 
     69  | 
     68  | ||||
| 
     15  | 
     080401  | 
     张雨桐  | 
     89  | 
     67  | 
     55  | ||||
| 
     16  | 
     080402  | 
     陈丹妮  | 
     57  | 
     72  | 
     55  | ||||
| 
     17  | 
     080403  | 
     蒋璐茜  | 
     94  | 
     85  | 
     51  | ||||
| 
     18  | 
     080404  | 
     马丁  | 
     83  | 
     83  | 
     73  | ||||
| 
     19  | 
     080405  | 
     陈可儿  | 
     100  | 
     69  | 
     91  | ||||
| 
     20  | 
     080406  | 
     路易  | 
     72  | 
     87  | 
     85  | ||||
| 
     21  | 
     090101  | 
     陈佳明  | 
     101  | 
     89  | 
     98  | ||||
| 
     22  | 
     090104  | 
     王克非  | 
     45  | 
     76  | 
     65  | ||||
| 
     23  | 
     090301  | 
     马依琳  | 
     78  | 
     87  | 
     95  | ||||
| 
     24  | 
     091101  | 
     王一诺  | 
     108  | 
     104  | 
     98  | ||||
| 
     25  | 
     091204  | 
     贾宇轩  | 
     98  | 
     77  | 
     98  | ||||
| 
     26  | 
     090303  | 
     贾朝轩  | 
     118  | 
     112  | 
     76  | ||||
| 
     27  | 
     090808  | 
     白丽娜  | 
     87  | 
     86  | 
     76  | ||||
| 
     28  | 
     090807  | 
     金海通  | 
     76  | 
     89  | 
     98  | ||||
| 
     29  | 
     090802  | 
     丁能通  | 
     119  | 
     120  | 
     99  | ||||
| 
     30  | 
     090203  | 
     沈丹妮  | 
     109  | 
     108  | 
     99  | ||||
| 
     31  | 
     090314  | 
     关立新  | 
     103  | 
     107  | 
     100  | 
在表18-1中,学号信息由6位数字字符构成,前两位表示年级信息,中间两位表示班级信息,后两位表示班内编号。
18.1关于xlrd模块
在python中,xlrd库是一个很常用的读取excel文件的库,其对excel文件的读写可以实现比较精细的控制。这是一种底层的操作,虽然现在已经不太常用,但在很多时候仍被较多使用。特别是在不知道类似pandas这样的库的使用方法的情况下,可以快速的使用xlrd库。
它是一个第三方库,可以在命令行中使用命令安装:
pip install xlrd
安装完成后,可以使用 pip list检查是否安装成功。
18.2读取Excel中的数据
先看下面的例子:
import xlrd
file='d:\\student.xlsx'
book = xlrd.open_workbook(file) # 打开工作簿
print('当前工作表名称:' book.sheet_names()) # 输出当前工作表的名称
sheet = book.sheet_by_index(0) #sheet变量赋值为第1个工作表
rows = sheet.nrows #rows为行数
cols = sheet.ncols #cols为列数
print('该工作表有%d行,%d列.'%(rows cols))
print('第三行内容为:' sheet.row_values(2))
print('第二列内容为%s 数据类型为%s.'%(sheet.col_values(1) type(sheet.col_values(1))))
print('第二列内容为%s 数据类型为%s.'%(sheet.col(1) type(sheet.col(1))))
print('第二行第二列的单元格内容为:' sheet.cell_value(1 1))
print('第三行第二列的单元格内容为:' sheet.cell(2 1).value)
print('第五行第三列的单元格内容为:' sheet.row(4)[2].value)
print('第五行第三列的单元格内容为%s 数据类型为%s'%(sheet.col(2)[4].value type(sheet.col(2)[4].value)))
print('第五行第三列的单元格内容为%s 数据类型为%s'%(sheet.col(2)[4] type(sheet.col(2)[4])))
输出结果为:
sheet页名称: ['Sheet1']
该工作表有21行,9列.
第三行内容为: ['2' '180102' '陈冠涛' '' 89.0 89.0 89.0 '' '']
第二列内容为['学号' '180101' '180102' '180103' '180204' '180205' '180206' '180207' '180208' '180301' '180302' '180303' '180304' '180305' '180306' '180401' '180402' '180403' '180404' '180405' '180406'] 数据类型为<class 'list'>.
第二列内容为[text:'学号' text:'180101' text:'180102' text:'180103' text:'180204' text:'180205' text:'180206' text:'180207' text:'180208' text:'180301' text:'180302' text:'180303' text:'180304' text:'180305' text:'180306' text:'180401' text:'180402' text:'180403' text:'180404' text:'180405' text:'180406'] 数据类型为<class 'list'>.
第二行第二列的单元格内容为: 180101
第三行第二列的单元格内容为: 180102
第五行第三列的单元格内容为: 姜海燕
第五行第三列的单元格内容为姜海燕 数据类型为<class 'str'>
第五行第三列的单元格内容为text:'姜海燕' 数据类型为<class 'xlrd.sheet.Cell'>
在上面的代码中,读取单元格数据值的方法有好几种,我们只需要掌握其中最常用的方法就可以了,如sheet.cell(2 1).value或sheet.cell_value(1 1),因为它最接近Excel的单元格表示方法。只要你了解Excel,一定会使用这两种表示方法。
18.3向Excel中的写入数据
向Excel写入数据时,需要使用第三方库xlwt。安装xlwt的方法与安装xlrd一样,在命令行输入:
pip install xlwt
下面举例说明写入数据:
import xlwt
book = xlwt.Workbook() #新建Excel文件对象
sheet = book.add_sheet('Sheet1') #添加工作表
sheet.write(0 0 'hello') #向第1行第1列写入数据
sheet.write(1 0 '你好') #向第2行第1列写入数据
book.save('d:\hello.xls') #保存文件
18.4处理Excel文件中的数据
1、求和
既可以对Excel表横向求和(行内求和,譬如每个学生的总分),也可以纵向求和(列内求和,譬如计算语文总分、数学总分等)。
2、获取年级和班级信息
在student.xlsx中,每个学生的学号信是用一个字符串表示的,字符串长度为6个字符,前两个字符为年级信息,接下来两个字符为班级信息,最后两个字符为班内编号。截取学号的前两个字符即可得到年级信息,截取学号的中间两个字符即可得到班级信息。
3、分班级统计平均分、及格率、优秀率、双科(语文、数学)合格率、三科(语文、数学、英语)合格率。同时,生成一个新的Excel文件stuscores.xlsx,并将上述统计结果写入。
为了便于初学者阅读学习,下面代码没有进一步优化。
import xlrd #导入读取Excel文件的模块
import xlwt #导入写入Excel文件的模块
file='d:\\student.xlsx' #该文件为原始数据(见表18-1)
book = xlrd.open_workbook(file) #以读取方式打开Excel工作簿
sheet = book.sheet_by_index(0) #变量赋值为当前工作簿的第一个工作表
rows = sheet.nrows #变量rows表示工作表的行数
cols = sheet.ncols #变量cols表示工作表的列数
bookNew=xlwt.Workbook() #以写入方式建立一个新的工作簿
sheetNew1=bookNew.add_sheet('Sheet1') #为工作簿添加一个新的工作表
sheetNew2=bookNew.add_sheet('Sheet2') #为工作簿添加一个新的工作表
#计算第5列(语文)、第6列(数学)、第7列(英语)的和(列号从0开始)
sum5=0 #变量sum5表示第5列和
sum6=0 #变量sum6表示第6列和
sum7=0 #变量sum7表示第7列和
#遍历第1行到最后1行(第0行为标题行,非成绩,最后一行为rows-1)
for i in range(1 rows):
sum5 =float(sheet.cell(i 5).value) # float函数为了将非数值转为为浮点数
sum6 =float(sheet.cell(i 6).value)
sum7 =float(sheet.cell(i 7).value)
col8=[0]
#列表col8存放每一个学生的总分,即每一行第5、6、7列的和,第一个元素为0是为了给标题行占位,这样列表的索引号正好与表格的行号对应
col3=[''] #列表col3存放年级信息,第一个元素为空字符
col4=[''] #列表col4存放班级信息,第一个元素为空字符
#遍历各行,为第3 4 8列准备数据,数据暂时存放在列表中
for i in range(1 rows):
total=0 #变量total存放每个学生的三科总分
for j in range(5 8): #遍历行内的第5至7列
total =float(sheet.cell(i j).value)
col8.append(total) #将合计追加到列表col8中
strno=str(sheet.cell(i 1).value) #变量strno为学号信息
col3.append(strno[:2]) #对字符串切片获取年级信息,存入列表col3中
col4.append(strno[:4])
#对字符串切片获取班级信息,存入列表col3中(取了前四位,包含了年级信息)
for i in range(rows): #遍历各行,从第0行到最后一行
for j in range(cols): #遍历各列,从第0列到最后一列
if sheet.cell(i j).value!='':
sheetNew1.write(i j sheet.cell(i j).value)
#如果原表单元格非空,则将原表单元格的值写入新表中对应的单元格中
elif j==3:
sheetNew1.write(i 3 col3[i]) #将列表col3中的值写入对应单元格
elif j==4:
sheetNew1.write(i 4 col4[i]) #将列表col4中的值写入对应单元格
elif j==8:
sheetNew1.write(i 8 col8[i]) #将列表col8中的值写入对应单元格
sheetNew1.write(rows 5 sum5) #在第rows行(新增行)第5列写入语文合计值
sheetNew1.write(rows 6 sum6) #在第rows行(新增行)第6列写入数学合计值
sheetNew1.write(rows 7 sum7) #在第rows行(新增行)第6列写入英语合计值
'''
至此,完成了新建Excel文件中Sheet1工作表数据的填充工作。
在表18-1中还有一个根据总分对学生进行排名的问题,但如果采用通常的算法效率太低,
还是建议采用Excel函数进行排名为宜,这里不再赘述。
'''
grade=[] #列表grade用于存放年级编号
for i in col3[1:]: #遍历列表col3(索引号为0的元素除外)
if i not in grade:
#为了保证列表grade中的元素值都是唯一的,即年级编号不重复
grade.append(i)
grade.sort #对列表grade排序
classno=[] #列表classno用于存放班级编号
for i in col4[1:]: #遍历列表col4(索引号为0的元素除外)
if i not in classno:
#为了保证列表classno中的元素值都是唯一的,即班级编号不重复
classno.append(i)
classno.sort #对列表classno排序
sumChnC=0 #全班语文总分
sumMathC=0 #全班数学总分
sumEnC=0 #全班英语总分
sumChnG=0 #全级语文总分
sumMathG=0 #全级数学总分
sumEnG=0 #全级英语总分
numClass=0 #班级学生人数
numGrade=0 #年级学生人数
passChnC=0 #全班语文及格人数
passMathC=0 #全班数学及格人数
passEnC=0 #全班英语及格人数
passChnG=0 #全级语文及格人数
passMathG=0 #全级数学及格人数
passEnG=0 #全级英语及格人数
excellenChnC=0 #全班语文优秀人数
excellenMathC=0 #全班数学优秀人数
excellenEnC=0 #全班英语优秀人数
excellenChnG=0 #全级语文优秀人数
excellenMathG=0 #全级数学优秀人数
excellenEnG=0 #全级英语优秀人数
pass2C=0 #全班双科及格人数
pass3C=0 #全班三科及格人数
pass2G=0 #全级双科及格人数
pass3G=0 #全级三科及格人数
excellen2C=0 #全班双科优秀人数
excellen3C=0 #全班三科优秀人数
excellen2G=0 #全级双科优秀人数
excellen3G=0 #全级三科优秀人数
passChn=72 #语文及格线
passMath=72 #数学及格线
passEn=60 #英语及格线
excellenChn=96 #语文优秀线
excellenMath=96 #数学优秀线
excellenEn=80 #英语优秀线
n=1 #变量n表示'班级成绩统计表'的行号
font = xlwt.Font()
#创建字体对象实例,并初始化
font.height = 20 * 11
#设置字体大小,11为字号,20为衡量单位
font.bold = True #字体加粗
alignment = xlwt.Alignment() #创建单元格对齐方式实例,并初始化
alignment.horz = 0x02 #设置单元格水平对齐方式
# 0x01(左端对齐)、0x02(水平方向上居中对齐)、0x03(右端对齐)
alignment.vert = 0x01
# 0x00(上端对齐)、0x01(垂直方向上居中对齐)、0x02(底端对齐)
style = xlwt.XFStyle() #创建式样实例,并初始化
style.alignment = alignment # 设置式样的对齐方式属性值
style.font = font # 设置式样的字体属性
sheetNew2.write_merge(0 0 0 16 '班级成绩统计表' style)
'''
xlwt模块的合并单元格函数
格式:worksheet.write_merge(开始行 结束行 开始列 结束列 字符串 style)
'''
sheetNew2.write(n 0 '序号' style) #第1行第0列单元格的内容,以下类似
sheetNew2.write(n 1 '年级' style)
sheetNew2.write(n 2 '班级' style)
sheetNew2.write(n 3 '人数' style)
sheetNew2.write(n 4 '语均' style)
sheetNew2.write(n 5 '语及' style)
sheetNew2.write(n 6 '语优' style)
sheetNew2.write(n 7 '数均' style)
sheetNew2.write(n 8 '数及' style)
sheetNew2.write(n 9 '数优' style)
sheetNew2.write(n 10 '英均' style)
sheetNew2.write(n 11 '英及' style)
sheetNew2.write(n 12 '英优' style)
sheetNew2.write(n 13 '双合' style)
sheetNew2.write(n 14 '双优' style)
sheetNew2.write(n 15 '三合' style)
sheetNew2.write(n 16 '三优' style)
'''
以下代码为统计各班级、各年级各科平均成绩、及格率、优秀率、双科合格率、
双科优秀率、三科合格率、三科优秀率,并将这些数据写入Excel文件的对应单元格中。
'''
for g in grade: #遍历各年级
for c in classno: #遍历各班级
if g != c[:2]: #判断班级是否是年级所属的班级
continue #若不是年级所属班级,遍历下一个班级
n =1 #变量n控制写入Excel行号变化
for i in range(1 rows): #遍历原始数据表student.xlsx各行
strno=str(sheet.cell(i 1).value) #变量strno赋值为学号值
if strno[:2]==g and strno[:4]==c: #如果是该年级和班级的学生
fpass2=0 #变量fpass2表示两科及格科目数
fpass3=0 #变量fpass3表示三科及格科目数
fexcellen2=0 #变量fexcellen2表示两科优秀科目数
fexcellen3=0 #变量fexcellen3表示三科优秀科目数
numClass =1 #变量numClass表示班级学生人数
sumChnC =float(sheet.cell(i 5).value)
#变量sumChnC记录全班语文总分
sumMathC =float(sheet.cell(i 6).value)
#变量sumMathC记录全班数学总分
sumEnC =float(sheet.cell(i 7).value)
#变量sumEnC记录全班数学总分
if float(sheet.cell(i 5).value) >= passChn:
#如果该生语文成绩及格
passChnC =1 #记录全班语文及格人数
fpass2 =1 #记录两科及格科目数
fpass3 =1 #记录三科及格科目数
if float(sheet.cell(i 5).value)>= excellenChn:
#如果该生语文成绩优秀
excellenChnC =1 #记录全班语文优秀人数
fexcellen2 =1 #记录两科优秀科目数
fexcellen3 =1 #记录三科优秀科目数
if float(sheet.cell(i 6).value) >= passMath:
#如果该生数学成绩及格
passMathC =1 #记录全班数学及格人数
fpass2 =1 #记录两科及格科目数
fpass3 =1 #记录三科及格科目数
if float(sheet.cell(i 6).value) >= excellenMath:
#如果该生数学成绩优秀
excellenMathC =1 #记录全班数学优秀人数
fexcellen2 =1 #记录两科优秀科目数
fexcellen3 =1 #记录三科优秀科目数
if float(sheet.cell(i 7).value) >= passEn:
#如果该生英语成绩及格
passEnC =1 #记录全班英语及格人数
fpass3 =1 #记录三科及格科目数
if float(sheet.cell(i 7).value) >= excellenEn:
#如果该生英语成绩优秀
excellenEnC =1 #记录全班英语优秀人数
fexcellen3 =1 #记录三科优秀科目数
if fpass2 == 2: #条件成立表明该生两科合格
pass2C =1 #班级两科合格人数增加1
if fpass3 == 3: #条件成立表明该生三科合格
pass3C =1 #班级三科合格人数增加1
if fexcellen2 == 2: #条件成立表明该生两科优秀
excellen2C =1 #班级两科优秀人数增加1
if fexcellen3 == 3: #条件成立表明该生三科优秀
excellen3C =1 #班级三科优秀人数增加1
sheetNew2.write(n 0 n-1) #写入序号
sheetNew2.write(n 2 c) #写入班级编号
sheetNew2.write(n 3 numClass) #写入班级人数
sheetNew2.write(n 4 round(sumChnC/numClass 2))
#写入全班语文平均分
sheetNew2.write(n 5 round(passChnC/numClass*100 2))
#写入全班语文及格率
sheetNew2.write(n 6 round(excellenChnC/numClass*100 2))
#写入全班语文优秀率
sheetNew2.write(n 7 round(sumMathC/numClass 2))
#写入全班数学平均分
sheetNew2.write(n 8 round(passMathC/numClass*100 2))
#写入全班数学及格率
sheetNew2.write(n 9 round(excellenMathC/numClass*100 2))
#写入全班数学优秀率
sheetNew2.write(n 10 round(sumEnC/numClass 2))
#写入全班英语平均分
sheetNew2.write(n 11 round(passEnC/numClass*100 2))
#写入全班英语及格率
sheetNew2.write(n 12 round(excellenEnC/numClass*100 2))
#写入全班英语优秀率
sheetNew2.write(n 13 round(pass2C/numClass*100 2))
#写入全班两科合格率(语文、数学两科同时达到及格线)
sheetNew2.write(n 14 round(excellen2C/numClass*100 2))
#写入全班两科优秀率(语文、数学两科同时达到优秀线)
sheetNew2.write(n 15 round(pass3C/numClass*100 2))
#写入全班三科合格率(语文、数学、英语三科同时达到及格线)
sheetNew2.write(n 16 round(excellen3C/numClass*100 2))
#写入全班三科优秀率(语文、数学、英语三科同时达到优秀线)
numGrade =numClass #将班级学生人数增加到年级学生人数
sumChnG =sumChnC #将班级语文总分增加到年级语文总分
sumMathG =sumMathC #将班级数学总分增加到年级数学总分
sumEnG =sumEnC #将班级英语总分增加到年级英语总分
passChnG =passChnC #将班级语文及格人数增加到年级语文及格人数
passMathG =passMathC #将班级数学及格人数增加到年级数学及格人数
passEnG =passEnC #将班级英语及格人数增加到年级英语及格人数
excellenChnG =excellenChnC
#将班级语文优秀人数增加到年级语文优秀人数
excellenMathG =excellenMathC
#将班级数学优秀人数增加到年级数学优秀人数
excellenEnG =excellenEnC
#将班级英语优秀人数增加到年级优秀优秀人数
pass2G =pass2C
#将班级两科合格人数增加到年级两科合格人数
pass3G =pass3C
#将班级三科合格人数增加到年级三科合格人数
excellen2G =excellen2C
#将班级两科合优秀人数增加到年级两科优秀人数
excellen3G =excellen3C
#将班级三科合优秀人数增加到年级三科优秀人数
numClass=0
#变量numClass(班级人数)设置为0,为统计下一个班级的信息做准备
sumChnC=0 #与上语句类似,下同
sumMathC=0
sumEnC=0
passChnC=0
passMathC=0
passEnC=0
excellenChnC=0
excellenMathC=0
excellenEnC=0
pass2C=0
pass3C=0
excellen2C=0
excellen3C=0
n =1 #行号增加1,为了在下一行填入年级的统计数据
sheetNew2.write(n 0 n-1) #写入序号
sheetNew2.write(n 1 g) #写入年级编号
sheetNew2.write(n 3 numGrade) #写入年级人数
sheetNew2.write(n 4 round(sumChnG/numGrade 2))
#写入全级语文平均分
sheetNew2.write(n 5 round(passChnG/numGrade*100 2))
#写入全级语文及格率
sheetNew2.write(n 6 round(excellenChnG/numGrade*100 2))
#写入全级语文优秀率
sheetNew2.write(n 7 round(sumMathG/numGrade 2))
#写入全级数学平均分
sheetNew2.write(n 8 round(passMathG/numGrade*100 2))
#写入全级数学及格率
sheetNew2.write(n 9 round(excellenMathG/numGrade*100 2))
#写入全级数学优秀率
sheetNew2.write(n 10 round(sumEnG/numGrade 2))
#写入全级英语平均分
sheetNew2.write(n 11 round(passEnG/numGrade*100 2))
#写入全级英语及格率
sheetNew2.write(n 12 round(excellenEnG/numGrade*100 2))
#写入全级英语优秀率
sheetNew2.write(n 13 round(pass2G/numGrade*100 2))
#写入全级两科合格率(语文、数学两科同时达到及格线)
sheetNew2.write(n 14 round(excellen2G/numGrade*100 2))
#写入全级两科优秀率(语文、数学两科同时达到优秀线)
sheetNew2.write(n 15 round(pass3G/numGrade*100 2))
#写入全级三科合格率(语数英三科同时达到及格线)
sheetNew2.write(n 16 round(excellen3G/numGrade*100 2))
#写入全级三科优秀率(语数英三科同时达到优秀线)
numGrade=0
#变量numGrade(年级人数)设置为0,为统计下一个年级的信息做准备
sumChnG=0 #与上语句类似,下同
sumMathG=0
sumEnG=0
passChnG=0
passMathG=0
passEnG=0
excellenChnG=0
excellenMathG=0
excellenEnG=0
pass2G=0
pass3G=0
excellen2G=0
excellen3G=0
bookNew.save('d:\stuscores.xlsx') #保存Excel文件
运行结果如图18-2所示。对于表格的各种格式设置,在Excel中设置远比用Python命令设置更方便,所以仅仅用Python完成各种计算即可,然后在Excel中按照需要完成各种格式设置。

图18-2




