forked from ScoDoc/ScoDoc
ajout export fichier par NIP
This commit is contained in:
parent
a5e5ad6248
commit
5cd495e33e
@ -40,6 +40,8 @@ from openpyxl.comments import Comment
|
|||||||
from openpyxl import Workbook, load_workbook
|
from openpyxl import Workbook, load_workbook
|
||||||
from openpyxl.cell import WriteOnlyCell
|
from openpyxl.cell import WriteOnlyCell
|
||||||
from openpyxl.styles import Font, Border, Side, Alignment, PatternFill
|
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
|
from openpyxl.worksheet.worksheet import Worksheet
|
||||||
|
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
@ -218,6 +220,7 @@ class ScoExcelSheet:
|
|||||||
self.rows = [] # list of list of cells
|
self.rows = [] # list of list of cells
|
||||||
self.column_dimensions = {}
|
self.column_dimensions = {}
|
||||||
self.row_dimensions = {}
|
self.row_dimensions = {}
|
||||||
|
self.formulae = {}
|
||||||
|
|
||||||
def excel_make_composite_style(
|
def excel_make_composite_style(
|
||||||
self,
|
self,
|
||||||
@ -363,6 +366,9 @@ class ScoExcelSheet:
|
|||||||
"""ajoute une ligne déjà construite à la feuille."""
|
"""ajoute une ligne déjà construite à la feuille."""
|
||||||
self.rows.append(row)
|
self.rows.append(row)
|
||||||
|
|
||||||
|
def set_formula(self, coord, formula):
|
||||||
|
self.formulae[coord] = formula
|
||||||
|
|
||||||
def prepare(self):
|
def prepare(self):
|
||||||
"""génére un flux décrivant la feuille.
|
"""génére un flux décrivant la feuille.
|
||||||
Ce flux pourra ensuite être repris dans send_excel_file (classeur mono feille)
|
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)
|
# construction d'un flux (https://openpyxl.readthedocs.io/en/stable/tutorial.html#saving-as-a-stream)
|
||||||
self.prepare()
|
self.prepare()
|
||||||
|
for coord, formula in self.formulae.items():
|
||||||
|
self.ws[coord] = formula
|
||||||
with NamedTemporaryFile() as tmp:
|
with NamedTemporaryFile() as tmp:
|
||||||
self.wb.save(tmp.name)
|
self.wb.save(tmp.name)
|
||||||
tmp.seek(0)
|
tmp.seek(0)
|
||||||
@ -433,7 +441,12 @@ def excel_simple_table(
|
|||||||
return ws.generate()
|
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.
|
"""Genere feuille excel pour saisie des notes.
|
||||||
E: evaluation (dict)
|
E: evaluation (dict)
|
||||||
lines: liste de tuples
|
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("D", 164.0 / 7) # groupes
|
||||||
ws.set_column_dimension_width("E", 115.0 / 7) # notes
|
ws.set_column_dimension_width("E", 115.0 / 7) # notes
|
||||||
ws.set_column_dimension_width("F", 355.0 / 7) # remarques
|
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
|
# fontes
|
||||||
font_base = Font(name="Arial", size=12)
|
font_base = Font(name="Arial", size=12)
|
||||||
@ -497,15 +517,32 @@ def excel_feuille_saisie(evaluation: "Evaluation", titreannee, description, line
|
|||||||
"font": font_blue,
|
"font": font_blue,
|
||||||
"border": border_top,
|
"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
|
# ligne de titres
|
||||||
ws.append_single_cell_row(
|
ws.append_single_cell_row(
|
||||||
"Feuille saisie note (à enregistrer au format excel)", style_titres
|
"Feuille saisie note (à enregistrer au format excel)", style_titres
|
||||||
)
|
)
|
||||||
# lignes d'instructions
|
# lignes d'instructions
|
||||||
|
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(
|
ws.append_single_cell_row(
|
||||||
"Saisir les notes dans la colonne E (cases jaunes)", style_expl
|
"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)
|
ws.append_single_cell_row("Ne pas modifier les cases en mauve !", style_expl)
|
||||||
# Nom du semestre
|
# Nom du semestre
|
||||||
ws.append_single_cell_row(scu.unescape_html(titreannee), style_titres)
|
ws.append_single_cell_row(scu.unescape_html(titreannee), style_titres)
|
||||||
@ -518,8 +555,7 @@ def excel_feuille_saisie(evaluation: "Evaluation", titreannee, description, line
|
|||||||
# ligne blanche
|
# ligne blanche
|
||||||
ws.append_blank_row()
|
ws.append_blank_row()
|
||||||
# code et titres colonnes
|
# code et titres colonnes
|
||||||
ws.append_row(
|
title_row = [
|
||||||
[
|
|
||||||
ws.make_cell("!%s" % evaluation.id, style_ro),
|
ws.make_cell("!%s" % evaluation.id, style_ro),
|
||||||
ws.make_cell("Nom", style_titres),
|
ws.make_cell("Nom", style_titres),
|
||||||
ws.make_cell("Prénom", style_titres),
|
ws.make_cell("Prénom", style_titres),
|
||||||
@ -527,10 +563,25 @@ def excel_feuille_saisie(evaluation: "Evaluation", titreannee, description, line
|
|||||||
ws.make_cell("Note sur %g" % (evaluation.note_max or 0.0), style_titres),
|
ws.make_cell("Note sur %g" % (evaluation.note_max or 0.0), style_titres),
|
||||||
ws.make_cell("Remarque", 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
|
# etudiants
|
||||||
for line in lines:
|
for line_number, line in enumerate(lines):
|
||||||
st = style_nom
|
st = style_nom
|
||||||
if line[3] != "I":
|
if line[3] != "I":
|
||||||
st = style_dem
|
st = style_dem
|
||||||
@ -543,9 +594,15 @@ def excel_feuille_saisie(evaluation: "Evaluation", titreannee, description, line
|
|||||||
try:
|
try:
|
||||||
val = float(line[5])
|
val = float(line[5])
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
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]
|
val = line[5]
|
||||||
ws.append_row(
|
row = [
|
||||||
[
|
|
||||||
ws.make_cell("!" + line[0], style_ro), # code
|
ws.make_cell("!" + line[0], style_ro), # code
|
||||||
ws.make_cell(line[1], st),
|
ws.make_cell(line[1], st),
|
||||||
ws.make_cell(line[2], st),
|
ws.make_cell(line[2], st),
|
||||||
@ -553,7 +610,14 @@ def excel_feuille_saisie(evaluation: "Evaluation", titreannee, description, line
|
|||||||
ws.make_cell(val, style_notes), # note
|
ws.make_cell(val, style_notes), # note
|
||||||
ws.make_cell(line[6], style_comment), # comment
|
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
|
# explication en bas
|
||||||
ws.append_row([None, ws.make_cell("Code notes", style_titres)])
|
ws.append_row([None, ws.make_cell("Code notes", style_titres)])
|
||||||
|
@ -733,6 +733,8 @@ def saisie_notes_tableur(evaluation_id, group_ids=()):
|
|||||||
<li><a class="stdlink" href="feuille_saisie_notes?evaluation_id={evaluation_id}&{
|
<li><a class="stdlink" href="feuille_saisie_notes?evaluation_id={evaluation_id}&{
|
||||||
groups_infos.groups_query_args}"
|
groups_infos.groups_query_args}"
|
||||||
id="lnk_feuille_saisie">obtenir le fichier tableur à remplir</a>
|
id="lnk_feuille_saisie">obtenir le fichier tableur à remplir</a>
|
||||||
|
(<a class="stdlink" href="feuille_saisie_notes?evaluation_id={evaluation_id}&{
|
||||||
|
groups_infos.groups_query_args}&withnips=1">saisie par NIP</a>)
|
||||||
</li>
|
</li>
|
||||||
<li>ou <a class="stdlink" href="{url_for("notes.saisie_notes",
|
<li>ou <a class="stdlink" href="{url_for("notes.saisie_notes",
|
||||||
scodoc_dept=g.scodoc_dept, evaluation_id=evaluation_id)
|
scodoc_dept=g.scodoc_dept, evaluation_id=evaluation_id)
|
||||||
@ -875,7 +877,7 @@ def saisie_notes_tableur(evaluation_id, group_ids=()):
|
|||||||
return "\n".join(H)
|
return "\n".join(H)
|
||||||
|
|
||||||
|
|
||||||
def feuille_saisie_notes(evaluation_id, group_ids=[]):
|
def feuille_saisie_notes(evaluation_id, group_ids=[], withnips=0):
|
||||||
"""Document Excel pour saisie notes dans l'évaluation et les groupes indiqués"""
|
"""Document Excel pour saisie notes dans l'évaluation et les groupes indiqués"""
|
||||||
evaluation: Evaluation = db.session.get(Evaluation, evaluation_id)
|
evaluation: Evaluation = db.session.get(Evaluation, evaluation_id)
|
||||||
if not evaluation:
|
if not evaluation:
|
||||||
@ -922,15 +924,12 @@ def feuille_saisie_notes(evaluation_id, group_ids=[]):
|
|||||||
|
|
||||||
# une liste de liste de chaines: lignes de la feuille de calcul
|
# une liste de liste de chaines: lignes de la feuille de calcul
|
||||||
rows = []
|
rows = []
|
||||||
|
|
||||||
etuds = _get_sorted_etuds(evaluation, etudids, formsemestre.id)
|
etuds = _get_sorted_etuds(evaluation, etudids, formsemestre.id)
|
||||||
for e in etuds:
|
for e in etuds:
|
||||||
etudid = e["etudid"]
|
etudid = e["etudid"]
|
||||||
groups = sco_groups.get_etud_groups(etudid, formsemestre.id)
|
groups = sco_groups.get_etud_groups(etudid, formsemestre.id)
|
||||||
grc = sco_groups.listgroups_abbrev(groups)
|
grc = sco_groups.listgroups_abbrev(groups)
|
||||||
|
row = [
|
||||||
rows.append(
|
|
||||||
[
|
|
||||||
str(etudid),
|
str(etudid),
|
||||||
e["nom"].upper(),
|
e["nom"].upper(),
|
||||||
e["prenom"].lower().capitalize(),
|
e["prenom"].lower().capitalize(),
|
||||||
@ -939,11 +938,17 @@ def feuille_saisie_notes(evaluation_id, group_ids=[]):
|
|||||||
e["val"],
|
e["val"],
|
||||||
e["explanation"],
|
e["explanation"],
|
||||||
]
|
]
|
||||||
)
|
if withnips == 1:
|
||||||
|
row.append(e["code_nip"])
|
||||||
|
rows.append(row)
|
||||||
|
|
||||||
filename = f"notes_{eval_name}_{gr_title_filename}"
|
filename = f"notes_{eval_name}_{gr_title_filename}"
|
||||||
xls = sco_excel.excel_feuille_saisie(
|
xls = sco_excel.excel_feuille_saisie(
|
||||||
evaluation, formsemestre.titre_annee(), description, lines=rows
|
evaluation,
|
||||||
|
formsemestre.titre_annee(),
|
||||||
|
description,
|
||||||
|
lines=rows,
|
||||||
|
withnips=(withnips == 1),
|
||||||
)
|
)
|
||||||
return scu.send_file(xls, filename, scu.XLSX_SUFFIX, mime=scu.XLSX_MIMETYPE)
|
return scu.send_file(xls, filename, scu.XLSX_SUFFIX, mime=scu.XLSX_MIMETYPE)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user