From 5cd495e33e2eecf1399e60ce6d92da8b37c92861 Mon Sep 17 00:00:00 2001 From: jmpla Date: Sun, 3 Dec 2023 00:17:16 +0100 Subject: [PATCH] ajout export fichier par NIP --- app/scodoc/sco_excel.py | 112 ++++++++++++++++++++++++++------- app/scodoc/sco_saisie_notes.py | 35 ++++++----- 2 files changed, 108 insertions(+), 39 deletions(-) diff --git a/app/scodoc/sco_excel.py b/app/scodoc/sco_excel.py index 87debfaaf..945b5f3a9 100644 --- a/app/scodoc/sco_excel.py +++ b/app/scodoc/sco_excel.py @@ -40,6 +40,8 @@ from openpyxl.comments import Comment from openpyxl import Workbook, load_workbook from openpyxl.cell import WriteOnlyCell from openpyxl.styles import Font, Border, Side, Alignment, PatternFill +from openpyxl.utils import quote_sheetname, absolute_coordinate +from openpyxl.workbook.defined_name import DefinedName from openpyxl.worksheet.worksheet import Worksheet import app.scodoc.sco_utils as scu @@ -218,6 +220,7 @@ class ScoExcelSheet: self.rows = [] # list of list of cells self.column_dimensions = {} self.row_dimensions = {} + self.formulae = {} def excel_make_composite_style( self, @@ -363,6 +366,9 @@ class ScoExcelSheet: """ajoute une ligne déjà construite à la feuille.""" self.rows.append(row) + def set_formula(self, coord, formula): + self.formulae[coord] = formula + def prepare(self): """génére un flux décrivant la feuille. Ce flux pourra ensuite être repris dans send_excel_file (classeur mono feille) @@ -383,6 +389,8 @@ class ScoExcelSheet: # construction d'un flux (https://openpyxl.readthedocs.io/en/stable/tutorial.html#saving-as-a-stream) self.prepare() + for coord, formula in self.formulae.items(): + self.ws[coord] = formula with NamedTemporaryFile() as tmp: self.wb.save(tmp.name) tmp.seek(0) @@ -433,7 +441,12 @@ def excel_simple_table( return ws.generate() -def excel_feuille_saisie(evaluation: "Evaluation", titreannee, description, lines): +from openpyxl.utils import absolute_coordinate + + +def excel_feuille_saisie( + evaluation: "Evaluation", titreannee, description, lines, withnips=False +): """Genere feuille excel pour saisie des notes. E: evaluation (dict) lines: liste de tuples @@ -450,6 +463,13 @@ def excel_feuille_saisie(evaluation: "Evaluation", titreannee, description, line ws.set_column_dimension_width("D", 164.0 / 7) # groupes ws.set_column_dimension_width("E", 115.0 / 7) # notes ws.set_column_dimension_width("F", 355.0 / 7) # remarques + if withnips: + ws.set_column_dimension_width("G", 11.0 / 7) # colonne NIP cachée + ws.set_column_dimension_width( + "H", 105.0 / 7 + ) # Colonne blanche entre liste et zone de saisie + ws.set_column_dimension_width("I", 90.0 / 7) # Saisie: NIP + ws.set_column_dimension_width("J", 115.0 / 7) # Saisie: Note # fontes font_base = Font(name="Arial", size=12) @@ -497,15 +517,32 @@ def excel_feuille_saisie(evaluation: "Evaluation", titreannee, description, line "font": font_blue, "border": border_top, } + style_input = { + "font": font_bold, + "border": border_top, + "fill": fill_light_yellow, + } + + if withnips: + del style_notes["fill"] + + list_top = 9 # ligne de titres ws.append_single_cell_row( "Feuille saisie note (à enregistrer au format excel)", style_titres ) # lignes d'instructions - ws.append_single_cell_row( - "Saisir les notes dans la colonne E (cases jaunes)", style_expl - ) + if withnips: + ws.append_single_cell_row( + "Saisir les (NIP, note) en colonne I et J (cases jaunes). ordre des NIP indifférent", + style_expl, + ) + else: + ws.append_single_cell_row( + "Saisir les notes dans la colonne E (cases jaunes)", style_expl + ) + ws.append_single_cell_row("Ne pas modifier les cases en mauve !", style_expl) # Nom du semestre ws.append_single_cell_row(scu.unescape_html(titreannee), style_titres) @@ -518,19 +555,33 @@ def excel_feuille_saisie(evaluation: "Evaluation", titreannee, description, line # ligne blanche ws.append_blank_row() # code et titres colonnes - ws.append_row( - [ - ws.make_cell("!%s" % evaluation.id, style_ro), - ws.make_cell("Nom", style_titres), - ws.make_cell("Prénom", style_titres), - ws.make_cell("Groupe", style_titres), - ws.make_cell("Note sur %g" % (evaluation.note_max or 0.0), style_titres), - ws.make_cell("Remarque", style_titres), + title_row = [ + ws.make_cell("!%s" % evaluation.id, style_ro), + ws.make_cell("Nom", style_titres), + ws.make_cell("Prénom", style_titres), + ws.make_cell("Groupe", style_titres), + ws.make_cell("Note sur %g" % (evaluation.note_max or 0.0), style_titres), + ws.make_cell("Remarque", style_titres), + ] + if withnips: + title_row += [ + ws.make_cell("NIP", style_titres), + ws.make_cell(), + ws.make_cell("NIP", style_titres), + ws.make_cell("Note sur 20", style_titres), ] - ) + ws.append_row(title_row) + + # Calcul de la zone de saisie (au format $I$9:$J$45) pour intégration dans la formule + if withnips: + min_row = list_top + max_row = list_top + len(lines) - 1 + min_col = "I" + max_col = "J" + input_range = absolute_coordinate(f"{min_col}{min_row}:{max_col}{max_row}") # etudiants - for line in lines: + for line_number, line in enumerate(lines): st = style_nom if line[3] != "I": st = style_dem @@ -543,17 +594,30 @@ def excel_feuille_saisie(evaluation: "Evaluation", titreannee, description, line try: val = float(line[5]) except ValueError: - val = line[5] - ws.append_row( - [ - ws.make_cell("!" + line[0], style_ro), # code - ws.make_cell(line[1], st), - ws.make_cell(line[2], st), - ws.make_cell(s, st), - ws.make_cell(val, style_notes), # note - ws.make_cell(line[6], style_comment), # comment + if withnips and line[5] == "": + ws.set_formula( + f"E{list_top + line_number}", + f"=VLOOKUP(G{list_top + line_number},{input_range}, 2, FALSE)", + ) + val = "" + else: + val = line[5] + row = [ + ws.make_cell("!" + line[0], style_ro), # code + ws.make_cell(line[1], st), + ws.make_cell(line[2], st), + ws.make_cell(s, st), + ws.make_cell(val, style_notes), # note + ws.make_cell(line[6], style_comment), # comment + ] + if withnips: + row += [ + ws.make_cell(line[7], style_ro), # NIP + ws.make_cell(), + ws.make_cell("", style_input), # Saisie NIP + ws.make_cell("", style_input), # Saisie note ] - ) + ws.append_row(row) # explication en bas ws.append_row([None, ws.make_cell("Code notes", style_titres)]) diff --git a/app/scodoc/sco_saisie_notes.py b/app/scodoc/sco_saisie_notes.py index 87bc1097b..8d13e1325 100644 --- a/app/scodoc/sco_saisie_notes.py +++ b/app/scodoc/sco_saisie_notes.py @@ -733,6 +733,8 @@ def saisie_notes_tableur(evaluation_id, group_ids=()):
  • obtenir le fichier tableur à remplir +  (saisie par NIP)
  • ou