教务成绩核查-半自动化解决方案
近期交大教务系统核查本科生成绩(使用原始成绩与教务系统成绩进行比对),教务处给出的方案是excel比对,感觉效率不高,故写此程序以提高效率。至于为什么是“半自动化解决方案”,是因为文档需要与程序在同一目录下(因为懒没写路径),且“原始成绩文档”、“教务成绩文档”、“文档中学号和成绩的位置”、“缺考标记”、“开始检测位置”需要手动调整。(因为懒没写位置判断)尽管如此,核查一个班的成绩的速度也可以保持在10秒以内,算是达到了提高效率的目的。
源代码
import pandas as pd
import warnings
file1 = pd.read_excel('序号08.xlsx',sheet_name='成绩简表') #原始成绩表格
#file1 = pd.read_excel('4.xlsx',sheet_name='Export')
rowsFile1=len(file1)
# id=file1.iloc[0:rowsFile1,6]
# score=file1.iloc[0:rowsFile1,10]
id=file1.iloc[0:rowsFile1,1] #学号
score=file1.iloc[0:rowsFile1,6] #成绩
idToScore={} #学号映射四舍五入成绩
idToScoreFloat={} #学号映射原始成绩
for i in range(len(id)):
if score[i] != '-': #原表中默认无成绩显示为“-”
idToScore[str(id[i])]=int(float(score[i])+0.5) #四舍五入,round实际上是“四舍六入五成偶”,故直接使用会出问题
idToScoreFloat[str(id[i])] = str(float(score[i]))
else:
idToScore[str(id[i])] = 0
idToScoreFloat[str(id[i])] = '-'
warnings.filterwarnings("ignore", message="Workbook contains no default style, apply openpyxl's default") #忽略默认样式警告
file2 = pd.read_excel('毛概.xlsx',sheet_name='sheet1') #教务系统成绩表格
rowsFile2=len(file2)
flag=0 #记录是否出现错误
for i in range(5,rowsFile2):
if file2.iloc[i,1] not in idToScore:
print("该学生未在总成绩表中出现:"+ file2.iloc[i,1])
flag=1
elif idToScore[file2.iloc[i,1]] != int(float(file2.iloc[i,8])+0.5):
print("该学生成绩不匹配:" + file2.iloc[i, 1]+" "+str(file2.iloc[i, 2])+" "+idToScoreFloat[file2.iloc[i,1]]+" "+str(float(file2.iloc[i,8])))
flag = 1
if flag==0:
print("该班成绩无错误")
使用说明
1.将原始文件放在与源代码相同目录下
2.调整第4行表格名称,如本次测试的文档(原始成绩文档)是“序号08.xlsx”,sheet为“成绩简表”,修改第12、13行的学号位置以及成绩位置(从左向右,从0开始,如此次“学号”位置为1,“得分”位置为6)
3.调整第16行的开始检测位置(表头的下一行开始为0,如表头只占一行则不需要调整,否则见第6条)
4.调整第18行的“缺考/无成绩标记”,如此次的缺考标记为“-”
5.调整第27行的表格名称,如本次测试的文档(教务成绩文档)是“毛概.xlsx”,sheet为“sheet1”,修改第35、38行的学号位置以及成绩位置(从左向右,从0开始,如此次“学号”位置为1,“得分”位置为8)
6.修改第33行的开始检测位置(如此次表头占6格,则开始位置为“5”)
7.运行可显示结果
途中碰到的问题汇总
round函数问题
round(四舍五入)函数其实执行的是“银行家取整法”(四舍六入五取偶),如下所示:
round(3.5) #结果为4
round(2.5) #结果为2
这种取整方式在教务系统中肯定是不合适的,所以使用+0.5之后强行int取整来代替:
int(3.5+0.5) #结果为4
int(2.5+0.5) #结果为3
int(2.4+0.5) #结果为2
学号问题
有的学生学号中含有字母,可以一开始就将其强行转化为字符串形式,以避免后续出现问题
idToScore[str(id[i])]
idToScoreFloat[str(id[i])]
最后的成绩显示问题
因教务系统成绩采用“四舍五入”形式,故本程序判定时也采用该原则,但最后显示时应显示表格原始成绩(只会显示错误成绩,故显示原始成绩有助于进一步核查),采用“两次映射”的方式解决(一次是四舍五入用于判断,一次是原始成绩用于显示),即第14行、第15行内容。
idToScore={} #学号映射四舍五入成绩
idToScoreFloat={} #学号映射原始成绩
注:如需“完全匹配”,则将idToScore的比对改为idToScoreFloat的比对即可(注意前者是int而后者是string)即将38行改为:
elif idToScoreFloat[file2.iloc[i,1]] != str(float(file2.iloc[i,8])):