aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/openpyxl/chart/_chart.py
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/openpyxl/chart/_chart.py')
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/_chart.py199
1 files changed, 199 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/_chart.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/_chart.py
new file mode 100644
index 00000000..6a613546
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/_chart.py
@@ -0,0 +1,199 @@
+# Copyright (c) 2010-2024 openpyxl
+
+from collections import OrderedDict
+from operator import attrgetter
+
+from openpyxl.descriptors import (
+ Typed,
+ Integer,
+ Alias,
+ MinMax,
+ Bool,
+ Set,
+)
+from openpyxl.descriptors.sequence import ValueSequence
+from openpyxl.descriptors.serialisable import Serialisable
+
+from ._3d import _3DBase
+from .data_source import AxDataSource, NumRef
+from .layout import Layout
+from .legend import Legend
+from .reference import Reference
+from .series_factory import SeriesFactory
+from .series import attribute_mapping
+from .shapes import GraphicalProperties
+from .title import TitleDescriptor
+
+class AxId(Serialisable):
+
+ val = Integer()
+
+ def __init__(self, val):
+ self.val = val
+
+
+def PlotArea():
+ from .chartspace import PlotArea
+ return PlotArea()
+
+
+class ChartBase(Serialisable):
+
+ """
+ Base class for all charts
+ """
+
+ legend = Typed(expected_type=Legend, allow_none=True)
+ layout = Typed(expected_type=Layout, allow_none=True)
+ roundedCorners = Bool(allow_none=True)
+ axId = ValueSequence(expected_type=int)
+ visible_cells_only = Bool(allow_none=True)
+ display_blanks = Set(values=['span', 'gap', 'zero'])
+ graphical_properties = Typed(expected_type=GraphicalProperties, allow_none=True)
+
+ _series_type = ""
+ ser = ()
+ series = Alias('ser')
+ title = TitleDescriptor()
+ anchor = "E15" # default anchor position
+ width = 15 # in cm, approx 5 rows
+ height = 7.5 # in cm, approx 14 rows
+ _id = 1
+ _path = "/xl/charts/chart{0}.xml"
+ style = MinMax(allow_none=True, min=1, max=48)
+ mime_type = "application/vnd.openxmlformats-officedocument.drawingml.chart+xml"
+ graphical_properties = Typed(expected_type=GraphicalProperties, allow_none=True) # mapped to chartspace
+
+ __elements__ = ()
+
+
+ def __init__(self, axId=(), **kw):
+ self._charts = [self]
+ self.title = None
+ self.layout = None
+ self.roundedCorners = None
+ self.legend = Legend()
+ self.graphical_properties = None
+ self.style = None
+ self.plot_area = PlotArea()
+ self.axId = axId
+ self.display_blanks = 'gap'
+ self.pivotSource = None
+ self.pivotFormats = ()
+ self.visible_cells_only = True
+ self.idx_base = 0
+ self.graphical_properties = None
+ super().__init__()
+
+
+ def __hash__(self):
+ """
+ Just need to check for identity
+ """
+ return id(self)
+
+ def __iadd__(self, other):
+ """
+ Combine the chart with another one
+ """
+ if not isinstance(other, ChartBase):
+ raise TypeError("Only other charts can be added")
+ self._charts.append(other)
+ return self
+
+
+ def to_tree(self, namespace=None, tagname=None, idx=None):
+ self.axId = [id for id in self._axes]
+ if self.ser is not None:
+ for s in self.ser:
+ s.__elements__ = attribute_mapping[self._series_type]
+ return super().to_tree(tagname, idx)
+
+
+ def _reindex(self):
+ """
+ Normalise and rebase series: sort by order and then rebase order
+
+ """
+ # sort data series in order and rebase
+ ds = sorted(self.series, key=attrgetter("order"))
+ for idx, s in enumerate(ds):
+ s.order = idx
+ self.series = ds
+
+
+ def _write(self):
+ from .chartspace import ChartSpace, ChartContainer
+ self.plot_area.layout = self.layout
+
+ idx_base = self.idx_base
+ for chart in self._charts:
+ if chart not in self.plot_area._charts:
+ chart.idx_base = idx_base
+ idx_base += len(chart.series)
+ self.plot_area._charts = self._charts
+
+ container = ChartContainer(plotArea=self.plot_area, legend=self.legend, title=self.title)
+ if isinstance(chart, _3DBase):
+ container.view3D = chart.view3D
+ container.floor = chart.floor
+ container.sideWall = chart.sideWall
+ container.backWall = chart.backWall
+ container.plotVisOnly = self.visible_cells_only
+ container.dispBlanksAs = self.display_blanks
+ container.pivotFmts = self.pivotFormats
+ cs = ChartSpace(chart=container)
+ cs.style = self.style
+ cs.roundedCorners = self.roundedCorners
+ cs.pivotSource = self.pivotSource
+ cs.spPr = self.graphical_properties
+ return cs.to_tree()
+
+
+ @property
+ def _axes(self):
+ x = getattr(self, "x_axis", None)
+ y = getattr(self, "y_axis", None)
+ z = getattr(self, "z_axis", None)
+ return OrderedDict([(axis.axId, axis) for axis in (x, y, z) if axis])
+
+
+ def set_categories(self, labels):
+ """
+ Set the categories / x-axis values
+ """
+ if not isinstance(labels, Reference):
+ labels = Reference(range_string=labels)
+ for s in self.ser:
+ s.cat = AxDataSource(numRef=NumRef(f=labels))
+
+
+ def add_data(self, data, from_rows=False, titles_from_data=False):
+ """
+ Add a range of data in a single pass.
+ The default is to treat each column as a data series.
+ """
+ if not isinstance(data, Reference):
+ data = Reference(range_string=data)
+
+ if from_rows:
+ values = data.rows
+
+ else:
+ values = data.cols
+
+ for ref in values:
+ series = SeriesFactory(ref, title_from_data=titles_from_data)
+ self.series.append(series)
+
+
+ def append(self, value):
+ """Append a data series to the chart"""
+ l = self.series[:]
+ l.append(value)
+ self.series = l
+
+
+ @property
+ def path(self):
+ return self._path.format(self._id)