成绩单生成软件使用教程

前言

太困了,索性写一个朴实无华的教程

介绍

功能

  • 提取专业课程列表,以选择要生成的所有专业课
  • 根据已选的专业课计算出每个学生的平均成绩,进行排序
  • 英语快班成绩*1.1
  • 对等级评定(优、良、中、及格)能够转换成分数(90、80、70、60)
  • 只能根据单个专业原始成绩表生成该专业的成绩排名
  • 生成的排名表含有各个课程的学分,方便用Excel进行人工核算

开发工具

使用python开发,主要使用xlrd、xlwt、tkinter等模块进行开发,代码简单,逻辑较清楚。

作者

一个名不见经传、心怀恪尽职守、疼爱助理(自己)的颇享受成就感的辅导员助理。

使用

用前须知

开发过程中处理的原始文件格式如下:

生成的成绩排名如下:

空白处的地方是该学生没有这门课程,在计算平均成绩时也不会算入
(可能的原因就是这门课是其他同学补修或重修来的,在选择课程时选中了它,而其他同学这门课程已经学过了。但该补修或重修同学的总成绩需要计入该课程)

开始使用

打开软件:

  1. 点击1处按钮,弹出对话框
  2. 在对话框选择原始excel文件,确认打开,完成第2步
  3. 点击3处按钮载入excel文件
  4. 在“选择要生成的科目”一栏中选择课程 公选课不计入成绩排名中,所以要筛选出必修课
  5. 在“选择英语快班所学的课程”一栏中选择快班学的大英课程 快班英语成绩要乘1.1
  6. 点击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

原文地址:https://www.cnblogs.com/dragonbean/p/13611488.html