from typing import Optional from openpyxl.reader.excel import load_workbook from openpyxl.workbook.workbook import Workbook from openpyxl.worksheet.worksheet import Worksheet class PickerStudent: total_time: int = 0 def __init__(self, name: str, position: int, scores: list[int]): self._name = name self._position = position self._scores = scores self._modify = False self._scores = [] self._scores.extend(scores) self._scores_pointer = -1 self.init_score() def init_score(self): self._scores += [0] * (self.total_time - len(self._scores)) for idx, val in enumerate(self._scores): if val is None: self._scores[idx] = 0 if self._scores[idx] == 0: self._scores_pointer = idx break def append_score(self, score: int) -> int: if self._scores_pointer > self.total_time or self._scores_pointer < 0: raise IndexError self._scores[self._scores_pointer] = score self._scores_pointer += 1 self.modified() return self._scores_pointer - 1 def change_score(self, new_score: int, index: int): if index < 0 or index > self.total_time: raise IndexError self._scores[index] = new_score self.modified() @classmethod def set_total_time(cls, total_time: int): cls.total_time = total_time @property def position(self) -> int: return self._position @property def scores(self) -> list[int]: return self._scores @property def modify(self) -> bool: return self._modify def saved(self): self._modify = False def modified(self): self._modify = True def __str__(self): return f"PickerStudent {self._name} at {self.position}, with scores: {','.join(str(x) for x in self._scores if x)}" def __repr__(self): return self.__str__() class PickerExcel: wb: Optional[Workbook] ws: Optional[Worksheet] path: str = '' max_time_position = 'L1' def __init__(self, path: str): self.open(path) @classmethod def open(cls, path: str): cls.path = path cls.wb = load_workbook(path) cls.ws = cls.wb.active PickerStudent.set_total_time(cls.ws[cls.max_time_position].value) @classmethod def read_student(cls, path: Optional[str] = None) -> list[PickerStudent]: if path: cls.open(path) if cls.wb and cls.ws: ret = [] for row in cls.ws.iter_rows(min_row=4, max_col=4 + cls.ws[cls.max_time_position].value, values_only=True): if (name := row[2]) is None: break ret.append(PickerStudent(name, int(row[0]) + 3, row[4:])) return ret else: raise Exception('No Workbook or Worksheet') @classmethod def write_back(cls, student: PickerStudent): start_col = 5 # E列 row = student.position for i, val in enumerate(student.scores): cls.ws.cell(row=row, column=start_col + i, value=val if val != 0 else '') student.saved() @classmethod def write_all(cls, students: list[PickerStudent]): for student in students: if student.modify: cls.write_back(student) @classmethod def save(cls): if cls.ws: cls.wb.save(cls.path) if __name__ == '__main__': ...