diff --git a/infrastructure/xlsx/branding.py b/infrastructure/xlsx/branding.py index b53195fad..b2a7f1622 100644 --- a/infrastructure/xlsx/branding.py +++ b/infrastructure/xlsx/branding.py @@ -11,6 +11,8 @@ palette once design supplies it. from __future__ import annotations +from openpyxl.styles import Alignment, Font, PatternFill +from openpyxl.utils import get_column_letter from openpyxl.worksheet.worksheet import Worksheet # openpyxl colours are 8-char ARGB. Placeholder Monday-style palette. @@ -24,4 +26,26 @@ _COLUMN_WIDTH: int = 18 def style_sheet(worksheet: Worksheet) -> None: """Paint the Monday-style branding onto a populated worksheet: header band + font, frozen header row, banded rows, and column widths.""" - raise NotImplementedError + header_fill = PatternFill( + start_color=HEADER_FILL, end_color=HEADER_FILL, fill_type="solid" + ) + header_font = Font(bold=True, color=HEADER_FONT) + for cell in worksheet[1]: + cell.fill = header_fill + cell.font = header_font + cell.alignment = Alignment(horizontal="left", vertical="center") + + # Keep the header visible while scrolling a long portfolio. + worksheet.freeze_panes = "A2" + + band_fill = PatternFill( + start_color=ROW_BAND_FILL, end_color=ROW_BAND_FILL, fill_type="solid" + ) + for row_index in range(3, worksheet.max_row + 1, 2): + for cell in worksheet[row_index]: + cell.fill = band_fill + + for column_index in range(1, worksheet.max_column + 1): + worksheet.column_dimensions[get_column_letter(column_index)].width = ( + _COLUMN_WIDTH + ) diff --git a/infrastructure/xlsx/scenario_export_workbook.py b/infrastructure/xlsx/scenario_export_workbook.py index 4f971d050..7dbc9bda8 100644 --- a/infrastructure/xlsx/scenario_export_workbook.py +++ b/infrastructure/xlsx/scenario_export_workbook.py @@ -15,6 +15,7 @@ from typing import Sequence from openpyxl import Workbook from domain.scenario_export.scenario_sheet import ExportSheet +from infrastructure.xlsx.branding import style_sheet # Excel forbids these in a sheet title and caps titles at 31 characters. _ILLEGAL_SHEET_CHARS = re.compile(r"[:\\/?*\[\]]") @@ -50,6 +51,7 @@ def render_workbook(sheets: Sequence[tuple[str, ExportSheet]]) -> bytes: worksheet.append(list(sheet.columns)) for row in sheet.rows: worksheet.append([row.get(column, "") for column in sheet.columns]) + style_sheet(worksheet) buffer = BytesIO() workbook.save(buffer)