期末考试通知单有很多种:
考试通知单(纸质);
计算机应用基础;
中央开网考通知单;
省开网考通知单;
职业技能考试通知单;
计算机文化基础考试通知单(如果有的话);
这里面最令人头疼的是通知单都是分开的,需要分别整理;
在考试通知单(纸质)里面包含所有科目的的信息,但是因为其它考试需要根据市校的具体情况安排时间,所以没办法提前显示,这样就造成了通知单有很多种,下发与合并很困难;如何才能把所有通知单合并到一起去呢?
解决思路:
- 以“考试通知单(纸质)”为下发的标准;
- 把其它考试填写入纸质版通知单中;
- 从网考课程下手
-- 因为网考课程都是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也可以保存结果!
目录结构:

网友评论