美文网首页
合并考试通知单

合并考试通知单

作者: Noza_ea8f | 来源:发表于2020-01-18 21:51 被阅读0次

期末考试通知单有很多种:
考试通知单(纸质);
计算机应用基础;
中央开网考通知单;
省开网考通知单;
职业技能考试通知单;
计算机文化基础考试通知单(如果有的话);

这里面最令人头疼的是通知单都是分开的,需要分别整理;
在考试通知单(纸质)里面包含所有科目的的信息,但是因为其它考试需要根据市校的具体情况安排时间,所以没办法提前显示,这样就造成了通知单有很多种,下发与合并很困难;如何才能把所有通知单合并到一起去呢?

解决思路:

  • 以“考试通知单(纸质)”为下发的标准;
  • 把其它考试填写入纸质版通知单中;
  • 从网考课程下手
    -- 因为网考课程都是xml的数据;
    -- 解决了数据的提取问题,后面就🆗了;
    -- 再解决计算机应用基础;因为计算机应用基础是我自己生成的excel表;数据提取相对容易得多

提取xml数据


import os
from xml.dom.minidom import parse

from openpyxl import load_workbook


def get_filenames(file_dir):
    '''
    获取所有xml的文件名
    :param file_dir:xml存放的文件路径
    :return:xml文件名列表
    '''
    for root, dirs, files in os.walk(file_dir):
        # print('files:', files)  # 当前路径下所有非目录子文件
        return files


def get_students_data(path, filenames):
    '''
    获取一个xml文件中的学生信息
    :param path:
    :param filenames:
    :return:
    '''
    stu_ls = []
    domTree = parse(f"{path}{filenames}")
    # 文档根元素
    rootNode = domTree.documentElement
    Students = rootNode.getElementsByTagName('Student')
    # 考试地点
    ExamRoomName = rootNode.getElementsByTagName('ExamRoomName')
    ExamRoom = ExamRoomName[0].childNodes[0].data
    # 考试时间日期
    ExamTime = rootNode.getElementsByTagName('ExamTime')
    exam_date_and_time = ExamTime[0].childNodes[0].data
    # 考试日期
    exam_date = exam_date_and_time.split(' ', 1)[0]
    # 考试时间
    exam_time = exam_date_and_time.split(' ', 1)[1]
    for Student in Students:
        ls = []
        # 学生的索引号
        # print(Student.getAttribute('index'))
        # 座位号
        Seat = Student.getElementsByTagName('Seat')[0]
        # print(Seat.nodeName, ":", Seat.childNodes[0].data)
        # 学号
        StudentCode = Student.getElementsByTagName('StudentCode')[0]
        # print(StudentCode.nodeName, ":", StudentCode.childNodes[0].data)
        # 姓名
        # RealName = Student.getElementsByTagName('RealName')[0]
        # print(RealName.nodeName, ":", RealName.childNodes[0].data)
        # 试卷号
        SubjectCode = Student.getElementsByTagName('SubjectCode')[0]
        # print(SubjectCode.nodeName, ":", SubjectCode.childNodes[0].data)
        # SubjectName = Student.getElementsByTagName('SubjectName')[0]
        # print(SubjectName.nodeName, ":", SubjectName.childNodes[0].data)
        # print(exam_date)
        # print(exam_time)
        ls.append(StudentCode.childNodes[0].data)
        ls.append(ExamRoom)
        ls.append(Seat.childNodes[0].data)
        ls.append(SubjectCode.childNodes[0].data)
        ls.append(exam_date)
        ls.append(exam_time)
        stu_ls.append(ls)
    return stu_ls


def get_students_data2(path, filenames):
    stu_ls = []
    domTree = parse(f"{path}{filenames}")
    # 文档根元素
    rootNode = domTree.documentElement
    # ExameCard信息
    ExamCards = rootNode.getElementsByTagName('ExamCards')
    # 因为ExamCards里面就一个元素,所以遍历ExamCards[0]下的所有子元素
    ExamCards = ExamCards[0].childNodes
    for ExamCard in ExamCards:
        try:
            # 学号
            StudentCode = ExamCard.getAttribute("StudentCode")
            # 姓名
            StudentName = ExamCard.getAttribute("StudentName")
            # 其他信息
            ExamArranges = ExamCard.getElementsByTagName('ExamArrange')
            # ExamArrange也是一个元素,它好像是把整体都算作一个元素,所以都是一个元素
            ExamArranges = ExamArranges[0]

            # 试卷号对象列表
            SubjectCodes = ExamArranges.getElementsByTagName('SubjectCode')
            # 机房号对象列表
            ExamRoomNames = ExamArranges.getElementsByTagName('ExamRoomName')
            # 座位号对象列表
            Seats = ExamArranges.getElementsByTagName('Seat')
            # 日期和时间对象列表
            ExamDateAndTimes = ExamArranges.getElementsByTagName('ExamTime')
            # print(len(SubjectCodes))
            for i in range(len(SubjectCodes)):
                ls = []
                ExamDateAndTime = ExamDateAndTimes[i].childNodes[0].data
                # 考试日期
                exam_date = ExamDateAndTime.split(' ', 1)[0]
                # 考试时间
                exam_time = ExamDateAndTime.split(' ', 1)[1]
                # print(i.childNodes[0].data)
                ls.append(StudentCode)
                ls.append(ExamRoomNames[i].childNodes[0].data)
                ls.append(Seats[i].childNodes[0].data)
                ls.append(SubjectCodes[i].childNodes[0].data)
                ls.append(exam_date)
                ls.append(exam_time)
                stu_ls.append(ls)
        except:
            pass
    return stu_ls

def get_students_exam_info_data(filenames, path):
    '''
    获取学生考试信息列表
    :return:
    '''
    stu_ls_ = []
    for filename in filenames:
        for i in get_students_data(path, filename):
            stu_ls_.append(i)
    return stu_ls_


def from_computer_course_info_get_students_data(path='计算机应用基础模板.xlsx', sheet_name='计算机应用基础模板'):
    '''
    获取“计算机应用基础”考生信息
    :param path: 计算机应用基础excel表所在路径
    :param sheet_name: 表名
    :return: 学生信息列表
    '''
    ls = []
    wb = load_workbook(path)
    rows = wb[sheet_name].max_row
    for i in range(2, rows + 1):
        ls_ = []
        # 座位号
        exam_seat = wb[sheet_name][f'A{i}'].value
        # 机房
        exam_room = wb[sheet_name][f'C{i}'].value
        # 考试日期时间
        exam_date_and_time = wb[sheet_name][f'D{i}'].value
        # 考试日期
        exam_date = exam_date_and_time.split(' ')[0]
        # 考试时间
        exam_time = exam_date_and_time.split(' ')[1]
        # 学号
        exam_code = wb[sheet_name][f'E{i}'].value
        # 姓名
        exam_name = wb[sheet_name][f'F{i}'].value
        ls_.append(exam_code)
        ls_.append(exam_room)
        ls_.append(exam_seat)
        ls_.append('1200')
        ls_.append(exam_date)
        ls_.append(exam_time)
        ls.append(ls_)
    return ls

上面代码保存在一个函数模块中
在提取代码的过程中,我误把签到表当成了考生通知单;
但结果是一致的;

写入纸质版通知单

因为都是xml文件,而且文件名都不相同,所以在提取xml文件数据之前最好做一下合并,通过搜索,找到所有.xml文件,拷贝到一个文件夹中,然后统一提取,并写入excel文件;

先通过openpyxl这个库写入;
因为这个库相对来说更人性化一些;
文件名:merge_exam_info_by_openpyxl.py

from merge_exam_info.lib.func import get_filenames, get_students_exam_info_data, \
    from_computer_course_info_get_students_data
from openpyxl import load_workbook

path = '计算机应用基础模板-.xlsx'
sheet_name = '计算机应用基础模板'

jsj_datas = from_computer_course_info_get_students_data(path=path)

# 中央开学生考试数据
# path = '签到表/中央开网考/data/'
path = 'xml/'
# 获取指定文件夹下所有xml文件名列表
filenames = get_filenames(path)[1:]
zyk_datas = get_students_exam_info_data(filenames, path)

print(f'计算机应用基础人数{len(jsj_datas)}')
print(f'网考人数{len(zyk_datas)}')

# 数据合并
for data in jsj_datas:
    zyk_datas.append(data)

print(f'合并后总人数{len(zyk_datas)}')

wb = load_workbook('tzd.xlsx')

# 获取行数
rows = wb['sheet1'].max_row
for a_i in range(1, rows + 1):
    print(f'-------程序进行到第{a_i}行-------')
    a_val = wb['sheet1'][f'A{a_i}'].value
    try:
        stu_id = a_val[24:37]  # 学号
        # 如果学号存在,从数据中遍历学生信息
        for i in range(len(zyk_datas) - 1, -1, -1):  # 倒叙遍历,为了可以删除找到的元素,缩短查找时间
            stu_info = zyk_datas[i]
            # 如果学号在信息表中找到
            if stu_id == stu_info[0]:
                # 遍历该学生所有考试科目,考试科目数量不会超过30
                for j in range(2, 30):
                    # 获取通知单试卷号
                    sjh = wb['sheet1'][f'A{a_i + j}'].value
                    # 先判断sjh是否为'考点名称:秦皇岛电大',
                    if sjh == '考点名称:秦皇岛电大':
                        # print(sjh)
                        break
                    # 如果试卷号在列表中
                    elif str(sjh) in stu_info:
                        # 写入考场号
                        wb['sheet1'][f'D{a_i + j}'].value = stu_info[1]
                        # 写入座位号
                        wb['sheet1'][f'E{a_i + j}'].value = stu_info[2]
                        # 写入考试日期
                        wb['sheet1'][f'F{a_i + j}'].value = stu_info[4]
                        # 写入考试时间
                        wb['sheet1'][f'G{a_i + j}'].value = stu_info[5]
                        # print(stu_id)
                        print(f'{stu_id}试卷号{sjh}写入完毕!')
                        # 移除找到的元素,缩小查找范围
                        zyk_datas.pop(i)
            # print(len(zyk_datas))
    except Exception as e:
        print(e)
        continue
wb.save('tzd.xlsx')
wb.close()

实际执行过程中会出现长时间的等待;
这是因为数据总行数在17000以上;
在处理较大数据上openpyxl这个库比较消耗内存;
也许还有别的什么原因,因为之前我在本地程序中直接运行数据量较大的文件效率还是可以的,可是到了flask上就会慢得出奇;
但只要有耐心等待,还是可以给你一个好的结果!
由于不会更改格式,所以还是建议耐心等一下这个程序的执行;

通过xlrd、xlutils来写入
文件名:merge_exam_info_by_xlrd_xlutils.py

from merge_exam_info.lib.func import get_filenames, get_students_exam_info_data, \
    from_computer_course_info_get_students_data
import xlrd
from xlutils.copy import copy

path = '计算机应用基础模板-.xlsx'
sheet_name = '计算机应用基础模板'

jsj_datas = from_computer_course_info_get_students_data(path=path)

# 中央开学生考试数据
# path = '签到表/中央开网考/data/'
path = 'xml/'
# 获取指定文件夹下所有xml文件名列表
filenames = get_filenames(path)[1:]
zyk_datas = get_students_exam_info_data(filenames, path)

print(f'计算机应用基础人数{len(jsj_datas)}')
print(f'网考人数{len(zyk_datas)}')

# 数据合并
for data in jsj_datas:
    zyk_datas.append(data)

print(f'合并后总人数{len(zyk_datas)}')

rb = xlrd.open_workbook('tzd.xls', formatting_info=True)
wb = copy(rb)
sheet = rb.sheet_by_name('sheet1')

# wb_w = xlwt.Workbook(encoding='utf-8')  # 创建workbook 对象
sheet_w = wb.get_sheet('sheet1')  # 创建工作表sheet

# 获取行数
rows = sheet.nrows
for a_i in range(1, rows):
    print(f'-------程序进行到第{a_i + 1}行-------')
    a_val = sheet.cell_value(a_i, 0)
    # print(a_val)
    try:
        stu_id = a_val[24:37]  # 学号
        print(stu_id)
        # 如果学号存在,从数据中遍历学生信息
        for i in range(len(zyk_datas) - 1, -1, -1):  # 倒叙遍历,为了可以删除找到的元素,缩短查找时间
            stu_info = zyk_datas[i]
            # 如果学号在信息表中找到
            if stu_id == stu_info[0]:
                # 遍历该学生所有考试科目,考试科目数量不会超过30
                for j in range(2, 30):
                    # 获取通知单试卷号
                    sjh = sheet.cell_value(rowx=a_i + j, colx=0)
                    # 先判断sjh是否为'考点名称:秦皇岛电大',
                    if sjh == '考点名称:秦皇岛电大':
                        # print(sjh)
                        break
                    # 如果试卷号在列表中
                    elif str(sjh) in stu_info:
                        # 写入考场号
                        # wb['sheet1'][f'D{a_i + j}'].value = stu_info[1]
                        sheet_w.write(a_i + j, 3, stu_info[1])
                        # 写入座位号
                        sheet_w.write(a_i + j, 4, stu_info[2])
                        # 写入考试日期
                        sheet_w.write(a_i + j, 5, stu_info[4])
                        # 写入考试时间
                        sheet_w.write(a_i + j, 6, stu_info[5])
                        # print(stu_id)
                        print(f'{stu_id}试卷号{sjh}写入完毕!')
                        # 移除找到的元素,缩小查找范围
                        zyk_datas.pop(i)
        # print(len(zyk_datas))
    except Exception as e:
        print(e)
        continue
wb.save('test.xls')

这个库运行起来要快得多;
但不足之处是如果不设置格式,写入的字体会和原表中不同,而且会去掉边框,不太美观,我不想花时间做这些修改;所以还是用openxl那个程序好了;意外发现写入程序可以不需要xlwt,xlrd也可以保存结果!

目录结构:

image.png

相关文章

  • 合并考试通知单

    期末考试通知单有很多种:考试通知单(纸质);计算机应用基础;中央开网考通知单;省开网考通知单;职业技能考试通知单;...

  • 合并考试通知单(PySimpleGUI)

    Code(openpyxl版) 效果 Code2(openpyxl版,修改进度条) 效果 Code(xlrd an...

  • 五元钱的交易

    前几天我因要参加自学考试,需要从某网站打印考试通知单,考试通知单上有关于考试地点,考场,座位号的相关信息,但我不知...

  • 合并考试

    这二天中考出了个新政策,不但考试时间提前了十天不说,还搞了个合并考试,这是怎样的人才才想的出啊,活久见!学校小测验...

  • 星宝贝0.2分失利

    这是一份考试通知单,星宝贝要在通知单内安排的时间经历美国USAG航校的选拔。 顺利通过选拔的学生将在下半年前往美国...

  • 2015年5月

    本月读书 11 本。 《死亡通知单2:宿命(上)》,《死亡通知单2:宿命(下)》,《死亡通知单3:离别曲(上)》,...

  • 12月28日4D分享

    A:全员业务考试 M:烦躁,紧张 B:第一次人员合并后业务考试,大家都很烦躁,因为人员合并后很多业务还是不懂,大家...

  • 点点滴滴 | 期末成绩

    孩子们都放假了,受疫情影响考试后不需要返校,老师把成绩发到班级优化大师。放假通知单考试后也拿回来了。 期末成绩没有...

  • 112-0602.试卷订单在哪里

    打开首页——教务处信息——考务科——左下角试卷订单。 打印考试通知单——用户名qydd——密码1234——考点代码...

  • 梦-考试

    在交大图书馆考试,会计考试,第一题考化学,下列不属于化学反应的图片是? 去之前拿通知单 带着我弟,他腿瘸了 开着一...

网友评论

      本文标题:合并考试通知单

      本文链接:https://www.haomeiwen.com/subject/gxrlzctx.html