前言
太困了,索性写一个朴实无华的教程
介绍
功能
- 提取专业课程列表,以选择要生成的所有专业课
- 根据已选的专业课计算出每个学生的平均成绩,进行排序
- 英语快班成绩*1.1
- 对等级评定(优、良、中、及格)能够转换成分数(90、80、70、60)
- 只能根据单个专业原始成绩表生成该专业的成绩排名
- 生成的排名表含有各个课程的学分,方便用Excel进行人工核算
开发工具
使用python开发,主要使用xlrd、xlwt、tkinter等模块进行开发,代码简单,逻辑较清楚。
作者
一个名不见经传、心怀恪尽职守、疼爱助理(自己)的颇享受成就感的辅导员助理。
使用
用前须知
开发过程中处理的原始文件格式如下:
生成的成绩排名如下:
空白处的地方是该学生没有这门课程,在计算平均成绩时也不会算入
(可能的原因就是这门课是其他同学补修或重修来的,在选择课程时选中了它,而其他同学这门课程已经学过了。但该补修或重修同学的总成绩需要计入该课程)
开始使用
打开软件:
- 点击1处按钮,弹出对话框
- 在对话框选择原始excel文件,确认打开,完成第2步
- 点击3处按钮载入excel文件
- 在“选择要生成的科目”一栏中选择课程 公选课不计入成绩排名中,所以要筛选出必修课
- 在“选择英语快班所学的课程”一栏中选择快班学的大英课程 快班英语成绩要乘1.1
- 点击6处按钮,在同文件夹下生成专业成绩排名表,成功后会弹出成功对话框
代码
附上代码,希望给帮助到命中注定的人,如有问题可以联系博主哦!
UI.py
# -*- coding: utf-8 -*-
"""
Created on Fri Aug 28 16:23:58 2020
@author: DragonBean
description:整个排版用固定像素值来排,通过设置width保证课程名称长的课只显示一部分,保证不打乱布局
"""
import tkinter as tk
from tkinter import ttk
def openFile():
import tkinter.filedialog #必须有
global filename
filename = tk.filedialog.askopenfilename()
if filename != '':
filePath.set(filename)
frame1.config(text="选择的Excel文件是:")
else:
filePath.set('没有选择任何文件')
def loadFile():
global filename,major
import getExcel as get
if not filename:
filePath.set('请先选择文件')
else :
try:
raw_titleList,raw_lessonList,major = get.getPreData(filename)
frame1.config(text="文件导入成功")
set_checkbox(raw_titleList, raw_lessonList)
except:
filePath.set('文件有误,请重新选择或联系开发人员')
def set_checkbox(raw_titleList, raw_lessonList):
for widget in frame2.winfo_children():
widget.destroy()
for widget in frame3.winfo_children():
widget.destroy()
for i in range(len(raw_titleList)):
tmpVar = tk.IntVar()
title = raw_titleList[i]
ttk.Checkbutton(frame2, text=title, width=10, variable=tmpVar, onvalue=1, offvalue=0).grid(row=i//8, column=i%8, padx=5, pady=5)
titleList.append(tmpVar)
for i in range(len(raw_lessonList)):
tmpVar = tk.StringVar()
text = raw_lessonList[i]
ttk.Checkbutton(frame3, text=text, width=35, variable=tmpVar, onvalue=text, offvalue="").grid(row=i//6, column=i%6, padx=5, pady=5)
#把变量加进去 (带顺序)
lessonValue.append(tmpVar)
def doExcel():
def close():
successwin.destroy()
global filename, major, english, lessonValue
import getExcel as get
import setExcel as write
import os
print(os.path.split(filename)[0])
new_filename = os.path.split(filename)[0] + "/" + major + "成绩单.xls"
if english.get() == 2:
specialLesson = "大学英语(2)"
elif english.get() == 3:
specialLesson = "大学英语(3)"
elif english.get() == 4:
specialLesson = "大学英语(4)"
else: specialLesson = None
lessons = []
for each in lessonValue:
if each.get() != "":
lessons.append(each.get())
try:
data = get.getAllData(filename, lessons)
write.writeData(new_filename, major, lessons, data, specialLesson)
successwin = tk.Toplevel()
successwin.title("生成成功")
successwin.geometry("%dx%d+%d+%d" %(400, 150, (width-400)/2, (height-150)/2))
ttk.Label(successwin, text='成绩排名生成成功
文件路径为:
' + new_filename ).grid(row=0, padx=30, pady=10)
ttk.Button(successwin, text="确定", command=close).grid(row=1, padx=30, pady=10)
except:
falsewin = tk.Toplevel()
falsewin.title("错误")
falsewin.geometry("%dx%d+%d+%d" %(350, 130, (width-350)/2, (height-130)/2))
ttk.Label(falsewin, text='程序执行有误
建议重新启动程序
如果还不行,请联系作者QQ:509931598 注明来由').grid(row=0, padx=30, pady=30)
def showHelp():
helpwin = tk.Toplevel()
helpwin.title("Help")
helpwin.geometry("%dx%d+%d+%d" %(450, 150, (width-450)/2, (height-150)/2))
ttk.Label(helpwin, text='详细使用教程请查看博客:').grid(row=0, padx=30, pady=10)
url = ttk.Entry(helpwin, width=50)
url.grid(row=1, padx=30, pady=10)
url.insert(tk.END,'https://www.cnblogs.com/dragonbean/p/13611488.html')
ttk.Label(helpwin, text='密码:123456
by DragonBean').grid(row=3, padx=30, pady=10)
global filename,lessonValue,major
filename = ''
lessonValue = []
titleList = [] #IntVar序列 0,1
window = tk.Tk()
window.title("成绩表单生成系统")
width, height = window.maxsize()
window.geometry("%dx%d+%d+%d" %(width*0.9, height*0.9, width*0.05, height*0.01))
#window.resizable(width=False,height=False)
window.rowconfigure(0,weight=1)
window.rowconfigure(1,weight=2)
window.rowconfigure(2,weight=3)
window.rowconfigure(3,weight=1)
window.columnconfigure(0,weight=1)
frame1 = ttk.LabelFrame(window, text="选择Excel文件")
frame2 = ttk.LabelFrame(window, text="选择要生成的内容")
frame3 = ttk.LabelFrame(window, text="选择要生成的科目")
frame4 = tk.Frame(window, padx=5,pady=5)
frame1.columnconfigure(0,weight=1)
frame4.rowconfigure(0, weight=1)
frame4.columnconfigure(0, weight=1)
frame1.grid(row=0,column=0, sticky=tk.EW, padx=5, pady=5)
frame3.grid(row=2,column=0, sticky=tk.NSEW, padx=5, pady=5)
frame4.grid(row=3,column=0, sticky=tk.EW, padx=5, pady=5)
#frmae1
filePath = tk.StringVar()
text = ttk.Entry(frame1, textvariable=filePath, state="readonly")
text.grid(row=0,sticky=tk.EW, padx=5, pady=5)
selectButton = ttk.Button(frame1, text='···', command=openFile)
importButton = ttk.Button(frame1, text='载入', command=loadFile)
selectButton.grid(row=0, column=1, padx=2, pady=2)
importButton.grid(row=0, column=2, padx=2, pady=2)
#frame2
#frame3
#frame4
frame4_4 = ttk.LabelFrame(frame4, text="选择英语快班所学的课程")
frame4_4.grid(row=0,column=0, sticky=tk.EW, padx=5, pady=5)
english = tk.IntVar()
ttk.Radiobutton(frame4_4, text="大学英语2", variable=english, value=2).grid(row=0,column=0,padx=10,pady=2)
ttk.Radiobutton(frame4_4, text="大学英语3", variable=english, value=3).grid(row=0,column=1,padx=10,pady=2)
ttk.Radiobutton(frame4_4, text="大学英语4", variable=english, value=4).grid(row=0,column=2,padx=10,pady=2)
ttk.Button(frame4, text="生成表单", command=doExcel).grid(row=0, column=1, padx=5, pady=10)
ttk.Button(frame4, text="帮助", command=showHelp).grid(row=0, column=2, padx=5, pady=10)
window.mainloop()
getExcel.py
# -*- coding: utf-8 -*-
"""
Created on Wed Sep 2 10:50:07 2020
@author: DragonBean
description: 接收excel文件,
传出表头title [表头1,表头2,....]
传出专业和课程列表 专业&[课程1,课程2,课程3,...]
传入筛选后的表头和课程,读取excel数据,
# 传出整个数据(新的数据格式:
# {20182*****:{学号:'20182*****',
# 姓名:'***',
# 班级:**班,
# 课程1:[成绩,学分],
# 课程2:[成绩,学分],
# ...},
# 20182*****:{学号:}}},...}
"""
import xlrd
def open_file(filename):
book = xlrd.open_workbook(filename)
sheet = book.sheet_by_index(0)
return sheet
def getPreData(filename):
titleList = []
lessonSet = set()
sheet = open_file(filename)
row = sheet.row(0) #获取表头所在行
for each in row:
titleList.append(each.value)
column = sheet.col(4) #获取课程所在列
x = 1
for each in column:
#去除第一行的表头
if x == 1:
x += 1
continue
lessonSet.add(each.value)
major = sheet.row(1)[9].value
data = [titleList,list(lessonSet),major]
return data
def getAllData(filename, lessons):
data = dict(dict())
studentIDSet = set()
sheet = open_file(filename)
for i in range(1, sheet.nrows):
row = sheet.row(i)
studentID = row[0].value #学号
studentName = row[1].value #名字
lesson = row[4].value #课程
classes = row[10].value #班级
grade = row[16].value #成绩
credit = row[13].value #学分
if studentID not in studentIDSet:
studentIDSet.add(studentID)
data[studentID] = {'学号':studentID,'姓名':studentName,'班级':classes}
if lesson in lessons:
data[studentID][lesson] = [grade, credit]
return data
setExcel.py
# -*- coding: utf-8 -*-
"""
Created on Thu Sep 3 10:26:43 2020
@author: DragonBean
description: 传入数据 data
{20182*****:{学号:'20182*****',
姓名:'***',
班级:**班,
课程1:[成绩,学分],
课程2:[成绩,学分],
...},
20182*****:{学号:}}},...}
把数据按顺序写到一个列表里,根据平均成绩排序,然后写入表格
输出一个excel表格
"""
import xlwt
def open_file(filename, major):
book = xlwt.Workbook()
sheet = book.add_sheet(major)
al = xlwt.Alignment()
al.horz = xlwt.Alignment.HORZ_CENTER
al.vert = xlwt.Alignment.VERT_CENTER
borders = xlwt.Borders()
borders.top = borders.THIN
borders.right = borders.THIN
borders.bottom = borders.THIN
borders.left = borders.THIN
style = xlwt.XFStyle()
style.borders = borders
style.alignment = al
return(book, sheet, style)
def is_num(string):
try:
float(string)
return True
except:
return False
def generate_list(titleList, lessons, data, specialLesson):
allDataList = []
#creditList : [["课程1",2.0],["课程2",3.0],["课程3",2.5],......]
creditList = [[lesson,0] for lesson in lessons]
studentList = list(data.values())
for i in range(len(studentList)):
dataList = []
student = studentList[i] #获取单个学生的数据 :字典
studentGrade = 0.0
studentCredit = 0.0
for j in range(len(titleList)):
key = titleList[j] #课程名称
if key in ['学号','姓名','班级']:
dataList.append(student[key])
elif key in lessons :
value = student.get(key)
#处理没有该该学生没有该课程的情况
if value == None:
grade = ""
credit = 0
else :
grade,credit = value
dataList.append(grade)
#将成绩的字符串转换成成绩数值,同时处理未考情况
if is_num(grade):
grade = float(grade)
elif grade == '优':
grade = 90
elif grade == '良':
grade = 80
elif grade == '中':
grade =70
elif grade == '及格':
grade = 60
else :
grade = 0;
#特殊的课程(英语快班*1.1) 处理了快班英语上完的情况
if specialLesson!=None and key==specialLesson:
grade = grade*1.1
#计算总成绩 和 总学分
studentGrade += grade*float(credit)
studentCredit += float(credit)
creditList[lessons.index(key)][1] = credit
elif key == '平均成绩':
dataList.append(studentGrade/studentCredit if studentCredit!=0 else 0) #排除一种异常:该学生一门课都没有上过
allDataList.append(dataList)
creditData = [each[1] for each in creditList]
return [creditData,allDataList]
def save_excel(filename, book):
book.save(filename)
def writeData(filename, major, lessons, data, specialLesson):
book,sheet,style = open_file(filename, major)
titleList = ['学号','姓名','班级'] + lessons + ['平均成绩','排名']
#写表头
sheet.write_merge(0, 0, 0, len(titleList)-1, '管理学院' + major + '成绩', style=style)
for i in range(len(titleList)):
sheet.write_merge(1, 3, i, i, titleList[i], style=style)
#获取数据:学分列表 和 每个学生的表格数据
creditList,raw_dataList = generate_list(titleList, lessons, data, specialLesson)
for i in range(len(creditList)):
sheet.write_merge(4, 4, i+3, i+3, creditList[i], style=style)
raw_dataList.sort(key = lambda x:x[-1], reverse=True) #根据平均成绩 进行降序排序
new_dataList = [each+[index+1] for index,each in enumerate(raw_dataList)] #添加排名
#写入数据进表格
for i in range(len(new_dataList)):
row = sheet.row(i + 5)
row_data = new_dataList[i]
for j in range(len(row_data)):
row.write(j, row_data[j], style=style)
save_excel(filename, book)
文章转自Dragonbean
https://www.cnblogs.com/dragonbean/p/13611488.html