forked from ScoDoc/ScoDoc
apres refactor merge cells
This commit is contained in:
parent
7427db0ba6
commit
66480f0d11
@ -1,84 +0,0 @@
|
|||||||
import openpyxl.cell
|
|
||||||
from openpyxl.cell import Cell
|
|
||||||
from openpyxl.worksheet.worksheet import Worksheet
|
|
||||||
|
|
||||||
from app.but.prepajury_xl import (
|
|
||||||
ScoExcelSheet,
|
|
||||||
)
|
|
||||||
from app.but.prepajury_xl_format import (
|
|
||||||
SCO_HALIGN,
|
|
||||||
SCO_VALIGN,
|
|
||||||
SCO_FONTNAME,
|
|
||||||
SCO_FONTSIZE,
|
|
||||||
FMT,
|
|
||||||
Sco_Style,
|
|
||||||
)
|
|
||||||
|
|
||||||
base_signature = (
|
|
||||||
FMT.FONT_NAME.set(SCO_FONTNAME.FONTNAME_CALIBRI)
|
|
||||||
+ FMT.FONT_SIZE.set(SCO_FONTSIZE.FONTSIZE_13)
|
|
||||||
+ FMT.ALIGNMENT_HALIGN.set(SCO_HALIGN.HALIGN_CENTER)
|
|
||||||
+ FMT.ALIGNMENT_VALIGN.set(SCO_VALIGN.VALIGN_CENTER)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def set_cell(
|
|
||||||
ws: Cell,
|
|
||||||
row: int,
|
|
||||||
column: int,
|
|
||||||
text: str = "",
|
|
||||||
from_signature: int = 0,
|
|
||||||
composition: list = [],
|
|
||||||
):
|
|
||||||
cell = ws.cell(row, column)
|
|
||||||
cell.value = text
|
|
||||||
sign = FMT.compose(composition, from_signature)
|
|
||||||
style: Sco_Style = FMT.style(sign)
|
|
||||||
style.apply(cell)
|
|
||||||
|
|
||||||
|
|
||||||
class Merge_Engine:
|
|
||||||
def __init__(self, ws: Worksheet, start_row: int = 1, start_column: int = 1):
|
|
||||||
self.start_row: int = start_row
|
|
||||||
self.start_column: int = start_column
|
|
||||||
self.ws: Worksheet = ws
|
|
||||||
|
|
||||||
def close(self, end_row=None, end_column=None):
|
|
||||||
if end_row is None:
|
|
||||||
end_row = self.start_row
|
|
||||||
if end_column is None:
|
|
||||||
end_column = self.start_column
|
|
||||||
if (end_row - self.start_row > 0) or (end_column - self.start_column > 0):
|
|
||||||
self.ws.merge_cells(
|
|
||||||
start_row=self.start_row,
|
|
||||||
start_column=self.start_column,
|
|
||||||
end_row=end_row,
|
|
||||||
end_column=end_column,
|
|
||||||
)
|
|
||||||
if end_row is not None:
|
|
||||||
end_row = end_row + 1
|
|
||||||
if end_column is not None:
|
|
||||||
end_column = end_column + 1
|
|
||||||
|
|
||||||
|
|
||||||
class Sco_Cell:
|
|
||||||
def __init__(
|
|
||||||
self, text: str = None, signature: int = base_signature, comment: str = None
|
|
||||||
):
|
|
||||||
self.text = text
|
|
||||||
self.signature = signature or base_signature
|
|
||||||
self.comment = comment
|
|
||||||
|
|
||||||
def format(self, value=None):
|
|
||||||
self.signature = FMT.ALL.composante.write(self.signature, value)
|
|
||||||
|
|
||||||
def copy(self, cell: openpyxl.cell.Cell):
|
|
||||||
cell.value = self.text
|
|
||||||
style: Sco_Style = FMT.style(self.signature)
|
|
||||||
style.apply(cell)
|
|
||||||
|
|
||||||
def make_cell(self, worksheet: ScoExcelSheet):
|
|
||||||
cell = worksheet.make_cell(self.text or "")
|
|
||||||
style: Sco_Style = FMT.style(self.signature)
|
|
||||||
style.apply(cell)
|
|
||||||
return cell
|
|
@ -1,7 +1,5 @@
|
|||||||
import openpyxl
|
import openpyxl
|
||||||
from openpyxl.worksheet.worksheet import Worksheet
|
from openpyxl.worksheet.worksheet import Worksheet
|
||||||
|
|
||||||
from app.but.prepajury_cells import Sco_Cell, base_signature, set_cell, Merge_Engine
|
|
||||||
from app.but.prepajury_xl_format import (
|
from app.but.prepajury_xl_format import (
|
||||||
SCO_COLORS,
|
SCO_COLORS,
|
||||||
FMT,
|
FMT,
|
||||||
@ -10,9 +8,17 @@ from app.but.prepajury_xl_format import (
|
|||||||
SCO_HALIGN,
|
SCO_HALIGN,
|
||||||
SCO_BORDERTHICKNESS,
|
SCO_BORDERTHICKNESS,
|
||||||
Sco_Style,
|
Sco_Style,
|
||||||
|
HAIR_BLACK,
|
||||||
|
SCO_NUMBER_FORMAT,
|
||||||
)
|
)
|
||||||
from app.models import ApcCompetence, ApcParcours
|
from app.models import ApcCompetence, ApcParcours
|
||||||
from app.but.prepajury_xl import ScoExcelBook, ScoExcelSheet
|
from app.but.prepajury_xl import (
|
||||||
|
ScoExcelBook,
|
||||||
|
ScoExcelSheet,
|
||||||
|
base_signature,
|
||||||
|
Frame_Engine,
|
||||||
|
Merge_Engine,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def parite(semestre_idx):
|
def parite(semestre_idx):
|
||||||
@ -39,54 +45,6 @@ header_colors = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class _Header:
|
|
||||||
def __init__(self):
|
|
||||||
self.lines: list[list[Sco_Cell]] = []
|
|
||||||
self.presets = [None, None, None, None]
|
|
||||||
self.signatures = [
|
|
||||||
base_signature,
|
|
||||||
base_signature,
|
|
||||||
base_signature,
|
|
||||||
base_signature,
|
|
||||||
]
|
|
||||||
|
|
||||||
def setLabelOnce(self, rang: int, label: str):
|
|
||||||
self.presets[rang] = label
|
|
||||||
|
|
||||||
def setSignatures(self, rangs: list[int], signature: int):
|
|
||||||
for rang in rangs:
|
|
||||||
self.signatures[rang] = signature
|
|
||||||
|
|
||||||
def add_column(
|
|
||||||
self,
|
|
||||||
label0=None,
|
|
||||||
label1=None,
|
|
||||||
label2=None,
|
|
||||||
label3=None,
|
|
||||||
labels: list[str] = None,
|
|
||||||
):
|
|
||||||
if labels is None:
|
|
||||||
labels = [label0, label1, label2, label3]
|
|
||||||
cells: list(Sco_Cell) = [
|
|
||||||
Sco_Cell(preset or label, signature=signature)
|
|
||||||
for label, preset, signature in zip(labels, self.presets, self.signatures)
|
|
||||||
]
|
|
||||||
self.presets = [None, None, None, None]
|
|
||||||
self.lines.append(cells)
|
|
||||||
|
|
||||||
def extend(self, header):
|
|
||||||
self.lines.extend(header.lines)
|
|
||||||
|
|
||||||
def write(self, worksheet: ScoExcelSheet):
|
|
||||||
column = 1
|
|
||||||
for items in self.lines:
|
|
||||||
items[0].copy(worksheet.ws.cell(1, column))
|
|
||||||
items[1].copy(worksheet.ws.cell(2, column))
|
|
||||||
items[2].copy(worksheet.ws.cell(3, column))
|
|
||||||
items[3].copy(worksheet.ws.cell(4, column))
|
|
||||||
column += 1
|
|
||||||
|
|
||||||
|
|
||||||
class NiveauDesc:
|
class NiveauDesc:
|
||||||
def __init__(self, scodocNiveau):
|
def __init__(self, scodocNiveau):
|
||||||
self.fromScodoc = scodocNiveau
|
self.fromScodoc = scodocNiveau
|
||||||
@ -167,14 +125,12 @@ class AnneeDesc:
|
|||||||
for _ in range(3):
|
for _ in range(3):
|
||||||
header.add_column()
|
header.add_column()
|
||||||
|
|
||||||
def generate_header(self, ws: Worksheet, column: int):
|
def generate_header(self, ws: ScoExcelSheet, column: int):
|
||||||
start = column
|
start = column
|
||||||
but_signature = FMT.FILL_BGCOLOR.write(
|
but_signature = FMT.FILL_BGCOLOR.write(
|
||||||
signature=base_signature, value=header_colors[self.codeAnnee]["BUT"].value
|
signature=base_signature, value=header_colors[self.codeAnnee]["BUT"].value
|
||||||
)
|
)
|
||||||
but_style = FMT.style(but_signature)
|
ws.set_cell(
|
||||||
set_cell(
|
|
||||||
ws,
|
|
||||||
1,
|
1,
|
||||||
column,
|
column,
|
||||||
text=self.codeAnnee,
|
text=self.codeAnnee,
|
||||||
@ -184,25 +140,24 @@ class AnneeDesc:
|
|||||||
(FMT.BORDER_LEFT_STYLE, SCO_BORDERTHICKNESS.BORDER_MEDIUM.value),
|
(FMT.BORDER_LEFT_STYLE, SCO_BORDERTHICKNESS.BORDER_MEDIUM.value),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
but_style.apply(ws.cell(1, column))
|
|
||||||
# for niveau in self.niveaux.values():
|
# for niveau in self.niveaux.values():
|
||||||
# column = niveau.generate_header(ws, column)
|
# column = niveau.generate_header(ws, column)
|
||||||
# for i in range(len(self.niveaux), 6):
|
# for i in range(len(self.niveaux), 6):
|
||||||
# column = self.generate_blank_niveau(ws, column)
|
# column = self.generate_blank_niveau(ws, column)
|
||||||
ws.cell(2, column).value = "Année"
|
ws.set_cell(2, column, "Année")
|
||||||
# cell_format(ws.cell(2, column), but_signature, [(FMT.FONT_BOLD, True)])
|
# cell_format(ws.cell(2, column), but_signature, [(FMT.FONT_BOLD, True)])
|
||||||
ws.cell(3, column).value = "Nb"
|
ws.set_cell(3, column, "Nb")
|
||||||
ws.cell(4, column).value = "RCUE"
|
ws.set_cell(4, column, "RCUE")
|
||||||
column += 1
|
column += 1
|
||||||
ws.cell(2, column).value = "Année"
|
ws.set_cell(2, column, "Année")
|
||||||
ws.cell(4, column).value = "Moy."
|
ws.set_cell(4, column, "Moy.")
|
||||||
column += 1
|
column += 1
|
||||||
if self.codeAnnee == "BUT2":
|
if self.codeAnnee == "BUT2":
|
||||||
ws.cell(3, column).value = "DUT"
|
ws.set_cell(3, column, "DUT")
|
||||||
ws.cell(3, column).value = "Rés."
|
ws.set_cell(3, column, "Rés.")
|
||||||
if self.codeAnnee == "BUT3":
|
if self.codeAnnee == "BUT3":
|
||||||
ws.cell(3, column).value = "BUT"
|
ws.set_cell(3, column, "BUT")
|
||||||
ws.cell(3, column).value = "Rés."
|
ws.set_cell(3, column, "Rés.")
|
||||||
# ws.merge_cells(start_column=start, end_column=column, start_row=1, end_row=1)
|
# ws.merge_cells(start_column=start, end_column=column, start_row=1, end_row=1)
|
||||||
return column
|
return column
|
||||||
|
|
||||||
@ -211,18 +166,15 @@ class ParcoursDesc:
|
|||||||
signature_header = FMT.compose(
|
signature_header = FMT.compose(
|
||||||
[
|
[
|
||||||
(FMT.FILL_BGCOLOR, SCO_COLORS.LIGHT_YELLOW.value),
|
(FMT.FILL_BGCOLOR, SCO_COLORS.LIGHT_YELLOW.value),
|
||||||
(FMT.FONT_BOLD, True),
|
(FMT.NUMBER_FORMAT, SCO_NUMBER_FORMAT.NUMBER_GENERAL.value),
|
||||||
(FMT.FONT_SIZE, SCO_FONTSIZE.FONTSIZE_13.value),
|
# (FMT.FONT_BOLD, True),
|
||||||
(FMT.ALIGNMENT_VALIGN, SCO_VALIGN.VALIGN_CENTER.value),
|
# (FMT.FONT_SIZE, SCO_FONTSIZE.FONTSIZE_13.value),
|
||||||
(FMT.ALIGNMENT_HALIGN, SCO_HALIGN.HALIGN_CENTER.value),
|
# (FMT.ALIGNMENT_VALIGN, SCO_VALIGN.VALIGN_CENTER.value),
|
||||||
(FMT.BORDER_LEFT_STYLE, SCO_BORDERTHICKNESS.BORDER_THIN.value),
|
# (FMT.ALIGNMENT_HALIGN, SCO_HALIGN.HALIGN_CENTER.value),
|
||||||
(FMT.BORDER_RIGHT_STYLE, SCO_BORDERTHICKNESS.BORDER_THIN.value),
|
# (FMT.BORDER_RIGHT, HAIR_BLACK),
|
||||||
(FMT.BORDER_TOP_STYLE, SCO_BORDERTHICKNESS.BORDER_THIN.value),
|
# (FMT.BORDER_LEFT, HAIR_BLACK),
|
||||||
(FMT.BORDER_BOTTOM_STYLE, SCO_BORDERTHICKNESS.BORDER_THIN.value),
|
# (FMT.BORDER_TOP, HAIR_BLACK),
|
||||||
(FMT.BORDER_LEFT_COLOR, SCO_COLORS.BLACK.value),
|
# (FMT.BORDER_BOTTOM, HAIR_BLACK),
|
||||||
(FMT.BORDER_RIGHT_COLOR, SCO_COLORS.BLACK.value),
|
|
||||||
(FMT.BORDER_TOP_COLOR, SCO_COLORS.BLACK.value),
|
|
||||||
(FMT.BORDER_RIGHT_COLOR, SCO_COLORS.BLACK.value),
|
|
||||||
],
|
],
|
||||||
base_signature,
|
base_signature,
|
||||||
)
|
)
|
||||||
@ -271,54 +223,27 @@ class ParcoursDesc:
|
|||||||
cells4.append(worksheet.make_cell(val4))
|
cells4.append(worksheet.make_cell(val4))
|
||||||
|
|
||||||
def handle_description(
|
def handle_description(
|
||||||
self, ws: Worksheet, description: tuple, row: int, column: int
|
self, ws: ScoExcelSheet, description: tuple, row: int, column: int
|
||||||
) -> int:
|
) -> int:
|
||||||
title, content_list = description
|
title, content_list = description
|
||||||
style = FMT.style(self.signature_header)
|
ws.set_cell(
|
||||||
ws.cell(row, column).value = title
|
row=row,
|
||||||
style.apply(ws.cell(row, column))
|
column=column,
|
||||||
merge_h = Merge_Engine(ws=ws, start_row=row, start_column=column)
|
text=title,
|
||||||
merge_v = Merge_Engine(ws=ws, start_row=row, start_column=column)
|
from_signature=self.signature_header,
|
||||||
|
)
|
||||||
|
merge_h = ws.get_merge_engine(start_row=row, start_column=column)
|
||||||
|
merge_v = ws.get_merge_engine(start_row=row, start_column=column)
|
||||||
if content_list is None:
|
if content_list is None:
|
||||||
merge_v.close(end_row=4)
|
merge_v.close(end_row=4)
|
||||||
column += 1
|
column += 1
|
||||||
else:
|
else:
|
||||||
first = column
|
|
||||||
for content in content_list:
|
for content in content_list:
|
||||||
column = self.handle_description(ws, content, row + 1, column)
|
column = self.handle_description(ws, content, row + 1, column)
|
||||||
merge_h.close(end_column=column - 1)
|
merge_h.close(end_column=column - 1)
|
||||||
# left_medium = FMT.compose(
|
|
||||||
# self.signature_header,
|
|
||||||
# [
|
|
||||||
# (FMT.BORDER_LEFT_STYLE, SCO_BORDERTHICKNESS.BORDER_MEDIUM.value),
|
|
||||||
# (FMT.BORDER_LEFT_COLOR, SCO_COLORS.BLACK.value),
|
|
||||||
# ],
|
|
||||||
# )
|
|
||||||
# right_medium = FMT.compose(
|
|
||||||
# self.signature_header,
|
|
||||||
# [
|
|
||||||
# (FMT.BORDER_RIGHT_STYLE, SCO_BORDERTHICKNESS.BORDER_MEDIUM.value),
|
|
||||||
# (FMT.BORDER_RIGHT_COLOR, SCO_COLORS.BLACK.value),
|
|
||||||
# ],
|
|
||||||
# )
|
|
||||||
# top_medium = FMT.compose(
|
|
||||||
# self.signature_header,
|
|
||||||
# [
|
|
||||||
# (FMT.BORDER_TOP_STYLE, SCO_BORDERTHICKNESS.BORDER_MEDIUM.value),
|
|
||||||
# (FMT.BORDER_TOP_COLOR, SCO_COLORS.BLACK.value),
|
|
||||||
# ],
|
|
||||||
# )
|
|
||||||
# FMT.get_style(FMT.ALL, left_medium).apply(ws.cell(1, 1))
|
|
||||||
# FMT.get_style(FMT.ALL, top_medium).apply(ws.cell(1, 1))
|
|
||||||
# FMT.get_style(FMT.ALL, right_medium).apply(ws.cell(1, 1))
|
|
||||||
# FMT.get_style(FMT.ALL, left_medium).apply(ws.cell(2, 1))
|
|
||||||
# FMT.get_style(FMT.ALL, right_medium).apply(ws.cell(2, column - 1))
|
|
||||||
# FMT.get_style(FMT.ALL, right_medium).apply(ws.cell(3, column - 1))
|
|
||||||
# FMT.get_style(FMT.ALL, right_medium).apply(ws.cell(4, column - 1))
|
|
||||||
# merge_h.close(end_column=column)
|
|
||||||
return column
|
return column
|
||||||
|
|
||||||
def generate_etudiant_header(self, ws: Worksheet) -> int:
|
def generate_etudiant_header(self, ws: ScoExcelSheet) -> int:
|
||||||
titles = (
|
titles = (
|
||||||
"ETUDIANT",
|
"ETUDIANT",
|
||||||
[
|
[
|
||||||
@ -338,19 +263,23 @@ class ParcoursDesc:
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
frame = ws.get_frame_engine(
|
||||||
|
1, 1, SCO_BORDERTHICKNESS.BORDER_THICK, SCO_COLORS.BLUE
|
||||||
|
)
|
||||||
column = self.handle_description(ws, titles, 1, 1)
|
column = self.handle_description(ws, titles, 1, 1)
|
||||||
|
frame.close(4, column - 1)
|
||||||
|
|
||||||
return column
|
return column
|
||||||
|
|
||||||
def generate_header(self, ws: Worksheet):
|
def generate_header(self, ws: ScoExcelSheet):
|
||||||
column: int = self.generate_etudiant_header(ws)
|
column: int = self.generate_etudiant_header(ws)
|
||||||
for codeAnnee in listeAnnees:
|
for codeAnnee in listeAnnees:
|
||||||
column = self.annees[codeAnnee].generate_header(ws, column)
|
column = self.annees[codeAnnee].generate_header(ws, column)
|
||||||
|
|
||||||
def generate(self, workbook: ScoExcelBook):
|
def generate(self, workbook: ScoExcelBook):
|
||||||
header = _Header()
|
|
||||||
if self.fromScodoc:
|
if self.fromScodoc:
|
||||||
sheet_name = self.fromScodoc.code
|
sheet_name = self.fromScodoc.code
|
||||||
else:
|
else:
|
||||||
sheet_name = "TC"
|
sheet_name = "TC"
|
||||||
worksheet: ScoExcelSheet = workbook.create_sheet(sheet_name)
|
worksheet: ScoExcelSheet = workbook.create_sheet(sheet_name)
|
||||||
self.generate_header(worksheet.ws)
|
self.generate_header(worksheet)
|
||||||
|
@ -27,10 +27,23 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
from openpyxl.cell import WriteOnlyCell
|
from openpyxl.cell import WriteOnlyCell
|
||||||
from openpyxl.worksheet.worksheet import Worksheet
|
from openpyxl.worksheet.worksheet import Worksheet
|
||||||
|
|
||||||
from app.but.prepajury_xl_format import Sco_Style
|
from app.but.prepajury_xl_format import (
|
||||||
|
Sco_Style,
|
||||||
|
FMT,
|
||||||
|
SCO_FONTNAME,
|
||||||
|
SCO_FONTSIZE,
|
||||||
|
SCO_HALIGN,
|
||||||
|
SCO_VALIGN,
|
||||||
|
SCO_NUMBER_FORMAT,
|
||||||
|
SCO_BORDERTHICKNESS,
|
||||||
|
SCO_COLORS,
|
||||||
|
fmt_atomics,
|
||||||
|
)
|
||||||
|
|
||||||
""" Excel file handling
|
""" Excel file handling
|
||||||
"""
|
"""
|
||||||
@ -51,6 +64,93 @@ from app.scodoc.sco_exceptions import ScoValueError
|
|||||||
# font, border, number_format, fill,...
|
# font, border, number_format, fill,...
|
||||||
# (cf https://openpyxl.readthedocs.io/en/stable/styles.html#working-with-styles)
|
# (cf https://openpyxl.readthedocs.io/en/stable/styles.html#working-with-styles)
|
||||||
|
|
||||||
|
base_signature = (
|
||||||
|
FMT.FONT_NAME.set(SCO_FONTNAME.FONTNAME_CALIBRI)
|
||||||
|
+ FMT.FONT_SIZE.set(SCO_FONTSIZE.FONTSIZE_13)
|
||||||
|
+ FMT.ALIGNMENT_HALIGN.set(SCO_HALIGN.HALIGN_CENTER)
|
||||||
|
+ FMT.ALIGNMENT_VALIGN.set(SCO_VALIGN.VALIGN_CENTER)
|
||||||
|
+ FMT.NUMBER_FORMAT.set(SCO_NUMBER_FORMAT.NUMBER_GENERAL)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Sco_Cell:
|
||||||
|
def __init__(self, text: str = "", signature: int = 0):
|
||||||
|
self.text = text
|
||||||
|
self.signature = signature
|
||||||
|
|
||||||
|
def alter(self, signature: int):
|
||||||
|
for fmt in fmt_atomics:
|
||||||
|
value: int = fmt.composante.read(signature)
|
||||||
|
if value > 0:
|
||||||
|
self.signature = fmt.write(value, self.signature)
|
||||||
|
|
||||||
|
def build(self, ws: Worksheet, row: int, column: int):
|
||||||
|
cell = ws.cell(row, column)
|
||||||
|
cell.value = self.text
|
||||||
|
FMT.ALL.apply(cell=cell, signature=self.signature)
|
||||||
|
|
||||||
|
|
||||||
|
class Frame_Engine:
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
ws: ScoExcelSheet,
|
||||||
|
start_row: int = 1,
|
||||||
|
start_column: int = 1,
|
||||||
|
thickness: SCO_BORDERTHICKNESS = SCO_BORDERTHICKNESS.NONE,
|
||||||
|
color: SCO_COLORS = SCO_COLORS.BLACK,
|
||||||
|
):
|
||||||
|
self.start_row: int = start_row
|
||||||
|
self.start_column: int = start_column
|
||||||
|
self.ws: ScoExcelSheet = ws
|
||||||
|
self.border_style = FMT.BORDER_LEFT.make_zero_based_constant([thickness, color])
|
||||||
|
|
||||||
|
def close(self, end_row: int, end_column: int):
|
||||||
|
left_signature: int = FMT.BORDER_LEFT.write(self.border_style)
|
||||||
|
right_signature: int = FMT.BORDER_RIGHT.write(self.border_style)
|
||||||
|
top_signature: int = FMT.BORDER_TOP.write(self.border_style)
|
||||||
|
bottom_signature: int = FMT.BORDER_BOTTOM.write(self.border_style)
|
||||||
|
for row in range(self.start_row, end_row + 1):
|
||||||
|
self.ws.cells[row][self.start_column].alter(left_signature)
|
||||||
|
self.ws.cells[row][end_column].alter(right_signature)
|
||||||
|
for column in range(self.start_column, end_column + 1):
|
||||||
|
self.ws.cells[self.start_row][column].alter(top_signature)
|
||||||
|
self.ws.cells[end_row][column].alter(bottom_signature)
|
||||||
|
|
||||||
|
|
||||||
|
class Merge_Engine:
|
||||||
|
def __init__(self, start_row: int = 1, start_column: int = 1):
|
||||||
|
self.start_row: int = start_row
|
||||||
|
self.start_column: int = start_column
|
||||||
|
self.end_row: int = None
|
||||||
|
self.end_column: int = None
|
||||||
|
self.closed: bool = False
|
||||||
|
|
||||||
|
def close(self, end_row=None, end_column=None):
|
||||||
|
if end_row is None:
|
||||||
|
self.end_row = self.start_row + 1
|
||||||
|
else:
|
||||||
|
self.end_row = end_row + 1
|
||||||
|
if end_column is None:
|
||||||
|
self.end_column = self.start_column + 1
|
||||||
|
else:
|
||||||
|
self.end_column = end_column + 1
|
||||||
|
self.closed = True
|
||||||
|
|
||||||
|
def write(self, ws: Worksheet):
|
||||||
|
if self.closed:
|
||||||
|
if (self.end_row - self.start_row > 0) and (
|
||||||
|
self.end_column - self.start_column > 0
|
||||||
|
):
|
||||||
|
ws.merge_cells(
|
||||||
|
start_row=self.start_row,
|
||||||
|
start_column=self.start_column,
|
||||||
|
end_row=self.end_row - 1,
|
||||||
|
end_column=self.end_column - 1,
|
||||||
|
)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"( {self.start_row}:{self.start_column}-{self.end_row}:{self.end_column})[{self.closed}]"
|
||||||
|
|
||||||
|
|
||||||
def xldate_as_datetime(xldate, datemode=0):
|
def xldate_as_datetime(xldate, datemode=0):
|
||||||
"""Conversion d'une date Excel en datetime python
|
"""Conversion d'une date Excel en datetime python
|
||||||
@ -90,14 +190,14 @@ class ScoExcelBook:
|
|||||||
self.sheets = [] # list of sheets
|
self.sheets = [] # list of sheets
|
||||||
self.wb = Workbook()
|
self.wb = Workbook()
|
||||||
|
|
||||||
def create_sheet(self, sheet_name="feuille", default_style=None):
|
def create_sheet(self, sheet_name="feuille", default_signature: int = 0):
|
||||||
"""Crée une nouvelle feuille dans ce classeur
|
"""Crée une nouvelle feuille dans ce classeur
|
||||||
sheet_name -- le nom de la feuille
|
sheet_name -- le nom de la feuille
|
||||||
default_style -- le style par défaut
|
default_style -- le style par défaut
|
||||||
"""
|
"""
|
||||||
sheet_name = adjust_sheetname(sheet_name)
|
sheet_name = adjust_sheetname(sheet_name)
|
||||||
ws = self.wb.create_sheet(sheet_name)
|
ws = self.wb.create_sheet(sheet_name)
|
||||||
sheet = ScoExcelSheet(sheet_name, default_style, ws)
|
sheet = ScoExcelSheet(sheet_name, default_signature=default_signature, ws=ws)
|
||||||
self.sheets.append(sheet)
|
self.sheets.append(sheet)
|
||||||
return sheet
|
return sheet
|
||||||
|
|
||||||
@ -128,7 +228,12 @@ class ScoExcelSheet:
|
|||||||
* pour finir appel de la méthode de génération
|
* pour finir appel de la méthode de génération
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, sheet_name="feuille", default_style=None, wb: Workbook = None):
|
def __init__(
|
||||||
|
self,
|
||||||
|
sheet_name: str = "feuille",
|
||||||
|
default_signature: int = 0,
|
||||||
|
ws: Worksheet = None,
|
||||||
|
):
|
||||||
"""Création de la feuille. sheet_name
|
"""Création de la feuille. sheet_name
|
||||||
-- le nom de la feuille default_style
|
-- le nom de la feuille default_style
|
||||||
-- le style par défaut des cellules ws
|
-- le style par défaut des cellules ws
|
||||||
@ -138,19 +243,42 @@ class ScoExcelSheet:
|
|||||||
# Le nom de la feuille ne peut faire plus de 31 caractères.
|
# 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' ?)
|
# si la taille du nom de feuille est > 31 on tronque (on pourrait remplacer par 'feuille' ?)
|
||||||
self.sheet_name = adjust_sheetname(sheet_name)
|
self.sheet_name = adjust_sheetname(sheet_name)
|
||||||
self.default_style = default_style or Sco_Style()
|
self.default_signature = default_signature
|
||||||
if wb is None:
|
self.merges: list[Merge_Engine] = []
|
||||||
|
if ws is None:
|
||||||
self.wb = Workbook()
|
self.wb = Workbook()
|
||||||
self.ws = self.wb.active
|
self.ws = self.wb.active
|
||||||
self.ws.title = self.sheet_name
|
self.ws.title = self.sheet_name
|
||||||
else:
|
else:
|
||||||
self.wb = None
|
self.wb = None
|
||||||
self.ws = wb
|
self.ws = ws
|
||||||
# internal data
|
# internal data
|
||||||
self.rows = [] # list of list of cells
|
self.cells = defaultdict(lambda: defaultdict(Sco_Cell))
|
||||||
self.column_dimensions = {}
|
self.column_dimensions = {}
|
||||||
self.row_dimensions = {}
|
self.row_dimensions = {}
|
||||||
|
|
||||||
|
def get_frame_engine(
|
||||||
|
self,
|
||||||
|
start_row: int,
|
||||||
|
start_column: int,
|
||||||
|
thickness: SCO_BORDERTHICKNESS = SCO_BORDERTHICKNESS.NONE,
|
||||||
|
color: SCO_COLORS = SCO_COLORS.NONE,
|
||||||
|
):
|
||||||
|
return Frame_Engine(
|
||||||
|
ws=self,
|
||||||
|
start_row=start_row,
|
||||||
|
start_column=start_column,
|
||||||
|
thickness=thickness,
|
||||||
|
color=color,
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_merge_engine(self, start_row: int, start_column: int):
|
||||||
|
merge_engine: Merge_Engine = Merge_Engine(
|
||||||
|
start_row=start_row, start_column=start_column
|
||||||
|
)
|
||||||
|
self.merges.append(merge_engine)
|
||||||
|
return merge_engine
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def i2col(idx):
|
def i2col(idx):
|
||||||
if idx < 26: # one letter key
|
if idx < 26: # one letter key
|
||||||
@ -160,6 +288,18 @@ class ScoExcelSheet:
|
|||||||
second = (idx % 26) + 65
|
second = (idx % 26) + 65
|
||||||
return "" + chr(first) + chr(second)
|
return "" + chr(first) + chr(second)
|
||||||
|
|
||||||
|
def set_cell(
|
||||||
|
self,
|
||||||
|
row: int,
|
||||||
|
column: int,
|
||||||
|
text: str = "",
|
||||||
|
from_signature: int = 0,
|
||||||
|
composition: list = [],
|
||||||
|
):
|
||||||
|
cell: Sco_Cell = self.cells[row][column]
|
||||||
|
cell.text = text
|
||||||
|
self.signature = FMT.compose(composition, from_signature)
|
||||||
|
|
||||||
def set_column_dimension_width(self, cle=None, value=21):
|
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,
|
"""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
|
value donne la liste des largeurs de colonnes depuis A, B, C, ... value -- la dimension (unité : 7 pixels
|
||||||
@ -192,83 +332,62 @@ class ScoExcelSheet:
|
|||||||
"""
|
"""
|
||||||
self.ws.row_dimensions[cle].hidden = value
|
self.ws.row_dimensions[cle].hidden = value
|
||||||
|
|
||||||
def make_cell(self, value: any = None, style: Sco_Style = None, comment=None):
|
# def make_cell(self, value: any = None, style: Sco_Style = None, comment=None):
|
||||||
"""Construit une cellule.
|
# """Construit une cellule.
|
||||||
value -- contenu de la cellule (texte, numérique, booléen ou date)
|
# value -- contenu de la cellule (texte, numérique, booléen ou date)
|
||||||
style -- style par défaut (dictionnaire cf. excel_make_style) de la feuille si non spécifié
|
# style -- style par défaut (dictionnaire cf. excel_make_style) de la feuille si non spécifié
|
||||||
"""
|
# """
|
||||||
# adaptation des valeurs si nécessaire
|
# # adaptation des valeurs si nécessaire
|
||||||
if value is None:
|
# if value is None:
|
||||||
value = ""
|
# value = ""
|
||||||
elif value is True:
|
# elif value is True:
|
||||||
value = 1
|
# value = 1
|
||||||
elif value is False:
|
# elif value is False:
|
||||||
value = 0
|
# value = 0
|
||||||
elif isinstance(value, datetime.datetime):
|
# elif isinstance(value, datetime.datetime):
|
||||||
value = value.replace(
|
# value = value.replace(
|
||||||
tzinfo=None
|
# tzinfo=None
|
||||||
) # make date naive (cf https://openpyxl.readthedocs.io/en/latest/datetime.html#timezones)
|
# ) # make date naive (cf https://openpyxl.readthedocs.io/en/latest/datetime.html#timezones)
|
||||||
|
#
|
||||||
# création de la cellule
|
# # création de la cellule
|
||||||
cell = WriteOnlyCell(self.ws, value)
|
# cell = WriteOnlyCell(self.ws, value)
|
||||||
|
#
|
||||||
if style is not None:
|
# if style is not None:
|
||||||
style.apply(cell)
|
# style.apply(cell)
|
||||||
|
#
|
||||||
if not comment is None:
|
# if not comment is None:
|
||||||
cell.comment = Comment(comment, "scodoc")
|
# cell.comment = Comment(comment, "scodoc")
|
||||||
lines = comment.splitlines()
|
# lines = comment.splitlines()
|
||||||
cell.comment.width = 7 * max([len(line) for line in lines]) if lines else 7
|
# cell.comment.width = 7 * max([len(line) for line in lines]) if lines else 7
|
||||||
cell.comment.height = 20 * len(lines) if lines else 20
|
# cell.comment.height = 20 * len(lines) if lines else 20
|
||||||
|
#
|
||||||
# test datatype to overwrite datetime format
|
# # test datatype to overwrite datetime format
|
||||||
if isinstance(value, datetime.date):
|
# if isinstance(value, datetime.date):
|
||||||
cell.data_type = "d"
|
# cell.data_type = "d"
|
||||||
cell.number_format = FORMAT_DATE_DDMMYY
|
# cell.number_format = FORMAT_DATE_DDMMYY
|
||||||
elif isinstance(value, int) or isinstance(value, float):
|
# elif isinstance(value, int) or isinstance(value, float):
|
||||||
cell.data_type = "n"
|
# cell.data_type = "n"
|
||||||
else:
|
# else:
|
||||||
cell.data_type = "s"
|
# cell.data_type = "s"
|
||||||
|
#
|
||||||
return cell
|
# return cell
|
||||||
|
|
||||||
def make_row(self, values: list, style=None, comments=None) -> list:
|
|
||||||
"build a row"
|
|
||||||
# TODO make possible differents styles in a row
|
|
||||||
if comments is None:
|
|
||||||
comments = [None] * len(values)
|
|
||||||
return [
|
|
||||||
self.make_cell(value, style, comment)
|
|
||||||
for value, comment in zip(values, comments)
|
|
||||||
]
|
|
||||||
|
|
||||||
def append_single_cell_row(self, value: any, style=None):
|
|
||||||
"""construit une ligne composée d'une seule cellule et l'ajoute à la feuille.
|
|
||||||
mêmes paramètres que make_cell:
|
|
||||||
value -- contenu de la cellule (texte ou numérique)
|
|
||||||
style -- style par défaut de la feuille si non spécifié
|
|
||||||
"""
|
|
||||||
self.append_row([self.make_cell(value, style)])
|
|
||||||
|
|
||||||
def append_blank_row(self):
|
|
||||||
"""construit une ligne vide et l'ajoute à la feuille."""
|
|
||||||
self.append_row([None])
|
|
||||||
|
|
||||||
def append_row(self, row):
|
|
||||||
"""ajoute une ligne déjà construite à la feuille."""
|
|
||||||
self.rows.append(row)
|
|
||||||
|
|
||||||
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)
|
||||||
ou pour la génération d'un classeur multi-feuilles
|
ou pour la génération d'un classeur multi-feuilles
|
||||||
"""
|
"""
|
||||||
for row in self.column_dimensions.keys():
|
# for row in self.column_dimensions.keys():
|
||||||
self.ws.column_dimensions[row] = self.column_dimensions[row]
|
# self.ws.column_dimensions[row] = self.column_dimensions[row]
|
||||||
for row in self.row_dimensions.keys():
|
# for row in self.row_dimensions.keys():
|
||||||
self.ws.row_dimensions[row] = self.row_dimensions[row]
|
# self.ws.row_dimensions[row] = self.row_dimensions[row]
|
||||||
for row in self.rows:
|
# for row in self.rows:
|
||||||
self.ws.append(row)
|
# self.ws.append(row)
|
||||||
|
for row in self.cells:
|
||||||
|
for column in self.cells[row]:
|
||||||
|
self.cells[row][column].build(self.ws, row, column)
|
||||||
|
for merge_engine in self.merges:
|
||||||
|
merge_engine.write(self.ws)
|
||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
"""génération d'un classeur mono-feuille"""
|
"""génération d'un classeur mono-feuille"""
|
||||||
|
@ -2,6 +2,7 @@ import abc
|
|||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
import openpyxl.styles
|
import openpyxl.styles
|
||||||
|
from openpyxl.cell import Cell
|
||||||
from openpyxl.styles import Side, Border, Font, PatternFill, Alignment
|
from openpyxl.styles import Side, Border, Font, PatternFill, Alignment
|
||||||
from openpyxl.styles.numbers import FORMAT_GENERAL, FORMAT_NUMBER_00
|
from openpyxl.styles.numbers import FORMAT_GENERAL, FORMAT_NUMBER_00
|
||||||
|
|
||||||
@ -42,7 +43,7 @@ class SCO_BORDERTHICKNESS(Enum):
|
|||||||
obj.width = width
|
obj.width = width
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
BORDER_NONE = (0, None)
|
NONE = (0, None)
|
||||||
BORDER_HAIR = (1, "hair")
|
BORDER_HAIR = (1, "hair")
|
||||||
BORDER_THIN = (2, "thin")
|
BORDER_THIN = (2, "thin")
|
||||||
BORDER_MEDIUM = (3, "medium")
|
BORDER_MEDIUM = (3, "medium")
|
||||||
@ -56,10 +57,11 @@ class SCO_FONTNAME(Enum):
|
|||||||
obj.fontname = fontname
|
obj.fontname = fontname
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
FONTNAME_CALIBRI = (0, "Calibri")
|
NONE = (0, None)
|
||||||
FONTNAME_ARIAL = (1, "Arial")
|
FONTNAME_CALIBRI = (1, "Calibri")
|
||||||
FONTNAME_COURIER = (2, "Courier New")
|
FONTNAME_ARIAL = (2, "Arial")
|
||||||
FONTNAME_TIMES = (3, "Times New Roman")
|
FONTNAME_COURIER = (3, "Courier New")
|
||||||
|
FONTNAME_TIMES = (4, "Times New Roman")
|
||||||
|
|
||||||
|
|
||||||
class SCO_FONTSIZE(Enum):
|
class SCO_FONTSIZE(Enum):
|
||||||
@ -69,11 +71,11 @@ class SCO_FONTSIZE(Enum):
|
|||||||
obj.fontsize = fontsize
|
obj.fontsize = fontsize
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
FONTSIZE_10 = (0, 10.0)
|
NONE = (0, None)
|
||||||
FONTSIZE_9 = (1, 9.0)
|
FONTSIZE_9 = (1, 9.0)
|
||||||
|
FONTSIZE_10 = (2, 10.0)
|
||||||
FONTSIZE_11 = (2, 11.0)
|
FONTSIZE_11 = (2, 11.0)
|
||||||
FONTSIZE_13 = (3, 13.0)
|
FONTSIZE_13 = (4, 13.0)
|
||||||
FONTSIZE_16 = (4, 16.0)
|
|
||||||
|
|
||||||
|
|
||||||
class SCO_NUMBER_FORMAT(Enum):
|
class SCO_NUMBER_FORMAT(Enum):
|
||||||
@ -83,6 +85,7 @@ class SCO_NUMBER_FORMAT(Enum):
|
|||||||
obj.format = format
|
obj.format = format
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
NONE = (0, None)
|
||||||
NUMBER_GENERAL = (0, FORMAT_GENERAL)
|
NUMBER_GENERAL = (0, FORMAT_GENERAL)
|
||||||
NUMBER_00 = (1, FORMAT_NUMBER_00)
|
NUMBER_00 = (1, FORMAT_NUMBER_00)
|
||||||
|
|
||||||
@ -94,9 +97,10 @@ class SCO_HALIGN(Enum):
|
|||||||
obj.position = position
|
obj.position = position
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
HALIGN_LEFT = (0, "left")
|
NONE = (0, None)
|
||||||
HALIGN_CENTER = (1, "center")
|
HALIGN_LEFT = (1, "left")
|
||||||
HALIGN_RIGHT = (2, "right")
|
HALIGN_CENTER = (2, "center")
|
||||||
|
HALIGN_RIGHT = (3, "right")
|
||||||
|
|
||||||
|
|
||||||
class SCO_VALIGN(Enum):
|
class SCO_VALIGN(Enum):
|
||||||
@ -151,7 +155,7 @@ class Composante_boolean(Composante):
|
|||||||
def set(self, data: bool, signature=0) -> int:
|
def set(self, data: bool, signature=0) -> int:
|
||||||
return self.write(1 if data else 0, signature)
|
return self.write(1 if data else 0, signature)
|
||||||
|
|
||||||
def build(self, signature):
|
def build(self, signature) -> bool:
|
||||||
value = self.read(signature)
|
value = self.read(signature)
|
||||||
assert value < (1 << self.width)
|
assert value < (1 << self.width)
|
||||||
return value == 1
|
return value == 1
|
||||||
@ -167,7 +171,7 @@ class Composante_number_format(Composante):
|
|||||||
def set(self, data: SCO_NUMBER_FORMAT, signature=0) -> int:
|
def set(self, data: SCO_NUMBER_FORMAT, signature=0) -> int:
|
||||||
return self.write(data.value, signature)
|
return self.write(data.value, signature)
|
||||||
|
|
||||||
def build(self, signature: int):
|
def build(self, signature: int) -> SCO_NUMBER_FORMAT:
|
||||||
value = self.read(signature)
|
value = self.read(signature)
|
||||||
assert value < (1 << self.width)
|
assert value < (1 << self.width)
|
||||||
return SCO_NUMBER_FORMAT(value)
|
return SCO_NUMBER_FORMAT(value)
|
||||||
@ -184,7 +188,7 @@ class Composante_Colors(Composante):
|
|||||||
def set(self, data: SCO_COLORS, signature=0) -> int:
|
def set(self, data: SCO_COLORS, signature=0) -> int:
|
||||||
return self.write(data.value, signature)
|
return self.write(data.value, signature)
|
||||||
|
|
||||||
def build(self, signature: int):
|
def build(self, signature: int) -> SCO_COLORS:
|
||||||
value = self.read(signature)
|
value = self.read(signature)
|
||||||
assert value < (1 << self.width)
|
assert value < (1 << self.width)
|
||||||
if value == 0:
|
if value == 0:
|
||||||
@ -205,7 +209,7 @@ class Composante_borderThickness(Composante):
|
|||||||
def set(self, data: SCO_BORDERTHICKNESS, signature=0) -> int:
|
def set(self, data: SCO_BORDERTHICKNESS, signature=0) -> int:
|
||||||
return self.write(data.value, signature)
|
return self.write(data.value, signature)
|
||||||
|
|
||||||
def build(self, signature: int):
|
def build(self, signature: int) -> SCO_BORDERTHICKNESS:
|
||||||
value = self.read(signature)
|
value = self.read(signature)
|
||||||
assert value < (1 << self.width)
|
assert value < (1 << self.width)
|
||||||
try:
|
try:
|
||||||
@ -224,7 +228,7 @@ class Composante_fontname(Composante):
|
|||||||
def set(self, data: SCO_FONTNAME, signature=0) -> int:
|
def set(self, data: SCO_FONTNAME, signature=0) -> int:
|
||||||
return self.write(data.value, signature)
|
return self.write(data.value, signature)
|
||||||
|
|
||||||
def build(self, signature: int):
|
def build(self, signature: int) -> SCO_FONTNAME:
|
||||||
value = self.read(signature)
|
value = self.read(signature)
|
||||||
assert value < (1 << self.width)
|
assert value < (1 << self.width)
|
||||||
try:
|
try:
|
||||||
@ -243,14 +247,14 @@ class Composante_fontsize(Composante):
|
|||||||
def set(self, data: SCO_FONTSIZE, signature=0) -> int:
|
def set(self, data: SCO_FONTSIZE, signature=0) -> int:
|
||||||
return self.write(data.value, signature)
|
return self.write(data.value, signature)
|
||||||
|
|
||||||
def build(self, signature: int):
|
def build(self, signature: int) -> SCO_FONTSIZE:
|
||||||
value = self.read(signature)
|
value = self.read(signature)
|
||||||
assert value < (1 << self.width)
|
assert value < (1 << self.width)
|
||||||
return SCO_FONTSIZE(value) or None
|
return SCO_FONTSIZE(value) or None
|
||||||
|
|
||||||
|
|
||||||
class Composante_halign(Composante):
|
class Composante_halign(Composante):
|
||||||
WIDTH: int = 2
|
WIDTH: int = 3
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
assert (1 << self.WIDTH) > SCO_HALIGN.__len__()
|
assert (1 << self.WIDTH) > SCO_HALIGN.__len__()
|
||||||
@ -259,7 +263,7 @@ class Composante_halign(Composante):
|
|||||||
def set(self, data: SCO_HALIGN, signature=0) -> int:
|
def set(self, data: SCO_HALIGN, signature=0) -> int:
|
||||||
return self.write(data.value, signature)
|
return self.write(data.value, signature)
|
||||||
|
|
||||||
def build(self, signature: int):
|
def build(self, signature: int) -> SCO_HALIGN:
|
||||||
value = self.read(signature)
|
value = self.read(signature)
|
||||||
assert value < (1 << self.width)
|
assert value < (1 << self.width)
|
||||||
try:
|
try:
|
||||||
@ -269,7 +273,7 @@ class Composante_halign(Composante):
|
|||||||
|
|
||||||
|
|
||||||
class Composante_valign(Composante):
|
class Composante_valign(Composante):
|
||||||
WIDTH: int = 2
|
WIDTH: int = 3
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
assert (1 << self.WIDTH) > SCO_VALIGN.__len__()
|
assert (1 << self.WIDTH) > SCO_VALIGN.__len__()
|
||||||
@ -278,7 +282,7 @@ class Composante_valign(Composante):
|
|||||||
def set(self, data: SCO_VALIGN, signature=0) -> int:
|
def set(self, data: SCO_VALIGN, signature=0) -> int:
|
||||||
return self.write(data.value, signature)
|
return self.write(data.value, signature)
|
||||||
|
|
||||||
def build(self, signature: int):
|
def build(self, signature: int) -> SCO_VALIGN:
|
||||||
value = self.read(signature)
|
value = self.read(signature)
|
||||||
assert value < (1 << self.width)
|
assert value < (1 << self.width)
|
||||||
try:
|
try:
|
||||||
@ -312,7 +316,7 @@ class Sco_BorderSide:
|
|||||||
|
|
||||||
def to_openpyxl(self):
|
def to_openpyxl(self):
|
||||||
return Side(
|
return Side(
|
||||||
border_style=self.thickness.width,
|
border_style=None if self.thickness is None else self.thickness.width,
|
||||||
color=None if self.color is None else self.color.argb,
|
color=None if self.color is None else self.color.argb,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -350,8 +354,8 @@ class Sco_Alignment:
|
|||||||
|
|
||||||
def to_openpyxl(self):
|
def to_openpyxl(self):
|
||||||
return Alignment(
|
return Alignment(
|
||||||
horizontal=self.halign.position,
|
horizontal=None if self.halign is None else self.halign.position,
|
||||||
vertical=self.valign.position,
|
vertical=None if self.valign is None else self.valign.position,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -374,8 +378,8 @@ class Sco_Font:
|
|||||||
|
|
||||||
def to_openpyxl(self):
|
def to_openpyxl(self):
|
||||||
return Font(
|
return Font(
|
||||||
name=self.name.fontname,
|
name=None if self.name is None else self.name.fontname,
|
||||||
size=self.fontsize.fontsize,
|
size=None if self.fontsize is None else self.fontsize.fontsize,
|
||||||
bold=self.bold,
|
bold=self.bold,
|
||||||
italic=self.italic,
|
italic=self.italic,
|
||||||
outline=self.outline,
|
outline=self.outline,
|
||||||
@ -392,13 +396,13 @@ class Sco_Style:
|
|||||||
fill: Sco_Fill = None,
|
fill: Sco_Fill = None,
|
||||||
alignment: Sco_Alignment = None,
|
alignment: Sco_Alignment = None,
|
||||||
borders: Sco_Borders = None,
|
borders: Sco_Borders = None,
|
||||||
number_format: SCO_NUMBER_FORMAT = None,
|
number_format: SCO_NUMBER_FORMAT = FORMAT_GENERAL,
|
||||||
):
|
):
|
||||||
self.font = font
|
self.font = font or None
|
||||||
self.fill = fill
|
self.fill = fill or None
|
||||||
self.alignment = alignment
|
self.alignment = alignment or None
|
||||||
self.borders = borders
|
self.borders = borders or None
|
||||||
self.number_format = number_format
|
self.number_format = number_format or SCO_NUMBER_FORMAT.NUMBER_GENERAL
|
||||||
|
|
||||||
def apply(self, cell: Cell):
|
def apply(self, cell: Cell):
|
||||||
if self.font:
|
if self.font:
|
||||||
@ -409,8 +413,12 @@ class Sco_Style:
|
|||||||
cell.alignment = self.alignment.to_openpyxl()
|
cell.alignment = self.alignment.to_openpyxl()
|
||||||
if self.borders:
|
if self.borders:
|
||||||
cell.border = self.borders.to_openpyxl()
|
cell.border = self.borders.to_openpyxl()
|
||||||
if self.number_format:
|
cell.number_format = (
|
||||||
cell.number_format = self.number_format.format
|
FORMAT_GENERAL
|
||||||
|
if self.number_format is None
|
||||||
|
or self.number_format == SCO_NUMBER_FORMAT.NONE
|
||||||
|
else self.number_format.format
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Composantes groupant d'autres composantes et dotées d'un mécanisme de cache
|
# Composantes groupant d'autres composantes et dotées d'un mécanisme de cache
|
||||||
@ -448,7 +456,7 @@ class Composante_fill(Composante_group):
|
|||||||
super().__init__([color])
|
super().__init__([color])
|
||||||
self.color = color
|
self.color = color
|
||||||
|
|
||||||
def build(self, signature: int):
|
def build(self, signature: int) -> Sco_Fill:
|
||||||
return Sco_Fill(color=self.color.build(signature))
|
return Sco_Fill(color=self.color.build(signature))
|
||||||
|
|
||||||
|
|
||||||
@ -470,7 +478,7 @@ class Composante_font(Composante_group):
|
|||||||
self.italic = italic
|
self.italic = italic
|
||||||
self.outline = outline
|
self.outline = outline
|
||||||
|
|
||||||
def build(self, signature: int):
|
def build(self, signature: int) -> Sco_Font:
|
||||||
return Sco_Font(
|
return Sco_Font(
|
||||||
name=self.name.build(signature),
|
name=self.name.build(signature),
|
||||||
fontsize=self.fontsize.build(signature),
|
fontsize=self.fontsize.build(signature),
|
||||||
@ -487,7 +495,7 @@ class Composante_border(Composante_group):
|
|||||||
self.thick = thick
|
self.thick = thick
|
||||||
self.color = color
|
self.color = color
|
||||||
|
|
||||||
def build(self, signature: int):
|
def build(self, signature: int) -> Sco_BorderSide:
|
||||||
return Sco_BorderSide(
|
return Sco_BorderSide(
|
||||||
thickness=self.thick.build(signature),
|
thickness=self.thick.build(signature),
|
||||||
color=self.color.build(signature),
|
color=self.color.build(signature),
|
||||||
@ -508,7 +516,7 @@ class Composante_borders(Composante_group):
|
|||||||
self.top = top
|
self.top = top
|
||||||
self.bottom = bottom
|
self.bottom = bottom
|
||||||
|
|
||||||
def build(self, signature: int):
|
def build(self, signature: int) -> Sco_Borders:
|
||||||
return Sco_Borders(
|
return Sco_Borders(
|
||||||
left=self.left.lookup_or_cache(signature),
|
left=self.left.lookup_or_cache(signature),
|
||||||
right=self.right.lookup_or_cache(signature),
|
right=self.right.lookup_or_cache(signature),
|
||||||
@ -523,7 +531,7 @@ class Composante_alignment(Composante_group):
|
|||||||
self.halign = halign
|
self.halign = halign
|
||||||
self.valign = valign
|
self.valign = valign
|
||||||
|
|
||||||
def build(self, signature: int):
|
def build(self, signature: int) -> Sco_Alignment:
|
||||||
return Sco_Alignment(
|
return Sco_Alignment(
|
||||||
halign=self.halign.build(signature),
|
halign=self.halign.build(signature),
|
||||||
valign=self.valign.build(signature),
|
valign=self.valign.build(signature),
|
||||||
@ -547,7 +555,7 @@ class Composante_all(Composante_group):
|
|||||||
self.alignment = alignment
|
self.alignment = alignment
|
||||||
self.number_format = number_format
|
self.number_format = number_format
|
||||||
|
|
||||||
def build(self, signature: int):
|
def build(self, signature: int) -> Sco_Style:
|
||||||
return Sco_Style(
|
return Sco_Style(
|
||||||
fill=self.fill.lookup_or_cache(signature),
|
fill=self.fill.lookup_or_cache(signature),
|
||||||
font=self.font.lookup_or_cache(signature),
|
font=self.font.lookup_or_cache(signature),
|
||||||
@ -576,14 +584,17 @@ class FMT(Enum):
|
|||||||
def make_zero_based_constant(self, enums: list[Enum]) -> int:
|
def make_zero_based_constant(self, enums: list[Enum]) -> int:
|
||||||
return self.composante.make_zero_based_constant(enums=enums)
|
return self.composante.make_zero_based_constant(enums=enums)
|
||||||
|
|
||||||
|
def apply(self, cell: Cell, signature: int):
|
||||||
|
self.composante.build(signature).apply(cell)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def compose(cls, composition: list, signature: int = 0) -> int:
|
def compose(cls, composition: list[("FMT", int)], signature: int = 0) -> int:
|
||||||
for field, value in composition:
|
for field, value in composition:
|
||||||
signature = field.write(value, signature)
|
signature = field.write(value, signature)
|
||||||
return signature
|
return signature
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def style(cls, signature: int):
|
def style(cls, signature: int = None) -> Sco_Style:
|
||||||
return FMT.ALL.get_style(signature)
|
return FMT.ALL.get_style(signature)
|
||||||
|
|
||||||
FONT_NAME = Composante_fontname()
|
FONT_NAME = Composante_fontname()
|
||||||
@ -617,6 +628,27 @@ class FMT(Enum):
|
|||||||
ALL = Composante_all(FONT, FILL, BORDERS, ALIGNMENT, NUMBER_FORMAT)
|
ALL = Composante_all(FONT, FILL, BORDERS, ALIGNMENT, NUMBER_FORMAT)
|
||||||
|
|
||||||
|
|
||||||
|
fmt_atomics = {
|
||||||
|
FMT.FONT_NAME,
|
||||||
|
FMT.FONT_SIZE,
|
||||||
|
FMT.FONT_COLOR,
|
||||||
|
FMT.FONT_BOLD,
|
||||||
|
FMT.FONT_ITALIC,
|
||||||
|
FMT.FONT_OUTLINE,
|
||||||
|
FMT.BORDER_LEFT_STYLE,
|
||||||
|
FMT.BORDER_LEFT_COLOR,
|
||||||
|
FMT.BORDER_RIGHT_STYLE,
|
||||||
|
FMT.BORDER_RIGHT_COLOR,
|
||||||
|
FMT.BORDER_TOP_STYLE,
|
||||||
|
FMT.BORDER_TOP_COLOR,
|
||||||
|
FMT.BORDER_BOTTOM_STYLE,
|
||||||
|
FMT.BORDER_BOTTOM_COLOR,
|
||||||
|
FMT.FILL_BGCOLOR,
|
||||||
|
FMT.ALIGNMENT_HALIGN,
|
||||||
|
FMT.ALIGNMENT_VALIGN,
|
||||||
|
FMT.NUMBER_FORMAT,
|
||||||
|
}
|
||||||
|
|
||||||
HAIR_BLACK: int = FMT.BORDER_LEFT.make_zero_based_constant(
|
HAIR_BLACK: int = FMT.BORDER_LEFT.make_zero_based_constant(
|
||||||
enums=[SCO_BORDERTHICKNESS.BORDER_HAIR, SCO_COLORS.BLACK]
|
enums=[SCO_BORDERTHICKNESS.BORDER_HAIR, SCO_COLORS.BLACK]
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user