first commit
This commit is contained in:
62
module/doc.py
Normal file
62
module/doc.py
Normal file
@@ -0,0 +1,62 @@
|
||||
import pathlib
|
||||
from copy import deepcopy
|
||||
|
||||
from docx import Document
|
||||
from docx.shared import Cm
|
||||
|
||||
from module.schema import Course, Student, Question
|
||||
|
||||
|
||||
class DocPaper:
|
||||
def __init__(self, filename: str = 'Paper', template_path: str = '../template/template.docx'):
|
||||
self._doc = Document()
|
||||
self._template = Document(template_path)
|
||||
self._filename = filename
|
||||
|
||||
section = self._doc.sections[0]
|
||||
section.top_margin = Cm(2)
|
||||
section.bottom_margin = Cm(1)
|
||||
section.left_margin = Cm(1.4)
|
||||
section.right_margin = Cm(1.4)
|
||||
|
||||
def add_paper(self, course: Course, student: Student):
|
||||
temp_table = self._template.tables[0]
|
||||
new_table = deepcopy(temp_table)
|
||||
para = self._doc.add_paragraph()
|
||||
para._p.addprevious(new_table._element)
|
||||
|
||||
data_list = {
|
||||
'%CNAME%': course.name,
|
||||
'%CLASS%': student.class_name,
|
||||
'%SNAME%': student.name,
|
||||
'%NO%': student.no,
|
||||
'%SO%': student.so,
|
||||
'%Q1%': student.picked_questions[0].topic,
|
||||
'%Q2%': student.picked_questions[1].topic,
|
||||
'%Q3%': student.picked_questions[2].topic
|
||||
}
|
||||
|
||||
# 替换表格中的占位符
|
||||
for row in new_table.rows:
|
||||
for cell in row.cells:
|
||||
for para in cell.paragraphs:
|
||||
for run in para.runs:
|
||||
for key, val in data_list.items():
|
||||
if key in run.text:
|
||||
run.text = run.text.replace(key, val)
|
||||
break
|
||||
|
||||
def save(self, path: str = './'):
|
||||
self._doc.save(str(pathlib.Path(path) / f"{self._filename}.docx"))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
course = Course.load_from_xls('../files/21工程管理-工程造价Ⅱ-点名册-系统0828.xlsx')
|
||||
students = Student.load_from_xls('../files/21工程管理-工程造价Ⅱ-点名册-系统0828.xlsx')
|
||||
questions = Question.load_from_csv()
|
||||
|
||||
d = DocPaper()
|
||||
for student in students:
|
||||
student.pick_question(questions)
|
||||
d.add_paper(course, student)
|
||||
d.save()
|
||||
115
module/schema.py
Normal file
115
module/schema.py
Normal file
@@ -0,0 +1,115 @@
|
||||
import random
|
||||
from typing import Optional
|
||||
from openpyxl.reader.excel import load_workbook
|
||||
|
||||
|
||||
class Question:
|
||||
def __init__(self, no: str, topic: str):
|
||||
self._no: str = no
|
||||
self._topic: str = topic
|
||||
|
||||
def __str__(self):
|
||||
return f"Question<No: {self._no}, Topic: {self._topic}>"
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
@staticmethod
|
||||
def load_from_csv(path: Optional[str] = None) -> list['Question']:
|
||||
questions = []
|
||||
with open(path if path else '../files/questions.csv', encoding='gbk') as f:
|
||||
for line in f.readlines():
|
||||
questions.append(Question(*line.strip('\n').split(',')))
|
||||
return questions
|
||||
|
||||
@property
|
||||
def no(self) -> str:
|
||||
return self._no
|
||||
|
||||
@property
|
||||
def topic(self) -> str:
|
||||
return self._topic
|
||||
|
||||
|
||||
class Student:
|
||||
def __init__(self, no: str, so: str, name: str, major: str, class_name: str):
|
||||
self._no: str = no
|
||||
self._so: str = so
|
||||
self._name: str = name
|
||||
self._major: str = major
|
||||
self._class_name: str = class_name
|
||||
self._picked_questions: list[Question] = []
|
||||
|
||||
def __str__(self):
|
||||
return f"Student<No: {self._no}, SO: {self._so}, Name: {self._name}, Major: {self._major}, Class: {self._class_name}>"
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
@staticmethod
|
||||
def load_from_xls(path: str) -> list['Student']:
|
||||
wb = load_workbook(path, read_only=True)
|
||||
ws = wb.active
|
||||
students = []
|
||||
for row in ws.iter_rows(min_row=6, max_col=5, values_only=True):
|
||||
students.append(Student(*row))
|
||||
return [x for x in students if x.valid]
|
||||
|
||||
@property
|
||||
def valid(self) -> bool:
|
||||
return bool(self._no and self._so and self._name and self._major and self._class_name)
|
||||
|
||||
@property
|
||||
def picked_questions(self) -> list[Question]:
|
||||
return self._picked_questions
|
||||
|
||||
@property
|
||||
def no(self) -> str:
|
||||
return self._no
|
||||
|
||||
@property
|
||||
def so(self) -> str:
|
||||
return self._so
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def major(self) -> str:
|
||||
return self._major
|
||||
|
||||
@property
|
||||
def class_name(self) -> str:
|
||||
return self._class_name
|
||||
|
||||
def pick_question(self, questions: list[Question], num: int = 3) -> None:
|
||||
if len(questions) < num:
|
||||
raise ValueError("Not enough questions to pick from.")
|
||||
self._picked_questions = random.sample(questions, num)
|
||||
|
||||
|
||||
class Course:
|
||||
def __init__(self, name: str):
|
||||
self._name = name
|
||||
|
||||
def __str__(self):
|
||||
return f"Course<Name: {self._name}>"
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
@staticmethod
|
||||
def load_from_xls(path: str) -> 'Course':
|
||||
wb = load_workbook(path, read_only=True)
|
||||
ws = wb.active
|
||||
name: str = ws['E3'].value
|
||||
return Course(name[5:])
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return self._name
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
...
|
||||
Reference in New Issue
Block a user