上周收到任务:统计实验成绩。我一看这不就是处理excel数据吗!想都不用想,这种简单重复的工作写一段python代码处理不就很快就能完成了吗?!
1. 简单介绍openpyxl
用python处理excel可选的模块多了去了(开源大法好!!),有openpyxl、pandas、xlrd和xlwt...我使用的是python官方推荐的openpyx。
打开已有的excel
from openpyxl import *
wb = load_workbook('test.xlsx')
第一句代码导入openpyxl模块。第二句代码打开一个已存在的工作本,所谓工作本就是一个excel文件。若test.xlsx不存在则抛出错误。
获取工作簿
ws = wb.worksheets[0]
从工作本wb中获取工作簿。索引0表示第一个工作簿。
获取行数
MAX_ROW = ws.max_row
max_row是ws的一个属性,表示该工作簿的行数。
获取和修改单元格的数据
cell_value = ws['F5'].value
ws['E6'].value = 666
第一句把第F列第5行的单元格的数据赋值给变量cell_value。第二句把第E列第6行的单元格的值设为666。
F5和E6这样对单元格的表示方式和excel中是完全一样的!一定要先写字母在前,数字在后,否则会报错。
好了,我们对于openpyxl的学习到此结束...openpyxl还提供了很多很好用的功能,但对于此问题,我们掌握以上几条代码就够了。
2. datetime和time
在处理数据之前必须要了解一下datetime和time。
我所说的datetime和time都是属于datetime这个模块的,即datetime.datetime和datetime.time。
简单来说,datetime既有date又有time,即既有年日月,又有时分秒。而time只有time,即只有时分秒。
需要注意,无论是datetime还是time,time部分最多能表示到23:59:59。
可以看出,datetime是包含time的。
t = dt.time()
从一个datetime对象中取其time部分。dt是datetime的一个实例对象。
还需要从str类型转换到datetime类型的方法。
s = '03:33:44'
pattern = '%H:%M:%S'
dt = datetime.strptime(s, pattern)
s是str类型的,其以':'分割了时分秒,因此在pattern中,同样以':'分割时分秒。
%H、%M、%S指定s中时分秒的位置(%M指定了33)。
需要注意,s的范围必须是00:00:00-23:59:59,否则会转换失败。
年月日没有指定,默认为1900年1月1日。这个方法的用处在后面说。
3. 单元格数据和变量数据
如下,注意看准行列就行了~
提交通过的题,会显示其和实验开始时刻的时间差。有的单元格内含有括号,括号内是提交错误的次数。如果没有提交过,那么该单元格为空。
会出现的数据类型及格式:
time:形如03:33:44,表示3时33分44秒提交通过
datetime:形如25:10:11,表示25时10分11秒提交通过。因为25>23,所以自动转换成datetime,其实际时间为1900年1月2日1时10分11秒。可以看出,时间减了24,日增加了1。
str:形如25:10:11(-2),表示25时10分11秒提交通过,并且有2次提交错误。因为(-2)无法用时间表示,所以自动转换成str。
None:空,表示不曾提交过。
要求:A题35分,B题35分,C题20分,D题10分。逾期提交通过的题只能得到满分的90%。记录逾期提交的题~
4. 代码思路
脑子一定要清醒,一样一样来。
先看None,表示未曾提交过,直接返回0,表示得该题0%的分数。
然后看datetime,表示通过了,但时间已经超过24小时,属于逾期提交通过,返回0.9,表示得该题90%的分数。
再看time,需要比较是否逾期。定义一个time类型的变量DEADLINE用于比较。看返回0.9还是1。不定义成datetime类型是因为time类型更简单。
最后看str,是真的麻烦...
如果cell_value含有括号,把括号去掉,因为提交错误的次数不影响分数。剩下的部分可能是datetime的形式(25:10:11),也可能是time的形式(23:59:59)。
取前两个字符转化成数字类型h,如果h>23,说明超过23小时,属于逾期提交通过,返回0.9。
否则,转化成time类型和DEADLINE比较。这就用到前面的str转datetime方法得到datetime,再得到time。(没有str直接转time的方法,所以经过datetime)
5.代码
isinstance()用来判断某变量是否属于某类,如isinstance(1, int),返回True。
def count(cell_value):
# None
if not cell_value:
return 0
# datetime 逾期提交通过
if isinstance(cell_value, datetime):
return 0.9
if isinstance(cell_value, str):
# 去括号
pos = cell_value.find('(')
if pos != -1:
cell_value = cell_value[0:pos]
# 去括号之后为空字符串'' 表示一直提交 不通过
if not cell_value:
return 0
else:
h = int(cell_value[0:2])
# h > 23 逾期提交通过
if(h > 23):
return 0.9
# 转化成time 留到下面比较
else:
cell_value = str2time(cell_value)
# 和 DEADLINE 比较
if cell_value <= DEADLINE:
return 1
else:
return 0.9
str->time:
def str2time(s):dt = datetime.strptime(s, "%H:%M:%S")return dt.time()
初始化~
FILE_NAME = 'test.xlsx'wb = load_workbook(FILE_NAME)ws = wb.worksheets[0]MAX_ROW = ws.max_row# 根据实际情况设置开始的行数START_ROW = 3# 根据实际情况设置DEADLINEDEADLINE = str2time('03:30:00')
对A题的判断~
# 保存逾期提交的题late = ''sum_score = 0# 千万不要写成 ws['A' + row]cell_value = ws['F' + row].valuec = count(cell_value)score = c * 35sum_score += scoreif c == 0.9:late += 'A 'ws['J' + row].value = score
主要代码就是这些,如果有其他要求,在此基础上稍微修改就行。
转自公众号「小z的笔记本」
每周更新各种内容
包括但不限于Python、爬虫、其他骚操作
欢迎关注
原文链接:https://blog.csdn.net/qq_41177763/article/details/105518216