70 lines
2.3 KiB
Python
70 lines
2.3 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
from typing import Iterable
|
|
|
|
from openpyxl import Workbook
|
|
from openpyxl.styles import Alignment, Font, PatternFill
|
|
from openpyxl.utils import get_column_letter
|
|
|
|
from .mapping import FIXED_REPORT_COLUMNS, build_fixed_row
|
|
|
|
|
|
@dataclass
|
|
class ReportRow:
|
|
file_name: str
|
|
record_id: str
|
|
operation_index: int
|
|
operation_fields: dict[str, str]
|
|
participant_fields: dict[str, str]
|
|
|
|
|
|
def write_report(rows: Iterable[ReportRow], destination: Path) -> None:
|
|
row_list = list(rows)
|
|
columns = list(FIXED_REPORT_COLUMNS)
|
|
workbook = Workbook()
|
|
sheet = workbook.active
|
|
sheet.title = "Отчет"
|
|
sheet.freeze_panes = "A2"
|
|
|
|
_write_header(sheet, columns)
|
|
for row_index, row in enumerate(row_list, start=2):
|
|
data = build_fixed_row(
|
|
file_name=row.file_name,
|
|
record_id=row.record_id,
|
|
operation_index=row.operation_index,
|
|
operation_fields=row.operation_fields,
|
|
participant_fields=row.participant_fields,
|
|
)
|
|
for col_index, column_name in enumerate(columns, start=1):
|
|
cell = sheet.cell(
|
|
row=row_index, column=col_index, value=data.get(column_name, "")
|
|
)
|
|
if "Дата" in column_name:
|
|
cell.number_format = "DD.MM.YYYY"
|
|
if "Сумм" in column_name or "Сумма" in column_name:
|
|
cell.number_format = "#,##0.00"
|
|
|
|
_auto_width(sheet, columns)
|
|
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
workbook.save(destination)
|
|
|
|
|
|
def _write_header(sheet, columns: list[str]) -> None:
|
|
fill = PatternFill(start_color="E2F0D9", end_color="E2F0D9", fill_type="solid")
|
|
for index, name in enumerate(columns, start=1):
|
|
cell = sheet.cell(row=1, column=index, value=name)
|
|
cell.font = Font(bold=True)
|
|
cell.alignment = Alignment(
|
|
horizontal="center", vertical="center", wrap_text=True
|
|
)
|
|
cell.fill = fill
|
|
|
|
|
|
def _auto_width(sheet, columns: list[str]) -> None:
|
|
for index, column_name in enumerate(columns, start=1):
|
|
width = max(12, min(60, len(column_name) + 4))
|
|
column_letter = get_column_letter(index)
|
|
sheet.column_dimensions[column_letter].width = width
|