Merge pull request 'indent-export: отсупы в экспорте по глубине вложенности' (#196) from indent-export into test
Reviewed-on: #196
This commit is contained in:
commit
18b834e1f8
@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import abc
|
||||
from copy import copy
|
||||
from collections import defaultdict
|
||||
from typing import Any, Callable
|
||||
|
||||
@ -255,6 +256,12 @@ class DepthSheetWriter(AbstractWriter):
|
||||
normalized = self.row_normalizer(raw_data)
|
||||
values = [self.value_serializer(normalized.get(key)) for key in self.columns]
|
||||
worksheet.append(values)
|
||||
for column, key in enumerate(self.columns, start=1):
|
||||
if key in ("name", "header.name"):
|
||||
cell = worksheet.cell(row=next_row, column=column)
|
||||
alignment = copy(cell.alignment)
|
||||
alignment.indent = outline_level
|
||||
cell.alignment = alignment
|
||||
self._track_row_widths(column_widths, values)
|
||||
if len(row) > 3:
|
||||
self._set_color_to_row(ws=worksheet, row=next_row, item_type=row[0])
|
||||
@ -492,13 +499,14 @@ class XlsxDepthSheetWriter(AbstractWriter):
|
||||
|
||||
return current_column
|
||||
|
||||
def _row_format(self, palette: str, item_type: str):
|
||||
cache_key = (palette, item_type)
|
||||
def _row_format(self, palette: str, item_type: str, indent: int = 0):
|
||||
cache_key = (palette, item_type, indent)
|
||||
if cache_key not in self._format_cache:
|
||||
self._format_cache[cache_key] = self.workbook.add_format(
|
||||
{
|
||||
"bg_color": f"#{PALETTE[palette][item_type]}",
|
||||
"pattern": 1,
|
||||
"indent": indent,
|
||||
}
|
||||
)
|
||||
return self._format_cache[cache_key]
|
||||
@ -531,6 +539,11 @@ class XlsxDepthSheetWriter(AbstractWriter):
|
||||
values = [self.value_serializer(normalized.get(key)) for key in self.columns]
|
||||
if column_formats is not None:
|
||||
worksheet.write_row(output_row, 0, values)
|
||||
for column, key in enumerate(self.columns):
|
||||
if key in ("name", "header.name") and outline_level:
|
||||
properties = dict(self.column_format_resolver(key, column) or {})
|
||||
properties["indent"] = outline_level
|
||||
worksheet.write(output_row, column, values[column], self._resolved_format(properties))
|
||||
if self.fixed_column_width is None:
|
||||
self._track_row_widths(column_widths, values)
|
||||
output_row += 1
|
||||
@ -540,12 +553,14 @@ class XlsxDepthSheetWriter(AbstractWriter):
|
||||
for column, value in enumerate(values):
|
||||
cell_format = None
|
||||
column_key = self.columns[column]
|
||||
indent = outline_level if column_key in ("name", "header.name") else 0
|
||||
resolved_format = (
|
||||
self.row_format_resolver(row, column_key, column)
|
||||
if self.row_format_resolver
|
||||
else None
|
||||
)
|
||||
if resolved_format:
|
||||
resolved_format = {**resolved_format, "indent": indent}
|
||||
cell_format = self._resolved_format(resolved_format)
|
||||
palette = self.palette.get(column_key)
|
||||
if (
|
||||
@ -553,7 +568,9 @@ class XlsxDepthSheetWriter(AbstractWriter):
|
||||
and palette
|
||||
and item_type not in (None, "SUB_ITEM", "INPUT")
|
||||
):
|
||||
cell_format = self._row_format(palette, item_type)
|
||||
cell_format = self._row_format(palette, item_type, indent)
|
||||
if cell_format is None and indent:
|
||||
cell_format = self._resolved_format({"indent": indent})
|
||||
worksheet.write(output_row, column, value, cell_format)
|
||||
if self.fixed_column_width is None:
|
||||
self._track_row_widths(column_widths, values)
|
||||
|
||||
@ -17,20 +17,27 @@ from src.services.export_service.export_writers import (
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("backend", ["openpyxl", "xlsxwriter", "xlsxwriter_columns"])
|
||||
def test_depth_writer_preserves_collapsible_row_hierarchy(backend):
|
||||
@pytest.mark.parametrize("backend", ["openpyxl", "xlsxwriter", "xlsxwriter_columns", "xlsxwriter_rows", "xlsxwriter_palette"])
|
||||
@pytest.mark.parametrize("name_key", ["name", "header.name"])
|
||||
def test_depth_writer_preserves_collapsible_row_hierarchy(backend, name_key):
|
||||
stream = BytesIO()
|
||||
workbook = Workbook() if backend == "openpyxl" else XlsxWorkbook(stream)
|
||||
worksheet = workbook.active if backend == "openpyxl" else workbook.add_worksheet()
|
||||
options = {}
|
||||
if backend == "xlsxwriter_columns":
|
||||
options["column_format_resolver"] = lambda key, column: {"bold": True}
|
||||
if backend == "xlsxwriter_rows":
|
||||
options["row_format_resolver"] = lambda row, key, column: {"bold": True}
|
||||
if backend == "xlsxwriter_palette":
|
||||
options["colors_config"] = {"header": {"palette": "green"}}
|
||||
writer_class = DepthSheetWriter if backend == "openpyxl" else XlsxDepthSheetWriter
|
||||
if backend != "openpyxl":
|
||||
options["workbook"] = workbook
|
||||
writer = writer_class(
|
||||
columns_dict={"header": {"name": "Header", "key": "", "children": {
|
||||
"name": {"name": "Name"},
|
||||
"name": {"name": "Name", "key": name_key},
|
||||
"code": {"name": "Code"},
|
||||
"contract.name": {"name": "Contract name"},
|
||||
}}},
|
||||
row_normalizer=lambda row: row,
|
||||
value_serializer=lambda value: value,
|
||||
@ -38,7 +45,7 @@ def test_depth_writer_preserves_collapsible_row_hierarchy(backend):
|
||||
)
|
||||
# Missing GROUP/SUB_ITEM levels and misleading numeric depths match frontend cases.
|
||||
types = ["ROOT", "ITEM", "INPUT", "META", "INPUT", "ITEM", "SUB_ITEM", "INPUT", "ROOT"]
|
||||
writer.write(worksheet, [(kind, 42, index, {"name": str(index)}) for index, kind in enumerate(types)])
|
||||
writer.write(worksheet, [(kind, 42, index, {name_key: str(index), "code": index, "contract.name": "Contract"}) for index, kind in enumerate(types)])
|
||||
if backend == "openpyxl":
|
||||
workbook.save(stream)
|
||||
else:
|
||||
@ -49,6 +56,12 @@ def test_depth_writer_preserves_collapsible_row_hierarchy(backend):
|
||||
assert [sheet.row_dimensions[index].outlineLevel for index in range(3, 11)] == [0, 1, 2, 2, 1, 2, 3, 0]
|
||||
assert [sheet.cell(index, 1).value for index in range(3, 11)] == ["0", "1", "2", "4", "5", "6", "7", "8"]
|
||||
assert all(not sheet.row_dimensions[index].hidden for index in range(3, 11))
|
||||
assert [sheet.cell(index, 1).alignment.indent for index in range(3, 11)] == [0, 1, 2, 2, 1, 2, 3, 0]
|
||||
assert all(sheet.cell(index, column).alignment.indent == 0 for index in range(3, 11) for column in (2, 3))
|
||||
if backend in ("xlsxwriter_columns", "xlsxwriter_rows"):
|
||||
assert sheet.cell(4, 1).font.bold is True
|
||||
if backend == "xlsxwriter_palette":
|
||||
assert sheet.cell(4, 1).fill.fgColor == sheet.cell(4, 2).fill.fgColor
|
||||
|
||||
|
||||
def test_tabular_sheet_writer_writes_headers_and_rows():
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user