Source code for fastpyxl.chart.plotarea

# Copyright (c) 2010-2024 fastpyxl

from __future__ import annotations

from fastpyxl.typed_serialisable.base import Serialisable
from fastpyxl.typed_serialisable.fields import AliasField, Field

from fastpyxl.descriptors.excel import ExtensionList

from fastpyxl.typed_serialisable.errors import FieldValidationError

from ._3d import _3DBase
from .area_chart import AreaChart, AreaChart3D
from .bar_chart import BarChart, BarChart3D
from .bubble_chart import BubbleChart
from .line_chart import LineChart, LineChart3D
from .pie_chart import PieChart, PieChart3D, ProjectedPieChart, DoughnutChart
from .radar_chart import RadarChart
from .scatter_chart import ScatterChart
from .stock_chart import StockChart
from .surface_chart import SurfaceChart, SurfaceChart3D
from .layout import Layout
from .shapes import GraphicalProperties
from .text import RichText

from .axis import (
    NumericAxis,
    TextAxis,
    SeriesAxis,
    DateAxis,
)


[docs] class DataTable(Serialisable): tagname = "dTable" showHorzBorder: bool | None = Field.nested_bool(allow_none=True, default=None) showVertBorder: bool | None = Field.nested_bool(allow_none=True, default=None) showOutline: bool | None = Field.nested_bool(allow_none=True, default=None) showKeys: bool | None = Field.nested_bool(allow_none=True, default=None) spPr: GraphicalProperties | None = Field.element( expected_type=GraphicalProperties, allow_none=True, default=None ) graphicalProperties = AliasField("spPr", default=None) txPr: RichText | None = Field.element(expected_type=RichText, allow_none=True, default=None) extLst: ExtensionList | None = Field.element( expected_type=ExtensionList, allow_none=True, serialize=False, default=None ) xml_order = ("showHorzBorder", "showVertBorder", "showOutline", "showKeys", "spPr", "txPr") def __init__( self, showHorzBorder=None, showVertBorder=None, showOutline=None, showKeys=None, spPr=None, txPr=None, extLst=None, ): self.showHorzBorder = showHorzBorder self.showVertBorder = showVertBorder self.showOutline = showOutline self.showKeys = showKeys self.spPr = spPr self.txPr = txPr self.extLst = extLst
_CHART_PARTS = { "areaChart": AreaChart, "area3DChart": AreaChart3D, "lineChart": LineChart, "line3DChart": LineChart3D, "stockChart": StockChart, "radarChart": RadarChart, "scatterChart": ScatterChart, "pieChart": PieChart, "pie3DChart": PieChart3D, "doughnutChart": DoughnutChart, "barChart": BarChart, "bar3DChart": BarChart3D, "ofPieChart": ProjectedPieChart, "surfaceChart": SurfaceChart, "surface3DChart": SurfaceChart3D, "bubbleChart": BubbleChart, } _AX_PARTS = { "valAx": NumericAxis, "catAx": TextAxis, "dateAx": DateAxis, "serAx": SeriesAxis, } _CHART_ASSIGN = frozenset(_CHART_PARTS) _AX_ASSIGN = frozenset(_AX_PARTS)
[docs] class PlotArea(Serialisable): tagname = "plotArea" layout: Layout | None = Field.element(expected_type=Layout, allow_none=True, default=None) dTable: DataTable | None = Field.element(expected_type=DataTable, allow_none=True, default=None) spPr: GraphicalProperties | None = Field.element( expected_type=GraphicalProperties, allow_none=True, default=None ) graphicalProperties = AliasField("spPr", default=None) extLst: ExtensionList | None = Field.element( expected_type=ExtensionList, allow_none=True, serialize=False, default=None ) _charts: list | None = Field.multi_sequence( parts=_CHART_PARTS, allow_none=True, default=list, ) _axes: list | None = Field.multi_sequence( parts=_AX_PARTS, allow_none=True, default=list, ) xml_order = ("layout", "_charts", "_axes", "dTable", "spPr") def __init__( self, layout=None, dTable=None, spPr=None, _charts=(), _axes=(), extLst=None, ): self.layout = layout self.dTable = dTable self.spPr = spPr self._charts = list(_charts) if _charts is not None else [] self._axes = list(_axes) if _axes is not None else [] self.extLst = extLst def __setattr__(self, name, value): if name in ("_charts", "_axes"): object.__setattr__(self, name, value) return if name in _CHART_ASSIGN: if value is None: return if not isinstance(value, _CHART_PARTS[name]): raise FieldValidationError(f"{name} rejected value {value!r}") cur = list(object.__getattribute__(self, "_charts")) cur.append(value) object.__setattr__(self, "_charts", cur) return if name in _AX_ASSIGN: if value is None: return if not isinstance(value, _AX_PARTS[name]): raise FieldValidationError(f"{name} rejected value {value!r}") cur = list(object.__getattribute__(self, "_axes")) cur.append(value) object.__setattr__(self, "_axes", cur) return super().__setattr__(name, value)
[docs] def to_tree(self, tagname=None, idx=None, namespace=None): del tagname, idx, namespace ax_ids = {ax.axId for ax in (self._axes or [])} for chart in self._charts or []: for _id, axis in chart._axes.items(): if _id not in ax_ids: setattr(self, axis.tagname, axis) ax_ids.add(_id) return super().to_tree()
[docs] @classmethod def from_tree(cls, node): self = super().from_tree(node) axes = dict((axis.axId, axis) for axis in (self._axes or [])) for chart in self._charts or []: if isinstance(chart, (ScatterChart, BubbleChart)): x, y = (axes[ax_id] for ax_id in chart.axId) chart.x_axis = x chart.y_axis = y continue for ax_id in chart.axId: axis = axes.get(ax_id) if axis is None and isinstance(chart, _3DBase): chart.z_axis = None continue if axis is None: continue if axis.tagname in ("catAx", "dateAx"): chart.x_axis = axis elif axis.tagname == "valAx": chart.y_axis = axis elif axis.tagname == "serAx": chart.z_axis = axis return self