forked from ScoDoc/ScoDoc
Merge pull request 'scodoc9_placement_PR' (#126) from jmplace/ScoDoc-Lille:scodoc9_placement_PR into master
Reviewed-on: https://scodoc.org/git/viennet/ScoDoc/pulls/126
This commit is contained in:
commit
11ba73d264
1
.gitignore
vendored
1
.gitignore
vendored
@ -170,3 +170,4 @@ Thumbs.db
|
||||
*.code-workspace
|
||||
|
||||
|
||||
copy
|
||||
|
@ -482,9 +482,9 @@ class GenTable(object):
|
||||
ses.append_blank_row() # empty line
|
||||
ses.append_single_cell_row(self.origin, style_base)
|
||||
if wb is None:
|
||||
return ses.generate_standalone()
|
||||
return ses.generate()
|
||||
else:
|
||||
ses.generate_embeded()
|
||||
ses.generate()
|
||||
|
||||
def text(self):
|
||||
"raw text representation of the table"
|
||||
|
@ -269,9 +269,14 @@ def etudarchive_generate_excel_sample(group_id=None, REQUEST=None):
|
||||
],
|
||||
extra_cols=["fichier_a_charger"],
|
||||
)
|
||||
return sco_excel.send_excel_file(
|
||||
REQUEST, data, "ImportFichiersEtudiants" + scu.XLSX_SUFFIX
|
||||
return scu.send_file(
|
||||
data,
|
||||
"ImportFichiersEtudiants",
|
||||
scu.XLSX_SUFFIX,
|
||||
scu.XLSX_MIMETYPE,
|
||||
attached=True,
|
||||
)
|
||||
# return sco_excel.send_excel_file(REQUEST, data, "ImportFichiersEtudiants" + scu.XLSX_SUFFIX)
|
||||
|
||||
|
||||
def etudarchive_import_files_form(group_id, REQUEST=None):
|
||||
|
@ -35,11 +35,11 @@ from enum import Enum
|
||||
from tempfile import NamedTemporaryFile
|
||||
|
||||
import openpyxl.utils.datetime
|
||||
from openpyxl.styles.numbers import FORMAT_NUMBER_00, FORMAT_GENERAL
|
||||
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.styles.numbers import FORMAT_NUMBER_00, FORMAT_GENERAL
|
||||
from openpyxl.comments import Comment
|
||||
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc import notesdb
|
||||
@ -59,24 +59,9 @@ class COLORS(Enum):
|
||||
LIGHT_YELLOW = "FFFFFF99"
|
||||
|
||||
|
||||
def send_excel_file(request, data, filename, mime=scu.XLSX_MIMETYPE):
|
||||
"""publication fichier.
|
||||
(on ne doit rien avoir émis avant, car ici sont générés les entetes)
|
||||
"""
|
||||
filename = (
|
||||
scu.unescape_html(scu.suppress_accents(filename))
|
||||
.replace("&", "")
|
||||
.replace(" ", "_")
|
||||
)
|
||||
request.RESPONSE.setHeader("content-type", mime)
|
||||
request.RESPONSE.setHeader(
|
||||
"content-disposition", 'attachment; filename="%s"' % filename
|
||||
)
|
||||
return data
|
||||
|
||||
|
||||
# Un style est enregistré comme un dictionnaire qui précise la valeur d'un attributdans la liste suivante:
|
||||
# font, border, number_format, fill, .. (cf https://openpyxl.readthedocs.io/en/stable/styles.html#working-with-styles)
|
||||
# font, border, number_format, fill,...
|
||||
# (cf https://openpyxl.readthedocs.io/en/stable/styles.html#working-with-styles)
|
||||
|
||||
|
||||
def xldate_as_datetime(xldate, datemode=0):
|
||||
@ -86,6 +71,12 @@ def xldate_as_datetime(xldate, datemode=0):
|
||||
return openpyxl.utils.datetime.from_ISO8601(xldate)
|
||||
|
||||
|
||||
def adjust_sheetname(sheet_name):
|
||||
# Le nom de la feuille ne peut faire plus de 31 caractères.
|
||||
# si la taille du nom de feuille est > 31 on tronque (on pourrait remplacer par 'feuille' ?)
|
||||
return sheet_name[:31]
|
||||
|
||||
|
||||
class ScoExcelBook:
|
||||
"""Permet la génération d'un classeur xlsx composé de plusieurs feuilles.
|
||||
usage:
|
||||
@ -98,13 +89,16 @@ class ScoExcelBook:
|
||||
|
||||
def __init__(self):
|
||||
self.sheets = [] # list of sheets
|
||||
self.wb = Workbook(write_only=True)
|
||||
|
||||
def create_sheet(self, sheet_name="feuille", default_style=None):
|
||||
"""Crée une nouvelle feuille dans ce classeur
|
||||
sheet_name -- le nom de la feuille
|
||||
default_style -- le style par défaut
|
||||
"""
|
||||
sheet = ScoExcelSheet(sheet_name, default_style)
|
||||
sheet_name = adjust_sheetname(sheet_name)
|
||||
ws = self.wb.create_sheet(sheet_name)
|
||||
sheet = ScoExcelSheet(sheet_name, default_style, ws)
|
||||
self.sheets.append(sheet)
|
||||
return sheet
|
||||
|
||||
@ -112,12 +106,12 @@ class ScoExcelBook:
|
||||
"""génération d'un stream binaire représentant la totalité du classeur.
|
||||
retourne le flux
|
||||
"""
|
||||
wb = Workbook(write_only=True)
|
||||
for sheet in self.sheets:
|
||||
sheet.generate(self)
|
||||
# construction d'un flux (https://openpyxl.readthedocs.io/en/stable/tutorial.html#saving-as-a-stream)
|
||||
sheet.prepare()
|
||||
# construction d'un flux
|
||||
# (https://openpyxl.readthedocs.io/en/stable/tutorial.html#saving-as-a-stream)
|
||||
with NamedTemporaryFile() as tmp:
|
||||
wb.save(tmp.name)
|
||||
self.wb.save(tmp.name)
|
||||
tmp.seek(0)
|
||||
return tmp.read()
|
||||
|
||||
@ -125,6 +119,7 @@ class ScoExcelBook:
|
||||
def excel_make_style(
|
||||
bold=False,
|
||||
italic=False,
|
||||
outline=False,
|
||||
color: COLORS = COLORS.BLACK,
|
||||
bgcolor: COLORS = None,
|
||||
halign=None,
|
||||
@ -145,7 +140,14 @@ def excel_make_style(
|
||||
size -- taille de police
|
||||
"""
|
||||
style = {}
|
||||
font = Font(name=font_name, bold=bold, italic=italic, color=color.value, size=size)
|
||||
font = Font(
|
||||
name=font_name,
|
||||
bold=bold,
|
||||
italic=italic,
|
||||
outline=outline,
|
||||
color=color.value,
|
||||
size=size,
|
||||
)
|
||||
style["font"] = font
|
||||
if bgcolor:
|
||||
style["fill"] = PatternFill(fill_type="solid", fgColor=bgcolor.value)
|
||||
@ -182,41 +184,93 @@ class ScoExcelSheet:
|
||||
"""
|
||||
|
||||
def __init__(self, sheet_name="feuille", default_style=None, wb=None):
|
||||
"""Création de la feuille.
|
||||
sheet_name -- le nom de la feuille
|
||||
default_style -- le style par défaut des cellules
|
||||
wb -- le WorkBook dans laquelle se trouve la feuille. Si wb est None (cas d'un classeur mono-feuille),
|
||||
un workbook est crée et associé à cette feuille.
|
||||
"""Création de la feuille. sheet_name
|
||||
-- le nom de la feuille default_style
|
||||
-- le style par défaut des cellules ws
|
||||
-- None si la feuille est autonome (dans ce cas ell crée son propre wb), sinon c'est la worksheet
|
||||
créée par le workbook propriétaire un workbook est crée et associé à cette feuille.
|
||||
"""
|
||||
# Le nom de la feuille ne peut faire plus de 31 caractères.
|
||||
# si la taille du nom de feuille est > 31 on tronque (on pourrait remplacer par 'feuille' ?)
|
||||
self.sheet_name = sheet_name[
|
||||
:31
|
||||
] # if len(sheet_name) > 31: sheet_name = 'Feuille' ?
|
||||
self.rows = [] # list of list of cells
|
||||
# self.cells_styles_lico = {} # { (li,co) : style }
|
||||
# self.cells_styles_li = {} # { li : style }
|
||||
# self.cells_styles_co = {} # { co : style }
|
||||
self.sheet_name = adjust_sheetname(sheet_name)
|
||||
if default_style is None:
|
||||
default_style = excel_make_style()
|
||||
self.default_style = default_style
|
||||
self.wb = wb or Workbook(write_only=True) # Création de workbook si nécessaire
|
||||
self.ws = self.wb.create_sheet(title=self.sheet_name)
|
||||
if wb is None:
|
||||
self.wb = Workbook()
|
||||
self.ws = self.wb.active
|
||||
self.ws.title = self.sheet_name
|
||||
else:
|
||||
self.wb = None
|
||||
self.ws = wb
|
||||
# internal data
|
||||
self.rows = [] # list of list of cells
|
||||
self.column_dimensions = {}
|
||||
self.row_dimensions = {}
|
||||
|
||||
def set_column_dimension_width(self, cle, value):
|
||||
"""Détermine la largeur d'une colonne.
|
||||
cle -- identifie la colonne ("A"n "B", ...)
|
||||
value -- la dimension (unité : 7 pixels comme affiché dans Excel)
|
||||
def excel_make_composite_style(
|
||||
self,
|
||||
alignment=None,
|
||||
border=None,
|
||||
fill=None,
|
||||
number_format=None,
|
||||
font=None,
|
||||
):
|
||||
style = {}
|
||||
if font is not None:
|
||||
style["font"] = font
|
||||
if alignment is not None:
|
||||
style["alignment"] = alignment
|
||||
if border is not None:
|
||||
style["border"] = border
|
||||
if fill is not None:
|
||||
style["fill"] = fill
|
||||
if number_format is None:
|
||||
style["number_format"] = FORMAT_GENERAL
|
||||
else:
|
||||
style["number_format"] = number_format
|
||||
return style
|
||||
|
||||
@staticmethod
|
||||
def i2col(idx):
|
||||
if idx < 26: # one letter key
|
||||
return chr(idx + 65)
|
||||
else: # two letters AA..ZZ
|
||||
first = (idx // 26) + 66
|
||||
second = (idx % 26) + 65
|
||||
return "" + chr(first) + chr(second)
|
||||
|
||||
def set_column_dimension_width(self, cle=None, value=21):
|
||||
"""Détermine la largeur d'une colonne. cle -- identifie la colonne ("A" "B", ... ou 0, 1, 2, ...) si None,
|
||||
value donne la liste des largeurs de colonnes depuis A, B, C, ... value -- la dimension (unité : 7 pixels
|
||||
comme affiché dans Excel)
|
||||
"""
|
||||
if cle is None:
|
||||
for i, val in enumerate(value):
|
||||
self.ws.column_dimensions[self.i2col(i)].width = val
|
||||
# No keys: value is a list of widths
|
||||
elif type(cle) == str: # accepts set_column_with("D", ...)
|
||||
self.ws.column_dimensions[cle].width = value
|
||||
else:
|
||||
self.ws.column_dimensions[self.i2col(cle)].width = value
|
||||
|
||||
def set_column_dimension_hidden(self, cle, value):
|
||||
"""Masque ou affiche une colonne.
|
||||
cle -- identifie la colonne ("A"n "B", ...)
|
||||
def set_row_dimension_height(self, cle=None, value=21):
|
||||
"""Détermine la hauteur d'une ligne. cle -- identifie la ligne (1, 2, ...) si None,
|
||||
value donne la liste des hauteurs de colonnes depuis 1, 2, 3, ... value -- la dimension
|
||||
"""
|
||||
if cle is None:
|
||||
for i, val in enumerate(value, start=1):
|
||||
self.ws.row_dimensions[i].height = val
|
||||
# No keys: value is a list of widths
|
||||
else:
|
||||
self.ws.row_dimensions[cle].height = value
|
||||
|
||||
def set_row_dimension_hidden(self, cle, value):
|
||||
"""Masque ou affiche une ligne.
|
||||
cle -- identifie la colonne (1...)
|
||||
value -- boolean (vrai = colonne cachée)
|
||||
"""
|
||||
self.ws.column_dimensions[cle].hidden = value
|
||||
self.ws.row_dimensions[cle].hidden = value
|
||||
|
||||
def make_cell(self, value: any = None, style=None, comment=None):
|
||||
"""Construit une cellule.
|
||||
@ -232,8 +286,12 @@ class ScoExcelSheet:
|
||||
style = self.default_style
|
||||
if "font" in style:
|
||||
cell.font = style["font"]
|
||||
if "alignment" in style:
|
||||
cell.alignment = style["alignment"]
|
||||
if "border" in style:
|
||||
cell.border = style["border"]
|
||||
if "fill" in style:
|
||||
cell.fill = style["fill"]
|
||||
if "number_format" in style:
|
||||
cell.number_format = style["number_format"]
|
||||
if "fill" in style:
|
||||
@ -272,73 +330,31 @@ class ScoExcelSheet:
|
||||
"""ajoute une ligne déjà construite à la feuille."""
|
||||
self.rows.append(row)
|
||||
|
||||
# def set_style(self, style=None, li=None, co=None):
|
||||
# if li is not None and co is not None:
|
||||
# self.cells_styles_lico[(li, co)] = style
|
||||
# elif li is None:
|
||||
# self.cells_styles_li[li] = style
|
||||
# elif co is None:
|
||||
# self.cells_styles_co[co] = style
|
||||
#
|
||||
# def get_cell_style(self, li, co):
|
||||
# """Get style for specified cell"""
|
||||
# return (
|
||||
# self.cells_styles_lico.get((li, co), None)
|
||||
# or self.cells_styles_li.get(li, None)
|
||||
# or self.cells_styles_co.get(co, None)
|
||||
# or self.default_style
|
||||
# )
|
||||
|
||||
def _generate_ws(self):
|
||||
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)
|
||||
ou pour la génération d'un classeur multi-feuilles
|
||||
"""
|
||||
for col in self.column_dimensions.keys():
|
||||
self.ws.column_dimensions[col] = self.column_dimensions[col]
|
||||
for row in self.column_dimensions.keys():
|
||||
self.ws.column_dimensions[row] = self.column_dimensions[row]
|
||||
for row in self.row_dimensions.keys():
|
||||
self.ws.row_dimensions[row] = self.row_dimensions[row]
|
||||
for row in self.rows:
|
||||
self.ws.append(row)
|
||||
|
||||
def generate_standalone(self):
|
||||
def generate(self):
|
||||
"""génération d'un classeur mono-feuille"""
|
||||
self._generate_ws()
|
||||
# this method makes sense only if it is a standalone worksheet (else call workbook.generate()
|
||||
if self.wb is None: # embeded sheet
|
||||
raise ScoValueError("can't generate a single sheet from a ScoWorkbook")
|
||||
|
||||
# construction d'un flux (https://openpyxl.readthedocs.io/en/stable/tutorial.html#saving-as-a-stream)
|
||||
self.prepare()
|
||||
with NamedTemporaryFile() as tmp:
|
||||
self.wb.save(tmp.name)
|
||||
tmp.seek(0)
|
||||
return tmp.read()
|
||||
|
||||
def generate_embeded(self):
|
||||
"""generation d'une feuille include dans un classeur multi-feuilles"""
|
||||
self._generate_ws()
|
||||
|
||||
def gen_workbook(self, wb=None):
|
||||
"""TODO: à remplacer"""
|
||||
"""Generates and returns a workbook from stored data.
|
||||
If wb, add a sheet (tab) to the existing workbook (in this case, returns None).
|
||||
"""
|
||||
if wb is None:
|
||||
wb = Workbook() # Création du fichier
|
||||
sauvegarde = True
|
||||
else:
|
||||
sauvegarde = False
|
||||
ws0 = wb.add_sheet(self.sheet_name)
|
||||
li = 0
|
||||
for row in self.rows:
|
||||
co = 0
|
||||
for c in row:
|
||||
# safety net: allow only str, int and float
|
||||
# #py3 #sco8 A revoir lors de la ré-écriture de ce module
|
||||
# XXX if type(c) not in (IntType, FloatType):
|
||||
# c = str(c).decode(scu.SCO_ENCODING)
|
||||
ws0.write(li, co, c, self.get_cell_style(li, co))
|
||||
co += 1
|
||||
li += 1
|
||||
if sauvegarde:
|
||||
return wb.savetostr()
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def excel_simple_table(
|
||||
titles=None, lines=None, sheet_name=b"feuille", titles_styles=None, comments=None
|
||||
@ -377,7 +393,7 @@ def excel_simple_table(
|
||||
cell_style = text_style
|
||||
cells.append(ws.make_cell(it, cell_style))
|
||||
ws.append_row(cells)
|
||||
return ws.generate_standalone()
|
||||
return ws.generate()
|
||||
|
||||
|
||||
def excel_feuille_saisie(e, titreannee, description, lines):
|
||||
@ -538,7 +554,7 @@ def excel_feuille_saisie(e, titreannee, description, lines):
|
||||
ws.make_cell("cellule vide -> note non modifiée", style_expl),
|
||||
]
|
||||
)
|
||||
return ws.generate_standalone()
|
||||
return ws.generate()
|
||||
|
||||
|
||||
def excel_bytes_to_list(bytes_content):
|
||||
@ -758,4 +774,4 @@ def excel_feuille_listeappel(
|
||||
cell_2 = ws.make_cell(("Liste éditée le " + dt), style1i)
|
||||
ws.append_row([None, cell_2])
|
||||
|
||||
return ws.generate_standalone()
|
||||
return ws.generate()
|
||||
|
@ -722,7 +722,10 @@ def groups_table(
|
||||
server_name=request.url_root,
|
||||
)
|
||||
filename = "liste_%s" % groups_infos.groups_filename + ".xlsx"
|
||||
return sco_excel.send_excel_file(REQUEST, xls, filename)
|
||||
return scu.send_file(
|
||||
xls, filename, scu.XLSX_SUFFIX, scu.XLSX_MIMETYPE, attached=True
|
||||
)
|
||||
# return sco_excel.send_excel_file(REQUEST, xls, filename)
|
||||
elif format == "allxls":
|
||||
# feuille Excel avec toutes les infos etudiants
|
||||
if not groups_infos.members:
|
||||
@ -791,7 +794,10 @@ def groups_table(
|
||||
title = "etudiants_%s" % groups_infos.groups_filename
|
||||
xls = sco_excel.excel_simple_table(titles=titles, lines=L, sheet_name=title)
|
||||
filename = title + scu.XLSX_SUFFIX
|
||||
return sco_excel.send_excel_file(REQUEST, xls, filename)
|
||||
return scu.send_file(
|
||||
xls, filename, scu.XLSX_SUFFIX, scu.XLSX_MIMETYPE, attached=True
|
||||
)
|
||||
# return sco_excel.send_excel_file(REQUEST, xls, filename)
|
||||
else:
|
||||
raise ValueError("unsupported format")
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -324,5 +324,12 @@ def feuille_preparation_jury(formsemestre_id, REQUEST):
|
||||
REQUEST.AUTHENTICATED_USER,
|
||||
)
|
||||
)
|
||||
xls = ws.generate_standalone()
|
||||
return sco_excel.send_excel_file(REQUEST, xls, f"PrepaJury{sn}{scu.XLSX_SUFFIX}")
|
||||
xls = ws.generate()
|
||||
return scu.send_file(
|
||||
xls,
|
||||
f"PrepaJury{sn}{scu.XLSX_SUFFIX}",
|
||||
scu.XLSX_SUFFIX,
|
||||
scu.XLSX_MIMETYPE,
|
||||
attached=True,
|
||||
)
|
||||
# return sco_excel.send_excel_file(REQUEST, xls, f"PrepaJury{sn}{scu.XLSX_SUFFIX}")
|
||||
|
@ -829,7 +829,10 @@ def feuille_saisie_notes(evaluation_id, group_ids=[], REQUEST=None):
|
||||
|
||||
filename = "notes_%s_%s.xlsx" % (evalname, gr_title_filename)
|
||||
xls = sco_excel.excel_feuille_saisie(E, sem["titreannee"], description, lines=L)
|
||||
return sco_excel.send_excel_file(REQUEST, xls, filename)
|
||||
return scu.send_file(
|
||||
xls, filename, scu.XLSX_SUFFIX, scu.XLSX_MIMETYPE, attached=True
|
||||
)
|
||||
# return sco_excel.send_excel_file(REQUEST, xls, filename)
|
||||
|
||||
|
||||
def has_existing_decision(M, E, etudid):
|
||||
|
@ -486,7 +486,10 @@ def photos_generate_excel_sample(group_ids=[], REQUEST=None):
|
||||
],
|
||||
extra_cols=["fichier_photo"],
|
||||
)
|
||||
return sco_excel.send_excel_file(REQUEST, data, "ImportPhotos" + scu.XLSX_SUFFIX)
|
||||
return scu.send_file(
|
||||
data, "ImportPhotos", scu.XLSX_SUFFIX, scu.XLSX_MIMETYPE, attached=True
|
||||
)
|
||||
# return sco_excel.send_excel_file(REQUEST, data, "ImportPhotos" + scu.XLSX_SUFFIX)
|
||||
|
||||
|
||||
def photos_import_files_form(group_ids=[], REQUEST=None):
|
||||
|
@ -1092,13 +1092,11 @@ h2.formsemestre, .gtrcontent h2 {
|
||||
#formnotes td.tf-fieldlabel {
|
||||
border-bottom: 1px dotted #fdcaca;
|
||||
}
|
||||
|
||||
/* Formulaires ScoDoc 9 */
|
||||
form.sco-form {
|
||||
margin-top: 1em;
|
||||
.wtf-field li {
|
||||
display: inline;
|
||||
}
|
||||
div.sco-submit {
|
||||
margin-top: 2em;
|
||||
.wtf-field .errors {
|
||||
color: red ; font-weight: bold;
|
||||
}
|
||||
/*
|
||||
.formsemestre_menubar {
|
||||
|
77
app/templates/scodoc/forms/placement.html
Normal file
77
app/templates/scodoc/forms/placement.html
Normal file
@ -0,0 +1,77 @@
|
||||
{% import 'bootstrap/wtf.html' as wtf %}
|
||||
|
||||
{% macro render_field(field) %}
|
||||
<tr>
|
||||
<td class="wtf-field">{{ field.label }}</td>
|
||||
<td class="wtf-field">{{ field()|safe }}
|
||||
{% if field.errors %}
|
||||
<ul class=errors>
|
||||
{% for error in field.errors %}
|
||||
<li>{{ error }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endmacro %}
|
||||
|
||||
<div class="saisienote_etape1 form_placement">
|
||||
<form method=post>
|
||||
{{ form.evaluation_id }}
|
||||
{{ form.csrf_token }}
|
||||
<table class="tf">
|
||||
<tbody>
|
||||
{{ render_field(form.surveillants) }}
|
||||
{{ render_field(form.batiment) }}
|
||||
{{ render_field(form.salle) }}
|
||||
{{ render_field(form.nb_rangs) }}
|
||||
{{ render_field(form.etiquetage) }}
|
||||
{% if form.has_groups %}
|
||||
{{ render_field(form.groups) }}
|
||||
<!-- Tentative de recréer le choix des groupes sous forme de cases à cocher // demande à créer des champs wtf dynamiquement
|
||||
{% for partition in form.groups_tree %}
|
||||
<tr>
|
||||
{% if partition == 'Tous' %}
|
||||
<td rowspan="{{ form.nb_groups }}">Groupes</td>
|
||||
{% endif %}
|
||||
<td>{{ partition }}</td>
|
||||
<td>
|
||||
{% for groupe in form.groups_tree[partition] %}
|
||||
{{ groupe }}{{ form[form.groups_tree[partition][groupe]] }}
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
-->
|
||||
{% endif %}
|
||||
{{ render_field(form.file_format) }}
|
||||
</tbody>
|
||||
</table>
|
||||
<p>
|
||||
<input id="gr_submit" type=submit value="Ok">
|
||||
<input id="gr_cancel" type=submit value="Annuler">
|
||||
</script>
|
||||
</form>
|
||||
<h3>Explications</h3>
|
||||
<ul>
|
||||
<li>préciser les surveillants et la localisation (bâtiment et salle) et indiquer le nombre de colonnes;</li>
|
||||
<li>deux types de placements sont possibles :
|
||||
<ul>
|
||||
<li>continue suppose que les tables ont toutes un numéro unique;</li>
|
||||
<li>coordonnées localise chaque table via un numéro de colonne et un numéro de ligne (ou rangée).</li>
|
||||
</ul></li>
|
||||
<li>il est possible de choisir un ou plusieurs groupes (shift/ctrl click) ou de choisir 'tous'.</li>
|
||||
<li>Choisir le format du fichier résultat :
|
||||
<ul>
|
||||
<li>le format pdf consiste en un tableau précisant pour chaque étudiant la localisation de sa table;</li>
|
||||
<li>le format xls produit un classeur avec deux onglets:
|
||||
<ul>
|
||||
<li>le premier onglet donne une vue de la salle avec la localisation des étudiants et
|
||||
peut servir de feuille d'émargement;</li>
|
||||
<li>le second onglet est un tableau similaire à celui du fichier pdf;</li>
|
||||
</ul></li>
|
||||
</ul> </li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
@ -1645,8 +1645,8 @@ sco_publish(
|
||||
"/placement_eval_selectetuds",
|
||||
sco_placement.placement_eval_selectetuds,
|
||||
Permission.ScoEnsView,
|
||||
methods=["GET", "POST"],
|
||||
)
|
||||
sco_publish("/do_placement", sco_placement.do_placement, Permission.ScoEnsView)
|
||||
|
||||
# --- Saisie des notes
|
||||
sco_publish(
|
||||
|
@ -1937,7 +1937,10 @@ def import_generate_excel_sample(REQUEST, with_codesemestre="1"):
|
||||
data = sco_import_etuds.sco_import_generate_excel_sample(
|
||||
format, with_codesemestre, exclude_cols=["photo_filename"]
|
||||
)
|
||||
return sco_excel.send_excel_file(REQUEST, data, "ImportEtudiants" + scu.XLSX_SUFFIX)
|
||||
return scu.send_file(
|
||||
data, "ImportEtudiants", scu.XLSX_SUFFIX, scu.XLSX_MIMETYPE, attached=True
|
||||
)
|
||||
# return sco_excel.send_excel_file(REQUEST, data, "ImportEtudiants" + scu.XLSX_SUFFIX)
|
||||
|
||||
|
||||
# --- Données admission
|
||||
@ -1955,9 +1958,10 @@ def import_generate_admission_sample(REQUEST, formsemestre_id):
|
||||
exclude_cols=["nationalite", "foto", "photo_filename"],
|
||||
group_ids=[group["group_id"]],
|
||||
)
|
||||
return sco_excel.send_excel_file(
|
||||
REQUEST, data, "AdmissionEtudiants" + scu.XLSX_SUFFIX
|
||||
return scu.send_file(
|
||||
data, "AdmissionEtudiants", scu.XLSX_SUFFIX, scu.XLSX_MIMETYPE, attached=True
|
||||
)
|
||||
# return sco_excel.send_excel_file(REQUEST, data, "AdmissionEtudiants" + scu.XLSX_SUFFIX)
|
||||
|
||||
|
||||
# --- Données admission depuis fichier excel (version nov 2016)
|
||||
|
@ -65,8 +65,6 @@ from app import log
|
||||
from app.scodoc.sco_exceptions import AccessDenied, ScoValueError
|
||||
from app.scodoc.sco_permissions_check import can_handle_passwd
|
||||
from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message
|
||||
from app.scodoc.sco_excel import send_excel_file
|
||||
from app.scodoc.sco_import_users import generate_excel_sample
|
||||
from app.views import users_bp as bp
|
||||
|
||||
|
||||
@ -490,9 +488,10 @@ def create_user_form(REQUEST, user_name=None, edit=0, all_roles=1):
|
||||
def import_users_generate_excel_sample(REQUEST):
|
||||
"une feuille excel pour importation utilisateurs"
|
||||
data = sco_import_users.generate_excel_sample()
|
||||
return sco_excel.send_excel_file(
|
||||
REQUEST, data, "ImportUtilisateurs" + scu.XLSX_SUFFIX
|
||||
return scu.send_file(
|
||||
data, "ImportUtilisateurs", scu.XLSX_SUFFIX, scu.XLSX_MIMETYPE, attached=True
|
||||
)
|
||||
# return sco_excel.send_excel_file(REQUEST, data, "ImportUtilisateurs" + scu.XLSX_SUFFIX)
|
||||
|
||||
|
||||
@bp.route("/import_users_form", methods=["GET", "POST"])
|
||||
|
Loading…
Reference in New Issue
Block a user