aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/openpyxl/chart
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/openpyxl/chart
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are hereHEADmaster
Diffstat (limited to '.venv/lib/python3.12/site-packages/openpyxl/chart')
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/_3d.py105
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/__init__.py19
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/_chart.py199
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/area_chart.py106
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/axis.py401
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/bar_chart.py144
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/bubble_chart.py67
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/chartspace.py195
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/data_source.py246
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/descriptors.py43
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/error_bar.py62
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/label.py127
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/layout.py74
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/legend.py75
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/line_chart.py129
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/marker.py90
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/picture.py35
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/pie_chart.py177
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/pivot.py65
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/plotarea.py162
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/print_settings.py57
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/radar_chart.py55
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/reader.py32
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/reference.py124
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/scatter_chart.py53
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/series.py197
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/series_factory.py41
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/shapes.py89
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/stock_chart.py54
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/surface_chart.py119
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/text.py78
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/title.py76
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/trendline.py98
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/chart/updown_bars.py31
34 files changed, 3625 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/_3d.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/_3d.py
new file mode 100644
index 00000000..1651a993
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/_3d.py
@@ -0,0 +1,105 @@
+# Copyright (c) 2010-2024 openpyxl
+
+from openpyxl.descriptors import Typed, Alias
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors.nested import (
+ NestedBool,
+ NestedInteger,
+ NestedMinMax,
+)
+from openpyxl.descriptors.excel import ExtensionList
+from .marker import PictureOptions
+from .shapes import GraphicalProperties
+
+
+class View3D(Serialisable):
+
+ tagname = "view3D"
+
+ rotX = NestedMinMax(min=-90, max=90, allow_none=True)
+ x_rotation = Alias('rotX')
+ hPercent = NestedMinMax(min=5, max=500, allow_none=True)
+ height_percent = Alias('hPercent')
+ rotY = NestedInteger(min=-90, max=90, allow_none=True)
+ y_rotation = Alias('rotY')
+ depthPercent = NestedInteger(allow_none=True)
+ rAngAx = NestedBool(allow_none=True)
+ right_angle_axes = Alias('rAngAx')
+ perspective = NestedInteger(allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('rotX', 'hPercent', 'rotY', 'depthPercent', 'rAngAx',
+ 'perspective',)
+
+ def __init__(self,
+ rotX=15,
+ hPercent=None,
+ rotY=20,
+ depthPercent=None,
+ rAngAx=True,
+ perspective=None,
+ extLst=None,
+ ):
+ self.rotX = rotX
+ self.hPercent = hPercent
+ self.rotY = rotY
+ self.depthPercent = depthPercent
+ self.rAngAx = rAngAx
+ self.perspective = perspective
+
+
+class Surface(Serialisable):
+
+ tagname = "surface"
+
+ thickness = NestedInteger(allow_none=True)
+ spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
+ graphicalProperties = Alias('spPr')
+ pictureOptions = Typed(expected_type=PictureOptions, allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('thickness', 'spPr', 'pictureOptions',)
+
+ def __init__(self,
+ thickness=None,
+ spPr=None,
+ pictureOptions=None,
+ extLst=None,
+ ):
+ self.thickness = thickness
+ self.spPr = spPr
+ self.pictureOptions = pictureOptions
+
+
+class _3DBase(Serialisable):
+
+ """
+ Base class for 3D charts
+ """
+
+ tagname = "ChartBase"
+
+ view3D = Typed(expected_type=View3D, allow_none=True)
+ floor = Typed(expected_type=Surface, allow_none=True)
+ sideWall = Typed(expected_type=Surface, allow_none=True)
+ backWall = Typed(expected_type=Surface, allow_none=True)
+
+ def __init__(self,
+ view3D=None,
+ floor=None,
+ sideWall=None,
+ backWall=None,
+ ):
+ if view3D is None:
+ view3D = View3D()
+ self.view3D = view3D
+ if floor is None:
+ floor = Surface()
+ self.floor = floor
+ if sideWall is None:
+ sideWall = Surface()
+ self.sideWall = sideWall
+ if backWall is None:
+ backWall = Surface()
+ self.backWall = backWall
+ super(_3DBase, self).__init__()
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/__init__.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/__init__.py
new file mode 100644
index 00000000..ecc4d8bf
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/__init__.py
@@ -0,0 +1,19 @@
+# Copyright (c) 2010-2024 openpyxl
+
+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,
+ DoughnutChart,
+ ProjectedPieChart
+)
+from .radar_chart import RadarChart
+from .scatter_chart import ScatterChart
+from .stock_chart import StockChart
+from .surface_chart import SurfaceChart, SurfaceChart3D
+
+from .series_factory import SeriesFactory as Series
+from .reference import Reference
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)
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/area_chart.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/area_chart.py
new file mode 100644
index 00000000..d3d98085
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/area_chart.py
@@ -0,0 +1,106 @@
+# Copyright (c) 2010-2024 openpyxl
+
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ Typed,
+ Set,
+ Bool,
+ Integer,
+ Sequence,
+ Alias,
+)
+
+from openpyxl.descriptors.excel import ExtensionList
+from openpyxl.descriptors.nested import (
+ NestedMinMax,
+ NestedSet,
+ NestedBool,
+)
+
+from ._chart import ChartBase
+from .descriptors import NestedGapAmount
+from .axis import TextAxis, NumericAxis, SeriesAxis, ChartLines
+from .label import DataLabelList
+from .series import Series
+
+
+class _AreaChartBase(ChartBase):
+
+ grouping = NestedSet(values=(['percentStacked', 'standard', 'stacked']))
+ varyColors = NestedBool(nested=True, allow_none=True)
+ ser = Sequence(expected_type=Series, allow_none=True)
+ dLbls = Typed(expected_type=DataLabelList, allow_none=True)
+ dataLabels = Alias("dLbls")
+ dropLines = Typed(expected_type=ChartLines, allow_none=True)
+
+ _series_type = "area"
+
+ __elements__ = ('grouping', 'varyColors', 'ser', 'dLbls', 'dropLines')
+
+ def __init__(self,
+ grouping="standard",
+ varyColors=None,
+ ser=(),
+ dLbls=None,
+ dropLines=None,
+ ):
+ self.grouping = grouping
+ self.varyColors = varyColors
+ self.ser = ser
+ self.dLbls = dLbls
+ self.dropLines = dropLines
+ super().__init__()
+
+
+class AreaChart(_AreaChartBase):
+
+ tagname = "areaChart"
+
+ grouping = _AreaChartBase.grouping
+ varyColors = _AreaChartBase.varyColors
+ ser = _AreaChartBase.ser
+ dLbls = _AreaChartBase.dLbls
+ dropLines = _AreaChartBase.dropLines
+
+ # chart properties actually used by containing classes
+ x_axis = Typed(expected_type=TextAxis)
+ y_axis = Typed(expected_type=NumericAxis)
+
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = _AreaChartBase.__elements__ + ('axId',)
+
+ def __init__(self,
+ axId=None,
+ extLst=None,
+ **kw
+ ):
+ self.x_axis = TextAxis()
+ self.y_axis = NumericAxis()
+ super().__init__(**kw)
+
+
+class AreaChart3D(AreaChart):
+
+ tagname = "area3DChart"
+
+ grouping = _AreaChartBase.grouping
+ varyColors = _AreaChartBase.varyColors
+ ser = _AreaChartBase.ser
+ dLbls = _AreaChartBase.dLbls
+ dropLines = _AreaChartBase.dropLines
+
+ gapDepth = NestedGapAmount()
+
+ x_axis = Typed(expected_type=TextAxis)
+ y_axis = Typed(expected_type=NumericAxis)
+ z_axis = Typed(expected_type=SeriesAxis, allow_none=True)
+
+ __elements__ = AreaChart.__elements__ + ('gapDepth', )
+
+ def __init__(self, gapDepth=None, **kw):
+ self.gapDepth = gapDepth
+ super(AreaChart3D, self).__init__(**kw)
+ self.x_axis = TextAxis()
+ self.y_axis = NumericAxis()
+ self.z_axis = SeriesAxis()
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/axis.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/axis.py
new file mode 100644
index 00000000..7e99416c
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/axis.py
@@ -0,0 +1,401 @@
+# Copyright (c) 2010-2024 openpyxl
+
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ Typed,
+ Float,
+ NoneSet,
+ Bool,
+ Integer,
+ MinMax,
+ NoneSet,
+ Set,
+ String,
+ Alias,
+)
+
+from openpyxl.descriptors.excel import (
+ ExtensionList,
+ Percentage,
+ _explicit_none,
+)
+from openpyxl.descriptors.nested import (
+ NestedValue,
+ NestedSet,
+ NestedBool,
+ NestedNoneSet,
+ NestedFloat,
+ NestedInteger,
+ NestedMinMax,
+)
+from openpyxl.xml.constants import CHART_NS
+
+from .descriptors import NumberFormatDescriptor
+from .layout import Layout
+from .text import Text, RichText
+from .shapes import GraphicalProperties
+from .title import Title, TitleDescriptor
+
+
+class ChartLines(Serialisable):
+
+ tagname = "chartLines"
+
+ spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
+ graphicalProperties = Alias('spPr')
+
+ def __init__(self, spPr=None):
+ self.spPr = spPr
+
+
+class Scaling(Serialisable):
+
+ tagname = "scaling"
+
+ logBase = NestedFloat(allow_none=True)
+ orientation = NestedSet(values=(['maxMin', 'minMax']))
+ max = NestedFloat(allow_none=True)
+ min = NestedFloat(allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('logBase', 'orientation', 'max', 'min',)
+
+ def __init__(self,
+ logBase=None,
+ orientation="minMax",
+ max=None,
+ min=None,
+ extLst=None,
+ ):
+ self.logBase = logBase
+ self.orientation = orientation
+ self.max = max
+ self.min = min
+
+
+class _BaseAxis(Serialisable):
+
+ axId = NestedInteger(expected_type=int)
+ scaling = Typed(expected_type=Scaling)
+ delete = NestedBool(allow_none=True)
+ axPos = NestedSet(values=(['b', 'l', 'r', 't']))
+ majorGridlines = Typed(expected_type=ChartLines, allow_none=True)
+ minorGridlines = Typed(expected_type=ChartLines, allow_none=True)
+ title = TitleDescriptor()
+ numFmt = NumberFormatDescriptor()
+ number_format = Alias("numFmt")
+ majorTickMark = NestedNoneSet(values=(['cross', 'in', 'out']), to_tree=_explicit_none)
+ minorTickMark = NestedNoneSet(values=(['cross', 'in', 'out']), to_tree=_explicit_none)
+ tickLblPos = NestedNoneSet(values=(['high', 'low', 'nextTo']))
+ spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
+ graphicalProperties = Alias('spPr')
+ txPr = Typed(expected_type=RichText, allow_none=True)
+ textProperties = Alias('txPr')
+ crossAx = NestedInteger(expected_type=int) # references other axis
+ crosses = NestedNoneSet(values=(['autoZero', 'max', 'min']))
+ crossesAt = NestedFloat(allow_none=True)
+
+ # crosses & crossesAt are mutually exclusive
+
+ __elements__ = ('axId', 'scaling', 'delete', 'axPos', 'majorGridlines',
+ 'minorGridlines', 'title', 'numFmt', 'majorTickMark', 'minorTickMark',
+ 'tickLblPos', 'spPr', 'txPr', 'crossAx', 'crosses', 'crossesAt')
+
+ def __init__(self,
+ axId=None,
+ scaling=None,
+ delete=None,
+ axPos='l',
+ majorGridlines=None,
+ minorGridlines=None,
+ title=None,
+ numFmt=None,
+ majorTickMark=None,
+ minorTickMark=None,
+ tickLblPos=None,
+ spPr=None,
+ txPr= None,
+ crossAx=None,
+ crosses=None,
+ crossesAt=None,
+ ):
+ self.axId = axId
+ if scaling is None:
+ scaling = Scaling()
+ self.scaling = scaling
+ self.delete = delete
+ self.axPos = axPos
+ self.majorGridlines = majorGridlines
+ self.minorGridlines = minorGridlines
+ self.title = title
+ self.numFmt = numFmt
+ self.majorTickMark = majorTickMark
+ self.minorTickMark = minorTickMark
+ self.tickLblPos = tickLblPos
+ self.spPr = spPr
+ self.txPr = txPr
+ self.crossAx = crossAx
+ self.crosses = crosses
+ self.crossesAt = crossesAt
+
+
+class DisplayUnitsLabel(Serialisable):
+
+ tagname = "dispUnitsLbl"
+
+ layout = Typed(expected_type=Layout, allow_none=True)
+ tx = Typed(expected_type=Text, allow_none=True)
+ text = Alias("tx")
+ spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
+ graphicalProperties = Alias("spPr")
+ txPr = Typed(expected_type=RichText, allow_none=True)
+ textPropertes = Alias("txPr")
+
+ __elements__ = ('layout', 'tx', 'spPr', 'txPr')
+
+ def __init__(self,
+ layout=None,
+ tx=None,
+ spPr=None,
+ txPr=None,
+ ):
+ self.layout = layout
+ self.tx = tx
+ self.spPr = spPr
+ self.txPr = txPr
+
+
+class DisplayUnitsLabelList(Serialisable):
+
+ tagname = "dispUnits"
+
+ custUnit = NestedFloat(allow_none=True)
+ builtInUnit = NestedNoneSet(values=(['hundreds', 'thousands',
+ 'tenThousands', 'hundredThousands', 'millions', 'tenMillions',
+ 'hundredMillions', 'billions', 'trillions']))
+ dispUnitsLbl = Typed(expected_type=DisplayUnitsLabel, allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('custUnit', 'builtInUnit', 'dispUnitsLbl',)
+
+ def __init__(self,
+ custUnit=None,
+ builtInUnit=None,
+ dispUnitsLbl=None,
+ extLst=None,
+ ):
+ self.custUnit = custUnit
+ self.builtInUnit = builtInUnit
+ self.dispUnitsLbl = dispUnitsLbl
+
+
+class NumericAxis(_BaseAxis):
+
+ tagname = "valAx"
+
+ axId = _BaseAxis.axId
+ scaling = _BaseAxis.scaling
+ delete = _BaseAxis.delete
+ axPos = _BaseAxis.axPos
+ majorGridlines = _BaseAxis.majorGridlines
+ minorGridlines = _BaseAxis.minorGridlines
+ title = _BaseAxis.title
+ numFmt = _BaseAxis.numFmt
+ majorTickMark = _BaseAxis.majorTickMark
+ minorTickMark = _BaseAxis.minorTickMark
+ tickLblPos = _BaseAxis.tickLblPos
+ spPr = _BaseAxis.spPr
+ txPr = _BaseAxis.txPr
+ crossAx = _BaseAxis.crossAx
+ crosses = _BaseAxis.crosses
+ crossesAt = _BaseAxis.crossesAt
+
+ crossBetween = NestedNoneSet(values=(['between', 'midCat']))
+ majorUnit = NestedFloat(allow_none=True)
+ minorUnit = NestedFloat(allow_none=True)
+ dispUnits = Typed(expected_type=DisplayUnitsLabelList, allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = _BaseAxis.__elements__ + ('crossBetween', 'majorUnit',
+ 'minorUnit', 'dispUnits',)
+
+
+ def __init__(self,
+ crossBetween=None,
+ majorUnit=None,
+ minorUnit=None,
+ dispUnits=None,
+ extLst=None,
+ **kw
+ ):
+ self.crossBetween = crossBetween
+ self.majorUnit = majorUnit
+ self.minorUnit = minorUnit
+ self.dispUnits = dispUnits
+ kw.setdefault('majorGridlines', ChartLines())
+ kw.setdefault('axId', 100)
+ kw.setdefault('crossAx', 10)
+ super().__init__(**kw)
+
+
+ @classmethod
+ def from_tree(cls, node):
+ """
+ Special case value axes with no gridlines
+ """
+ self = super().from_tree(node)
+ gridlines = node.find("{%s}majorGridlines" % CHART_NS)
+ if gridlines is None:
+ self.majorGridlines = None
+ return self
+
+
+
+class TextAxis(_BaseAxis):
+
+ tagname = "catAx"
+
+ axId = _BaseAxis.axId
+ scaling = _BaseAxis.scaling
+ delete = _BaseAxis.delete
+ axPos = _BaseAxis.axPos
+ majorGridlines = _BaseAxis.majorGridlines
+ minorGridlines = _BaseAxis.minorGridlines
+ title = _BaseAxis.title
+ numFmt = _BaseAxis.numFmt
+ majorTickMark = _BaseAxis.majorTickMark
+ minorTickMark = _BaseAxis.minorTickMark
+ tickLblPos = _BaseAxis.tickLblPos
+ spPr = _BaseAxis.spPr
+ txPr = _BaseAxis.txPr
+ crossAx = _BaseAxis.crossAx
+ crosses = _BaseAxis.crosses
+ crossesAt = _BaseAxis.crossesAt
+
+ auto = NestedBool(allow_none=True)
+ lblAlgn = NestedNoneSet(values=(['ctr', 'l', 'r']))
+ lblOffset = NestedMinMax(min=0, max=1000)
+ tickLblSkip = NestedInteger(allow_none=True)
+ tickMarkSkip = NestedInteger(allow_none=True)
+ noMultiLvlLbl = NestedBool(allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = _BaseAxis.__elements__ + ('auto', 'lblAlgn', 'lblOffset',
+ 'tickLblSkip', 'tickMarkSkip', 'noMultiLvlLbl')
+
+ def __init__(self,
+ auto=None,
+ lblAlgn=None,
+ lblOffset=100,
+ tickLblSkip=None,
+ tickMarkSkip=None,
+ noMultiLvlLbl=None,
+ extLst=None,
+ **kw
+ ):
+ self.auto = auto
+ self.lblAlgn = lblAlgn
+ self.lblOffset = lblOffset
+ self.tickLblSkip = tickLblSkip
+ self.tickMarkSkip = tickMarkSkip
+ self.noMultiLvlLbl = noMultiLvlLbl
+ kw.setdefault('axId', 10)
+ kw.setdefault('crossAx', 100)
+ super().__init__(**kw)
+
+
+class DateAxis(TextAxis):
+
+ tagname = "dateAx"
+
+ axId = _BaseAxis.axId
+ scaling = _BaseAxis.scaling
+ delete = _BaseAxis.delete
+ axPos = _BaseAxis.axPos
+ majorGridlines = _BaseAxis.majorGridlines
+ minorGridlines = _BaseAxis.minorGridlines
+ title = _BaseAxis.title
+ numFmt = _BaseAxis.numFmt
+ majorTickMark = _BaseAxis.majorTickMark
+ minorTickMark = _BaseAxis.minorTickMark
+ tickLblPos = _BaseAxis.tickLblPos
+ spPr = _BaseAxis.spPr
+ txPr = _BaseAxis.txPr
+ crossAx = _BaseAxis.crossAx
+ crosses = _BaseAxis.crosses
+ crossesAt = _BaseAxis.crossesAt
+
+ auto = NestedBool(allow_none=True)
+ lblOffset = NestedInteger(allow_none=True)
+ baseTimeUnit = NestedNoneSet(values=(['days', 'months', 'years']))
+ majorUnit = NestedFloat(allow_none=True)
+ majorTimeUnit = NestedNoneSet(values=(['days', 'months', 'years']))
+ minorUnit = NestedFloat(allow_none=True)
+ minorTimeUnit = NestedNoneSet(values=(['days', 'months', 'years']))
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = _BaseAxis.__elements__ + ('auto', 'lblOffset',
+ 'baseTimeUnit', 'majorUnit', 'majorTimeUnit', 'minorUnit',
+ 'minorTimeUnit')
+
+ def __init__(self,
+ auto=None,
+ lblOffset=None,
+ baseTimeUnit=None,
+ majorUnit=None,
+ majorTimeUnit=None,
+ minorUnit=None,
+ minorTimeUnit=None,
+ extLst=None,
+ **kw
+ ):
+ self.auto = auto
+ self.lblOffset = lblOffset
+ self.baseTimeUnit = baseTimeUnit
+ self.majorUnit = majorUnit
+ self.majorTimeUnit = majorTimeUnit
+ self.minorUnit = minorUnit
+ self.minorTimeUnit = minorTimeUnit
+ kw.setdefault('axId', 500)
+ kw.setdefault('lblOffset', lblOffset)
+ super().__init__(**kw)
+
+
+class SeriesAxis(_BaseAxis):
+
+ tagname = "serAx"
+
+ axId = _BaseAxis.axId
+ scaling = _BaseAxis.scaling
+ delete = _BaseAxis.delete
+ axPos = _BaseAxis.axPos
+ majorGridlines = _BaseAxis.majorGridlines
+ minorGridlines = _BaseAxis.minorGridlines
+ title = _BaseAxis.title
+ numFmt = _BaseAxis.numFmt
+ majorTickMark = _BaseAxis.majorTickMark
+ minorTickMark = _BaseAxis.minorTickMark
+ tickLblPos = _BaseAxis.tickLblPos
+ spPr = _BaseAxis.spPr
+ txPr = _BaseAxis.txPr
+ crossAx = _BaseAxis.crossAx
+ crosses = _BaseAxis.crosses
+ crossesAt = _BaseAxis.crossesAt
+
+ tickLblSkip = NestedInteger(allow_none=True)
+ tickMarkSkip = NestedInteger(allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = _BaseAxis.__elements__ + ('tickLblSkip', 'tickMarkSkip')
+
+ def __init__(self,
+ tickLblSkip=None,
+ tickMarkSkip=None,
+ extLst=None,
+ **kw
+ ):
+ self.tickLblSkip = tickLblSkip
+ self.tickMarkSkip = tickMarkSkip
+ kw.setdefault('axId', 1000)
+ kw.setdefault('crossAx', 10)
+ super().__init__(**kw)
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/bar_chart.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/bar_chart.py
new file mode 100644
index 00000000..fa08e076
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/bar_chart.py
@@ -0,0 +1,144 @@
+# Copyright (c) 2010-2024 openpyxl
+
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ Typed,
+ Bool,
+ Integer,
+ Sequence,
+ Alias,
+)
+from openpyxl.descriptors.excel import ExtensionList
+from openpyxl.descriptors.nested import (
+ NestedNoneSet,
+ NestedSet,
+ NestedBool,
+ NestedInteger,
+ NestedMinMax,
+)
+
+from .descriptors import (
+ NestedGapAmount,
+ NestedOverlap,
+)
+from ._chart import ChartBase
+from ._3d import _3DBase
+from .axis import TextAxis, NumericAxis, SeriesAxis, ChartLines
+from .shapes import GraphicalProperties
+from .series import Series
+from .legend import Legend
+from .label import DataLabelList
+
+
+class _BarChartBase(ChartBase):
+
+ barDir = NestedSet(values=(['bar', 'col']))
+ type = Alias("barDir")
+ grouping = NestedSet(values=(['percentStacked', 'clustered', 'standard',
+ 'stacked']))
+ varyColors = NestedBool(nested=True, allow_none=True)
+ ser = Sequence(expected_type=Series, allow_none=True)
+ dLbls = Typed(expected_type=DataLabelList, allow_none=True)
+ dataLabels = Alias("dLbls")
+
+ __elements__ = ('barDir', 'grouping', 'varyColors', 'ser', 'dLbls')
+
+ _series_type = "bar"
+
+ def __init__(self,
+ barDir="col",
+ grouping="clustered",
+ varyColors=None,
+ ser=(),
+ dLbls=None,
+ **kw
+ ):
+ self.barDir = barDir
+ self.grouping = grouping
+ self.varyColors = varyColors
+ self.ser = ser
+ self.dLbls = dLbls
+ super().__init__(**kw)
+
+
+class BarChart(_BarChartBase):
+
+ tagname = "barChart"
+
+ barDir = _BarChartBase.barDir
+ grouping = _BarChartBase.grouping
+ varyColors = _BarChartBase.varyColors
+ ser = _BarChartBase.ser
+ dLbls = _BarChartBase.dLbls
+
+ gapWidth = NestedGapAmount()
+ overlap = NestedOverlap()
+ serLines = Typed(expected_type=ChartLines, allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ # chart properties actually used by containing classes
+ x_axis = Typed(expected_type=TextAxis)
+ y_axis = Typed(expected_type=NumericAxis)
+
+ __elements__ = _BarChartBase.__elements__ + ('gapWidth', 'overlap', 'serLines', 'axId')
+
+ def __init__(self,
+ gapWidth=150,
+ overlap=None,
+ serLines=None,
+ extLst=None,
+ **kw
+ ):
+ self.gapWidth = gapWidth
+ self.overlap = overlap
+ self.serLines = serLines
+ self.x_axis = TextAxis()
+ self.y_axis = NumericAxis()
+ self.legend = Legend()
+ super().__init__(**kw)
+
+
+class BarChart3D(_BarChartBase, _3DBase):
+
+ tagname = "bar3DChart"
+
+ barDir = _BarChartBase.barDir
+ grouping = _BarChartBase.grouping
+ varyColors = _BarChartBase.varyColors
+ ser = _BarChartBase.ser
+ dLbls = _BarChartBase.dLbls
+
+ view3D = _3DBase.view3D
+ floor = _3DBase.floor
+ sideWall = _3DBase.sideWall
+ backWall = _3DBase.backWall
+
+ gapWidth = NestedGapAmount()
+ gapDepth = NestedGapAmount()
+ shape = NestedNoneSet(values=(['cone', 'coneToMax', 'box', 'cylinder', 'pyramid', 'pyramidToMax']))
+ serLines = Typed(expected_type=ChartLines, allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ x_axis = Typed(expected_type=TextAxis)
+ y_axis = Typed(expected_type=NumericAxis)
+ z_axis = Typed(expected_type=SeriesAxis, allow_none=True)
+
+ __elements__ = _BarChartBase.__elements__ + ('gapWidth', 'gapDepth', 'shape', 'serLines', 'axId')
+
+ def __init__(self,
+ gapWidth=150,
+ gapDepth=150,
+ shape=None,
+ serLines=None,
+ extLst=None,
+ **kw
+ ):
+ self.gapWidth = gapWidth
+ self.gapDepth = gapDepth
+ self.shape = shape
+ self.serLines = serLines
+ self.x_axis = TextAxis()
+ self.y_axis = NumericAxis()
+ self.z_axis = SeriesAxis()
+
+ super(BarChart3D, self).__init__(**kw)
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/bubble_chart.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/bubble_chart.py
new file mode 100644
index 00000000..3fca043a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/bubble_chart.py
@@ -0,0 +1,67 @@
+#Autogenerated schema
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ Typed,
+ Set,
+ MinMax,
+ Bool,
+ Integer,
+ Alias,
+ Sequence,
+)
+from openpyxl.descriptors.excel import ExtensionList
+from openpyxl.descriptors.nested import (
+ NestedNoneSet,
+ NestedMinMax,
+ NestedBool,
+)
+
+from ._chart import ChartBase
+from .axis import TextAxis, NumericAxis
+from .series import XYSeries
+from .label import DataLabelList
+
+
+class BubbleChart(ChartBase):
+
+ tagname = "bubbleChart"
+
+ varyColors = NestedBool(allow_none=True)
+ ser = Sequence(expected_type=XYSeries, allow_none=True)
+ dLbls = Typed(expected_type=DataLabelList, allow_none=True)
+ dataLabels = Alias("dLbls")
+ bubble3D = NestedBool(allow_none=True)
+ bubbleScale = NestedMinMax(min=0, max=300, allow_none=True)
+ showNegBubbles = NestedBool(allow_none=True)
+ sizeRepresents = NestedNoneSet(values=(['area', 'w']))
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ x_axis = Typed(expected_type=NumericAxis)
+ y_axis = Typed(expected_type=NumericAxis)
+
+ _series_type = "bubble"
+
+ __elements__ = ('varyColors', 'ser', 'dLbls', 'bubble3D', 'bubbleScale',
+ 'showNegBubbles', 'sizeRepresents', 'axId')
+
+ def __init__(self,
+ varyColors=None,
+ ser=(),
+ dLbls=None,
+ bubble3D=None,
+ bubbleScale=None,
+ showNegBubbles=None,
+ sizeRepresents=None,
+ extLst=None,
+ **kw
+ ):
+ self.varyColors = varyColors
+ self.ser = ser
+ self.dLbls = dLbls
+ self.bubble3D = bubble3D
+ self.bubbleScale = bubbleScale
+ self.showNegBubbles = showNegBubbles
+ self.sizeRepresents = sizeRepresents
+ self.x_axis = NumericAxis(axId=10, crossAx=20)
+ self.y_axis = NumericAxis(axId=20, crossAx=10)
+ super().__init__(**kw)
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/chartspace.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/chartspace.py
new file mode 100644
index 00000000..cba213c2
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/chartspace.py
@@ -0,0 +1,195 @@
+
+# Copyright (c) 2010-2024 openpyxl
+
+"""
+Enclosing chart object. The various chart types are actually child objects.
+Will probably need to call this indirectly
+"""
+
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ Typed,
+ String,
+ Alias,
+)
+from openpyxl.descriptors.excel import (
+ ExtensionList,
+ Relation
+)
+from openpyxl.descriptors.nested import (
+ NestedBool,
+ NestedNoneSet,
+ NestedString,
+ NestedMinMax,
+)
+from openpyxl.descriptors.sequence import NestedSequence
+from openpyxl.xml.constants import CHART_NS
+
+from openpyxl.drawing.colors import ColorMapping
+from .text import RichText
+from .shapes import GraphicalProperties
+from .legend import Legend
+from ._3d import _3DBase
+from .plotarea import PlotArea
+from .title import Title
+from .pivot import (
+ PivotFormat,
+ PivotSource,
+)
+from .print_settings import PrintSettings
+
+
+class ChartContainer(Serialisable):
+
+ tagname = "chart"
+
+ title = Typed(expected_type=Title, allow_none=True)
+ autoTitleDeleted = NestedBool(allow_none=True)
+ pivotFmts = NestedSequence(expected_type=PivotFormat)
+ view3D = _3DBase.view3D
+ floor = _3DBase.floor
+ sideWall = _3DBase.sideWall
+ backWall = _3DBase.backWall
+ plotArea = Typed(expected_type=PlotArea, )
+ legend = Typed(expected_type=Legend, allow_none=True)
+ plotVisOnly = NestedBool()
+ dispBlanksAs = NestedNoneSet(values=(['span', 'gap', 'zero']))
+ showDLblsOverMax = NestedBool(allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('title', 'autoTitleDeleted', 'pivotFmts', 'view3D',
+ 'floor', 'sideWall', 'backWall', 'plotArea', 'legend', 'plotVisOnly',
+ 'dispBlanksAs', 'showDLblsOverMax')
+
+ def __init__(self,
+ title=None,
+ autoTitleDeleted=None,
+ pivotFmts=(),
+ view3D=None,
+ floor=None,
+ sideWall=None,
+ backWall=None,
+ plotArea=None,
+ legend=None,
+ plotVisOnly=True,
+ dispBlanksAs="gap",
+ showDLblsOverMax=None,
+ extLst=None,
+ ):
+ self.title = title
+ self.autoTitleDeleted = autoTitleDeleted
+ self.pivotFmts = pivotFmts
+ self.view3D = view3D
+ self.floor = floor
+ self.sideWall = sideWall
+ self.backWall = backWall
+ if plotArea is None:
+ plotArea = PlotArea()
+ self.plotArea = plotArea
+ self.legend = legend
+ self.plotVisOnly = plotVisOnly
+ self.dispBlanksAs = dispBlanksAs
+ self.showDLblsOverMax = showDLblsOverMax
+
+
+class Protection(Serialisable):
+
+ tagname = "protection"
+
+ chartObject = NestedBool(allow_none=True)
+ data = NestedBool(allow_none=True)
+ formatting = NestedBool(allow_none=True)
+ selection = NestedBool(allow_none=True)
+ userInterface = NestedBool(allow_none=True)
+
+ __elements__ = ("chartObject", "data", "formatting", "selection", "userInterface")
+
+ def __init__(self,
+ chartObject=None,
+ data=None,
+ formatting=None,
+ selection=None,
+ userInterface=None,
+ ):
+ self.chartObject = chartObject
+ self.data = data
+ self.formatting = formatting
+ self.selection = selection
+ self.userInterface = userInterface
+
+
+class ExternalData(Serialisable):
+
+ tagname = "externalData"
+
+ autoUpdate = NestedBool(allow_none=True)
+ id = String() # Needs namespace
+
+ def __init__(self,
+ autoUpdate=None,
+ id=None
+ ):
+ self.autoUpdate = autoUpdate
+ self.id = id
+
+
+class ChartSpace(Serialisable):
+
+ tagname = "chartSpace"
+
+ date1904 = NestedBool(allow_none=True)
+ lang = NestedString(allow_none=True)
+ roundedCorners = NestedBool(allow_none=True)
+ style = NestedMinMax(allow_none=True, min=1, max=48)
+ clrMapOvr = Typed(expected_type=ColorMapping, allow_none=True)
+ pivotSource = Typed(expected_type=PivotSource, allow_none=True)
+ protection = Typed(expected_type=Protection, allow_none=True)
+ chart = Typed(expected_type=ChartContainer)
+ spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
+ graphical_properties = Alias("spPr")
+ txPr = Typed(expected_type=RichText, allow_none=True)
+ textProperties = Alias("txPr")
+ externalData = Typed(expected_type=ExternalData, allow_none=True)
+ printSettings = Typed(expected_type=PrintSettings, allow_none=True)
+ userShapes = Relation()
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('date1904', 'lang', 'roundedCorners', 'style',
+ 'clrMapOvr', 'pivotSource', 'protection', 'chart', 'spPr', 'txPr',
+ 'externalData', 'printSettings', 'userShapes')
+
+ def __init__(self,
+ date1904=None,
+ lang=None,
+ roundedCorners=None,
+ style=None,
+ clrMapOvr=None,
+ pivotSource=None,
+ protection=None,
+ chart=None,
+ spPr=None,
+ txPr=None,
+ externalData=None,
+ printSettings=None,
+ userShapes=None,
+ extLst=None,
+ ):
+ self.date1904 = date1904
+ self.lang = lang
+ self.roundedCorners = roundedCorners
+ self.style = style
+ self.clrMapOvr = clrMapOvr
+ self.pivotSource = pivotSource
+ self.protection = protection
+ self.chart = chart
+ self.spPr = spPr
+ self.txPr = txPr
+ self.externalData = externalData
+ self.printSettings = printSettings
+ self.userShapes = userShapes
+
+
+ def to_tree(self, tagname=None, idx=None, namespace=None):
+ tree = super().to_tree()
+ tree.set("xmlns", CHART_NS)
+ return tree
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/data_source.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/data_source.py
new file mode 100644
index 00000000..c38eafb2
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/data_source.py
@@ -0,0 +1,246 @@
+"""
+Collection of utility primitives for charts.
+"""
+
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ Bool,
+ Typed,
+ Alias,
+ String,
+ Integer,
+ Sequence,
+)
+from openpyxl.descriptors.excel import ExtensionList
+from openpyxl.descriptors.nested import (
+ NestedString,
+ NestedText,
+ NestedInteger,
+)
+
+
+class NumFmt(Serialisable):
+
+ formatCode = String()
+ sourceLinked = Bool()
+
+ def __init__(self,
+ formatCode=None,
+ sourceLinked=False
+ ):
+ self.formatCode = formatCode
+ self.sourceLinked = sourceLinked
+
+
+class NumberValueDescriptor(NestedText):
+ """
+ Data should be numerical but isn't always :-/
+ """
+
+ allow_none = True
+
+ def __set__(self, instance, value):
+ if value == "#N/A":
+ self.expected_type = str
+ else:
+ self.expected_type = float
+ super().__set__(instance, value)
+
+
+class NumVal(Serialisable):
+
+ idx = Integer()
+ formatCode = NestedText(allow_none=True, expected_type=str)
+ v = NumberValueDescriptor()
+
+ def __init__(self,
+ idx=None,
+ formatCode=None,
+ v=None,
+ ):
+ self.idx = idx
+ self.formatCode = formatCode
+ self.v = v
+
+
+class NumData(Serialisable):
+
+ formatCode = NestedText(expected_type=str, allow_none=True)
+ ptCount = NestedInteger(allow_none=True)
+ pt = Sequence(expected_type=NumVal)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('formatCode', 'ptCount', 'pt')
+
+ def __init__(self,
+ formatCode=None,
+ ptCount=None,
+ pt=(),
+ extLst=None,
+ ):
+ self.formatCode = formatCode
+ self.ptCount = ptCount
+ self.pt = pt
+
+
+class NumRef(Serialisable):
+
+ f = NestedText(expected_type=str)
+ ref = Alias('f')
+ numCache = Typed(expected_type=NumData, allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('f', 'numCache')
+
+ def __init__(self,
+ f=None,
+ numCache=None,
+ extLst=None,
+ ):
+ self.f = f
+ self.numCache = numCache
+
+
+class StrVal(Serialisable):
+
+ tagname = "strVal"
+
+ idx = Integer()
+ v = NestedText(expected_type=str)
+
+ def __init__(self,
+ idx=0,
+ v=None,
+ ):
+ self.idx = idx
+ self.v = v
+
+
+class StrData(Serialisable):
+
+ tagname = "strData"
+
+ ptCount = NestedInteger(allow_none=True)
+ pt = Sequence(expected_type=StrVal)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('ptCount', 'pt')
+
+ def __init__(self,
+ ptCount=None,
+ pt=(),
+ extLst=None,
+ ):
+ self.ptCount = ptCount
+ self.pt = pt
+
+
+class StrRef(Serialisable):
+
+ tagname = "strRef"
+
+ f = NestedText(expected_type=str, allow_none=True)
+ strCache = Typed(expected_type=StrData, allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('f', 'strCache')
+
+ def __init__(self,
+ f=None,
+ strCache=None,
+ extLst=None,
+ ):
+ self.f = f
+ self.strCache = strCache
+
+
+class NumDataSource(Serialisable):
+
+ numRef = Typed(expected_type=NumRef, allow_none=True)
+ numLit = Typed(expected_type=NumData, allow_none=True)
+
+
+ def __init__(self,
+ numRef=None,
+ numLit=None,
+ ):
+ self.numRef = numRef
+ self.numLit = numLit
+
+
+class Level(Serialisable):
+
+ tagname = "lvl"
+
+ pt = Sequence(expected_type=StrVal)
+
+ __elements__ = ('pt',)
+
+ def __init__(self,
+ pt=(),
+ ):
+ self.pt = pt
+
+
+class MultiLevelStrData(Serialisable):
+
+ tagname = "multiLvlStrData"
+
+ ptCount = Integer(allow_none=True)
+ lvl = Sequence(expected_type=Level)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('ptCount', 'lvl',)
+
+ def __init__(self,
+ ptCount=None,
+ lvl=(),
+ extLst=None,
+ ):
+ self.ptCount = ptCount
+ self.lvl = lvl
+
+
+class MultiLevelStrRef(Serialisable):
+
+ tagname = "multiLvlStrRef"
+
+ f = NestedText(expected_type=str)
+ multiLvlStrCache = Typed(expected_type=MultiLevelStrData, allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('multiLvlStrCache', 'f')
+
+ def __init__(self,
+ f=None,
+ multiLvlStrCache=None,
+ extLst=None,
+ ):
+ self.f = f
+ self.multiLvlStrCache = multiLvlStrCache
+
+
+class AxDataSource(Serialisable):
+
+ tagname = "cat"
+
+ numRef = Typed(expected_type=NumRef, allow_none=True)
+ numLit = Typed(expected_type=NumData, allow_none=True)
+ strRef = Typed(expected_type=StrRef, allow_none=True)
+ strLit = Typed(expected_type=StrData, allow_none=True)
+ multiLvlStrRef = Typed(expected_type=MultiLevelStrRef, allow_none=True)
+
+ def __init__(self,
+ numRef=None,
+ numLit=None,
+ strRef=None,
+ strLit=None,
+ multiLvlStrRef=None,
+ ):
+ if not any([numLit, numRef, strRef, strLit, multiLvlStrRef]):
+ raise TypeError("A data source must be provided")
+ self.numRef = numRef
+ self.numLit = numLit
+ self.strRef = strRef
+ self.strLit = strLit
+ self.multiLvlStrRef = multiLvlStrRef
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/descriptors.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/descriptors.py
new file mode 100644
index 00000000..6bc94348
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/descriptors.py
@@ -0,0 +1,43 @@
+# Copyright (c) 2010-2024 openpyxl
+
+
+
+from openpyxl.descriptors.nested import (
+ NestedMinMax
+ )
+
+from openpyxl.descriptors import Typed
+
+from .data_source import NumFmt
+
+"""
+Utility descriptors for the chart module.
+For convenience but also clarity.
+"""
+
+class NestedGapAmount(NestedMinMax):
+
+ allow_none = True
+ min = 0
+ max = 500
+
+
+class NestedOverlap(NestedMinMax):
+
+ allow_none = True
+ min = -100
+ max = 100
+
+
+class NumberFormatDescriptor(Typed):
+ """
+ Allow direct assignment of format code
+ """
+
+ expected_type = NumFmt
+ allow_none = True
+
+ def __set__(self, instance, value):
+ if isinstance(value, str):
+ value = NumFmt(value)
+ super().__set__(instance, value)
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/error_bar.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/error_bar.py
new file mode 100644
index 00000000..6ae24451
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/error_bar.py
@@ -0,0 +1,62 @@
+# Copyright (c) 2010-2024 openpyxl
+
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ Typed,
+ Float,
+ Set,
+ Alias
+)
+
+from openpyxl.descriptors.excel import ExtensionList
+from openpyxl.descriptors.nested import (
+ NestedNoneSet,
+ NestedSet,
+ NestedBool,
+ NestedFloat,
+)
+
+from .data_source import NumDataSource
+from .shapes import GraphicalProperties
+
+
+class ErrorBars(Serialisable):
+
+ tagname = "errBars"
+
+ errDir = NestedNoneSet(values=(['x', 'y']))
+ direction = Alias("errDir")
+ errBarType = NestedSet(values=(['both', 'minus', 'plus']))
+ style = Alias("errBarType")
+ errValType = NestedSet(values=(['cust', 'fixedVal', 'percentage', 'stdDev', 'stdErr']))
+ size = Alias("errValType")
+ noEndCap = NestedBool(nested=True, allow_none=True)
+ plus = Typed(expected_type=NumDataSource, allow_none=True)
+ minus = Typed(expected_type=NumDataSource, allow_none=True)
+ val = NestedFloat(allow_none=True)
+ spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
+ graphicalProperties = Alias("spPr")
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('errDir','errBarType', 'errValType', 'noEndCap','minus', 'plus', 'val', 'spPr')
+
+
+ def __init__(self,
+ errDir=None,
+ errBarType="both",
+ errValType="fixedVal",
+ noEndCap=None,
+ plus=None,
+ minus=None,
+ val=None,
+ spPr=None,
+ extLst=None,
+ ):
+ self.errDir = errDir
+ self.errBarType = errBarType
+ self.errValType = errValType
+ self.noEndCap = noEndCap
+ self.plus = plus
+ self.minus = minus
+ self.val = val
+ self.spPr = spPr
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/label.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/label.py
new file mode 100644
index 00000000..d6eacb16
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/label.py
@@ -0,0 +1,127 @@
+# Copyright (c) 2010-2024 openpyxl
+
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ Sequence,
+ Alias,
+ Typed
+)
+from openpyxl.descriptors.excel import ExtensionList
+from openpyxl.descriptors.nested import (
+ NestedNoneSet,
+ NestedBool,
+ NestedString,
+ NestedInteger,
+ )
+
+from .shapes import GraphicalProperties
+from .text import RichText
+
+
+class _DataLabelBase(Serialisable):
+
+ numFmt = NestedString(allow_none=True, attribute="formatCode")
+ spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
+ graphicalProperties = Alias('spPr')
+ txPr = Typed(expected_type=RichText, allow_none=True)
+ textProperties = Alias('txPr')
+ dLblPos = NestedNoneSet(values=['bestFit', 'b', 'ctr', 'inBase', 'inEnd',
+ 'l', 'outEnd', 'r', 't'])
+ position = Alias('dLblPos')
+ showLegendKey = NestedBool(allow_none=True)
+ showVal = NestedBool(allow_none=True)
+ showCatName = NestedBool(allow_none=True)
+ showSerName = NestedBool(allow_none=True)
+ showPercent = NestedBool(allow_none=True)
+ showBubbleSize = NestedBool(allow_none=True)
+ showLeaderLines = NestedBool(allow_none=True)
+ separator = NestedString(allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ("numFmt", "spPr", "txPr", "dLblPos", "showLegendKey",
+ "showVal", "showCatName", "showSerName", "showPercent", "showBubbleSize",
+ "showLeaderLines", "separator")
+
+ def __init__(self,
+ numFmt=None,
+ spPr=None,
+ txPr=None,
+ dLblPos=None,
+ showLegendKey=None,
+ showVal=None,
+ showCatName=None,
+ showSerName=None,
+ showPercent=None,
+ showBubbleSize=None,
+ showLeaderLines=None,
+ separator=None,
+ extLst=None,
+ ):
+ self.numFmt = numFmt
+ self.spPr = spPr
+ self.txPr = txPr
+ self.dLblPos = dLblPos
+ self.showLegendKey = showLegendKey
+ self.showVal = showVal
+ self.showCatName = showCatName
+ self.showSerName = showSerName
+ self.showPercent = showPercent
+ self.showBubbleSize = showBubbleSize
+ self.showLeaderLines = showLeaderLines
+ self.separator = separator
+
+
+class DataLabel(_DataLabelBase):
+
+ tagname = "dLbl"
+
+ idx = NestedInteger()
+
+ numFmt = _DataLabelBase.numFmt
+ spPr = _DataLabelBase.spPr
+ txPr = _DataLabelBase.txPr
+ dLblPos = _DataLabelBase.dLblPos
+ showLegendKey = _DataLabelBase.showLegendKey
+ showVal = _DataLabelBase.showVal
+ showCatName = _DataLabelBase.showCatName
+ showSerName = _DataLabelBase.showSerName
+ showPercent = _DataLabelBase.showPercent
+ showBubbleSize = _DataLabelBase.showBubbleSize
+ showLeaderLines = _DataLabelBase.showLeaderLines
+ separator = _DataLabelBase.separator
+ extLst = _DataLabelBase.extLst
+
+ __elements__ = ("idx",) + _DataLabelBase.__elements__
+
+ def __init__(self, idx=0, **kw ):
+ self.idx = idx
+ super().__init__(**kw)
+
+
+class DataLabelList(_DataLabelBase):
+
+ tagname = "dLbls"
+
+ dLbl = Sequence(expected_type=DataLabel, allow_none=True)
+
+ delete = NestedBool(allow_none=True)
+ numFmt = _DataLabelBase.numFmt
+ spPr = _DataLabelBase.spPr
+ txPr = _DataLabelBase.txPr
+ dLblPos = _DataLabelBase.dLblPos
+ showLegendKey = _DataLabelBase.showLegendKey
+ showVal = _DataLabelBase.showVal
+ showCatName = _DataLabelBase.showCatName
+ showSerName = _DataLabelBase.showSerName
+ showPercent = _DataLabelBase.showPercent
+ showBubbleSize = _DataLabelBase.showBubbleSize
+ showLeaderLines = _DataLabelBase.showLeaderLines
+ separator = _DataLabelBase.separator
+ extLst = _DataLabelBase.extLst
+
+ __elements__ = ("delete", "dLbl",) + _DataLabelBase.__elements__
+
+ def __init__(self, dLbl=(), delete=None, **kw):
+ self.dLbl = dLbl
+ self.delete = delete
+ super().__init__(**kw)
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/layout.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/layout.py
new file mode 100644
index 00000000..f2f65530
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/layout.py
@@ -0,0 +1,74 @@
+# Copyright (c) 2010-2024 openpyxl
+
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ NoneSet,
+ Float,
+ Typed,
+ Alias,
+)
+
+from openpyxl.descriptors.excel import ExtensionList
+from openpyxl.descriptors.nested import (
+ NestedNoneSet,
+ NestedSet,
+ NestedMinMax,
+)
+
+class ManualLayout(Serialisable):
+
+ tagname = "manualLayout"
+
+ layoutTarget = NestedNoneSet(values=(['inner', 'outer']))
+ xMode = NestedNoneSet(values=(['edge', 'factor']))
+ yMode = NestedNoneSet(values=(['edge', 'factor']))
+ wMode = NestedSet(values=(['edge', 'factor']))
+ hMode = NestedSet(values=(['edge', 'factor']))
+ x = NestedMinMax(min=-1, max=1, allow_none=True)
+ y = NestedMinMax(min=-1, max=1, allow_none=True)
+ w = NestedMinMax(min=0, max=1, allow_none=True)
+ width = Alias('w')
+ h = NestedMinMax(min=0, max=1, allow_none=True)
+ height = Alias('h')
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('layoutTarget', 'xMode', 'yMode', 'wMode', 'hMode', 'x',
+ 'y', 'w', 'h')
+
+ def __init__(self,
+ layoutTarget=None,
+ xMode=None,
+ yMode=None,
+ wMode="factor",
+ hMode="factor",
+ x=None,
+ y=None,
+ w=None,
+ h=None,
+ extLst=None,
+ ):
+ self.layoutTarget = layoutTarget
+ self.xMode = xMode
+ self.yMode = yMode
+ self.wMode = wMode
+ self.hMode = hMode
+ self.x = x
+ self.y = y
+ self.w = w
+ self.h = h
+
+
+class Layout(Serialisable):
+
+ tagname = "layout"
+
+ manualLayout = Typed(expected_type=ManualLayout, allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('manualLayout',)
+
+ def __init__(self,
+ manualLayout=None,
+ extLst=None,
+ ):
+ self.manualLayout = manualLayout
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/legend.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/legend.py
new file mode 100644
index 00000000..1f7c802b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/legend.py
@@ -0,0 +1,75 @@
+# Copyright (c) 2010-2024 openpyxl
+
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ Typed,
+ Integer,
+ Alias,
+ Sequence,
+)
+from openpyxl.descriptors.excel import ExtensionList
+from openpyxl.descriptors.nested import (
+ NestedBool,
+ NestedSet,
+ NestedInteger
+)
+
+from .layout import Layout
+from .shapes import GraphicalProperties
+from .text import RichText
+
+
+class LegendEntry(Serialisable):
+
+ tagname = "legendEntry"
+
+ idx = NestedInteger()
+ delete = NestedBool()
+ txPr = Typed(expected_type=RichText, allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('idx', 'delete', 'txPr')
+
+ def __init__(self,
+ idx=0,
+ delete=False,
+ txPr=None,
+ extLst=None,
+ ):
+ self.idx = idx
+ self.delete = delete
+ self.txPr = txPr
+
+
+class Legend(Serialisable):
+
+ tagname = "legend"
+
+ legendPos = NestedSet(values=(['b', 'tr', 'l', 'r', 't']))
+ position = Alias('legendPos')
+ legendEntry = Sequence(expected_type=LegendEntry)
+ layout = Typed(expected_type=Layout, allow_none=True)
+ overlay = NestedBool(allow_none=True)
+ spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
+ graphicalProperties = Alias('spPr')
+ txPr = Typed(expected_type=RichText, allow_none=True)
+ textProperties = Alias('txPr')
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('legendPos', 'legendEntry', 'layout', 'overlay', 'spPr', 'txPr',)
+
+ def __init__(self,
+ legendPos="r",
+ legendEntry=(),
+ layout=None,
+ overlay=None,
+ spPr=None,
+ txPr=None,
+ extLst=None,
+ ):
+ self.legendPos = legendPos
+ self.legendEntry = legendEntry
+ self.layout = layout
+ self.overlay = overlay
+ self.spPr = spPr
+ self.txPr = txPr
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/line_chart.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/line_chart.py
new file mode 100644
index 00000000..0aa3ad5b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/line_chart.py
@@ -0,0 +1,129 @@
+#Autogenerated schema
+from openpyxl.descriptors import (
+ Typed,
+ Sequence,
+ Alias,
+ )
+from openpyxl.descriptors.excel import ExtensionList
+from openpyxl.descriptors.nested import (
+ NestedSet,
+ NestedBool,
+)
+
+from ._chart import ChartBase
+from .updown_bars import UpDownBars
+from .descriptors import NestedGapAmount
+from .axis import TextAxis, NumericAxis, SeriesAxis, ChartLines, _BaseAxis
+from .label import DataLabelList
+from .series import Series
+
+
+class _LineChartBase(ChartBase):
+
+ grouping = NestedSet(values=(['percentStacked', 'standard', 'stacked']))
+ varyColors = NestedBool(allow_none=True)
+ ser = Sequence(expected_type=Series, allow_none=True)
+ dLbls = Typed(expected_type=DataLabelList, allow_none=True)
+ dataLabels = Alias("dLbls")
+ dropLines = Typed(expected_type=ChartLines, allow_none=True)
+
+ _series_type = "line"
+
+ __elements__ = ('grouping', 'varyColors', 'ser', 'dLbls', 'dropLines')
+
+ def __init__(self,
+ grouping="standard",
+ varyColors=None,
+ ser=(),
+ dLbls=None,
+ dropLines=None,
+ **kw
+ ):
+ self.grouping = grouping
+ self.varyColors = varyColors
+ self.ser = ser
+ self.dLbls = dLbls
+ self.dropLines = dropLines
+ super().__init__(**kw)
+
+
+class LineChart(_LineChartBase):
+
+ tagname = "lineChart"
+
+ grouping = _LineChartBase.grouping
+ varyColors = _LineChartBase.varyColors
+ ser = _LineChartBase.ser
+ dLbls = _LineChartBase.dLbls
+ dropLines =_LineChartBase.dropLines
+
+ hiLowLines = Typed(expected_type=ChartLines, allow_none=True)
+ upDownBars = Typed(expected_type=UpDownBars, allow_none=True)
+ marker = NestedBool(allow_none=True)
+ smooth = NestedBool(allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ x_axis = Typed(expected_type=_BaseAxis)
+ y_axis = Typed(expected_type=NumericAxis)
+
+ __elements__ = _LineChartBase.__elements__ + ('hiLowLines', 'upDownBars', 'marker', 'smooth', 'axId')
+
+ def __init__(self,
+ hiLowLines=None,
+ upDownBars=None,
+ marker=None,
+ smooth=None,
+ extLst=None,
+ **kw
+ ):
+ self.hiLowLines = hiLowLines
+ self.upDownBars = upDownBars
+ self.marker = marker
+ self.smooth = smooth
+ self.x_axis = TextAxis()
+ self.y_axis = NumericAxis()
+
+ super().__init__(**kw)
+
+
+class LineChart3D(_LineChartBase):
+
+ tagname = "line3DChart"
+
+ grouping = _LineChartBase.grouping
+ varyColors = _LineChartBase.varyColors
+ ser = _LineChartBase.ser
+ dLbls = _LineChartBase.dLbls
+ dropLines =_LineChartBase.dropLines
+
+ gapDepth = NestedGapAmount()
+ hiLowLines = Typed(expected_type=ChartLines, allow_none=True)
+ upDownBars = Typed(expected_type=UpDownBars, allow_none=True)
+ marker = NestedBool(allow_none=True)
+ smooth = NestedBool(allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ x_axis = Typed(expected_type=TextAxis)
+ y_axis = Typed(expected_type=NumericAxis)
+ z_axis = Typed(expected_type=SeriesAxis)
+
+ __elements__ = _LineChartBase.__elements__ + ('gapDepth', 'hiLowLines',
+ 'upDownBars', 'marker', 'smooth', 'axId')
+
+ def __init__(self,
+ gapDepth=None,
+ hiLowLines=None,
+ upDownBars=None,
+ marker=None,
+ smooth=None,
+ **kw
+ ):
+ self.gapDepth = gapDepth
+ self.hiLowLines = hiLowLines
+ self.upDownBars = upDownBars
+ self.marker = marker
+ self.smooth = smooth
+ self.x_axis = TextAxis()
+ self.y_axis = NumericAxis()
+ self.z_axis = SeriesAxis()
+ super(LineChart3D, self).__init__(**kw)
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/marker.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/marker.py
new file mode 100644
index 00000000..61e2641d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/marker.py
@@ -0,0 +1,90 @@
+# Copyright (c) 2010-2024 openpyxl
+
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ Typed,
+ Alias,
+)
+
+from openpyxl.descriptors.excel import(
+ ExtensionList,
+ _explicit_none,
+)
+
+from openpyxl.descriptors.nested import (
+ NestedBool,
+ NestedInteger,
+ NestedMinMax,
+ NestedNoneSet,
+)
+
+from .layout import Layout
+from .picture import PictureOptions
+from .shapes import *
+from .text import *
+from .error_bar import *
+
+
+class Marker(Serialisable):
+
+ tagname = "marker"
+
+ symbol = NestedNoneSet(values=(['circle', 'dash', 'diamond', 'dot', 'picture',
+ 'plus', 'square', 'star', 'triangle', 'x', 'auto']),
+ to_tree=_explicit_none)
+ size = NestedMinMax(min=2, max=72, allow_none=True)
+ spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
+ graphicalProperties = Alias('spPr')
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('symbol', 'size', 'spPr')
+
+ def __init__(self,
+ symbol=None,
+ size=None,
+ spPr=None,
+ extLst=None,
+ ):
+ self.symbol = symbol
+ self.size = size
+ if spPr is None:
+ spPr = GraphicalProperties()
+ self.spPr = spPr
+
+
+class DataPoint(Serialisable):
+
+ tagname = "dPt"
+
+ idx = NestedInteger()
+ invertIfNegative = NestedBool(allow_none=True)
+ marker = Typed(expected_type=Marker, allow_none=True)
+ bubble3D = NestedBool(allow_none=True)
+ explosion = NestedInteger(allow_none=True)
+ spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
+ graphicalProperties = Alias('spPr')
+ pictureOptions = Typed(expected_type=PictureOptions, allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('idx', 'invertIfNegative', 'marker', 'bubble3D',
+ 'explosion', 'spPr', 'pictureOptions')
+
+ def __init__(self,
+ idx=None,
+ invertIfNegative=None,
+ marker=None,
+ bubble3D=None,
+ explosion=None,
+ spPr=None,
+ pictureOptions=None,
+ extLst=None,
+ ):
+ self.idx = idx
+ self.invertIfNegative = invertIfNegative
+ self.marker = marker
+ self.bubble3D = bubble3D
+ self.explosion = explosion
+ if spPr is None:
+ spPr = GraphicalProperties()
+ self.spPr = spPr
+ self.pictureOptions = pictureOptions
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/picture.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/picture.py
new file mode 100644
index 00000000..8c917d8c
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/picture.py
@@ -0,0 +1,35 @@
+# Copyright (c) 2010-2024 openpyxl
+
+from openpyxl.descriptors.serialisable import Serialisable
+
+from openpyxl.descriptors.nested import (
+ NestedBool,
+ NestedFloat,
+ NestedMinMax,
+ NestedNoneSet,
+)
+
+class PictureOptions(Serialisable):
+
+ tagname = "pictureOptions"
+
+ applyToFront = NestedBool(allow_none=True, nested=True)
+ applyToSides = NestedBool(allow_none=True, nested=True)
+ applyToEnd = NestedBool(allow_none=True, nested=True)
+ pictureFormat = NestedNoneSet(values=(['stretch', 'stack', 'stackScale']), nested=True)
+ pictureStackUnit = NestedFloat(allow_none=True, nested=True)
+
+ __elements__ = ('applyToFront', 'applyToSides', 'applyToEnd', 'pictureFormat', 'pictureStackUnit')
+
+ def __init__(self,
+ applyToFront=None,
+ applyToSides=None,
+ applyToEnd=None,
+ pictureFormat=None,
+ pictureStackUnit=None,
+ ):
+ self.applyToFront = applyToFront
+ self.applyToSides = applyToSides
+ self.applyToEnd = applyToEnd
+ self.pictureFormat = pictureFormat
+ self.pictureStackUnit = pictureStackUnit
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/pie_chart.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/pie_chart.py
new file mode 100644
index 00000000..6bb67e1e
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/pie_chart.py
@@ -0,0 +1,177 @@
+#Autogenerated schema
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ Typed,
+ Bool,
+ MinMax,
+ Integer,
+ NoneSet,
+ Float,
+ Alias,
+ Sequence,
+)
+from openpyxl.descriptors.excel import ExtensionList, Percentage
+from openpyxl.descriptors.nested import (
+ NestedBool,
+ NestedMinMax,
+ NestedInteger,
+ NestedFloat,
+ NestedNoneSet,
+ NestedSet,
+)
+from openpyxl.descriptors.sequence import ValueSequence
+
+from ._chart import ChartBase
+from .axis import ChartLines
+from .descriptors import NestedGapAmount
+from .series import Series
+from .label import DataLabelList
+
+
+class _PieChartBase(ChartBase):
+
+ varyColors = NestedBool(allow_none=True)
+ ser = Sequence(expected_type=Series, allow_none=True)
+ dLbls = Typed(expected_type=DataLabelList, allow_none=True)
+ dataLabels = Alias("dLbls")
+
+ _series_type = "pie"
+
+ __elements__ = ('varyColors', 'ser', 'dLbls')
+
+ def __init__(self,
+ varyColors=True,
+ ser=(),
+ dLbls=None,
+ ):
+ self.varyColors = varyColors
+ self.ser = ser
+ self.dLbls = dLbls
+ super().__init__()
+
+
+
+class PieChart(_PieChartBase):
+
+ tagname = "pieChart"
+
+ varyColors = _PieChartBase.varyColors
+ ser = _PieChartBase.ser
+ dLbls = _PieChartBase.dLbls
+
+ firstSliceAng = NestedMinMax(min=0, max=360)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = _PieChartBase.__elements__ + ('firstSliceAng', )
+
+ def __init__(self,
+ firstSliceAng=0,
+ extLst=None,
+ **kw
+ ):
+ self.firstSliceAng = firstSliceAng
+ super().__init__(**kw)
+
+
+class PieChart3D(_PieChartBase):
+
+ tagname = "pie3DChart"
+
+ varyColors = _PieChartBase.varyColors
+ ser = _PieChartBase.ser
+ dLbls = _PieChartBase.dLbls
+
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = _PieChartBase.__elements__
+
+
+class DoughnutChart(_PieChartBase):
+
+ tagname = "doughnutChart"
+
+ varyColors = _PieChartBase.varyColors
+ ser = _PieChartBase.ser
+ dLbls = _PieChartBase.dLbls
+
+ firstSliceAng = NestedMinMax(min=0, max=360)
+ holeSize = NestedMinMax(min=1, max=90, allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = _PieChartBase.__elements__ + ('firstSliceAng', 'holeSize')
+
+ def __init__(self,
+ firstSliceAng=0,
+ holeSize=10,
+ extLst=None,
+ **kw
+ ):
+ self.firstSliceAng = firstSliceAng
+ self.holeSize = holeSize
+ super().__init__(**kw)
+
+
+class CustomSplit(Serialisable):
+
+ tagname = "custSplit"
+
+ secondPiePt = ValueSequence(expected_type=int)
+
+ __elements__ = ('secondPiePt',)
+
+ def __init__(self,
+ secondPiePt=(),
+ ):
+ self.secondPiePt = secondPiePt
+
+
+class ProjectedPieChart(_PieChartBase):
+
+ """
+ From the spec 21.2.2.126
+
+ This element contains the pie of pie or bar of pie series on this
+ chart. Only the first series shall be displayed. The splitType element
+ shall determine whether the splitPos and custSplit elements apply.
+ """
+
+ tagname = "ofPieChart"
+
+ varyColors = _PieChartBase.varyColors
+ ser = _PieChartBase.ser
+ dLbls = _PieChartBase.dLbls
+
+ ofPieType = NestedSet(values=(['pie', 'bar']))
+ type = Alias('ofPieType')
+ gapWidth = NestedGapAmount()
+ splitType = NestedNoneSet(values=(['auto', 'cust', 'percent', 'pos', 'val']))
+ splitPos = NestedFloat(allow_none=True)
+ custSplit = Typed(expected_type=CustomSplit, allow_none=True)
+ secondPieSize = NestedMinMax(min=5, max=200, allow_none=True)
+ serLines = Typed(expected_type=ChartLines, allow_none=True)
+ join_lines = Alias('serLines')
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = _PieChartBase.__elements__ + ('ofPieType', 'gapWidth',
+ 'splitType', 'splitPos', 'custSplit', 'secondPieSize', 'serLines')
+
+ def __init__(self,
+ ofPieType="pie",
+ gapWidth=None,
+ splitType="auto",
+ splitPos=None,
+ custSplit=None,
+ secondPieSize=75,
+ serLines=None,
+ extLst=None,
+ **kw
+ ):
+ self.ofPieType = ofPieType
+ self.gapWidth = gapWidth
+ self.splitType = splitType
+ self.splitPos = splitPos
+ self.custSplit = custSplit
+ self.secondPieSize = secondPieSize
+ if serLines is None:
+ self.serLines = ChartLines()
+ super().__init__(**kw)
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/pivot.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/pivot.py
new file mode 100644
index 00000000..937fd294
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/pivot.py
@@ -0,0 +1,65 @@
+
+# Copyright (c) 2010-2024 openpyxl
+
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ Alias,
+ Typed,
+)
+from openpyxl.descriptors.nested import NestedInteger, NestedText
+from openpyxl.descriptors.excel import ExtensionList
+
+from .label import DataLabel
+from .marker import Marker
+from .shapes import GraphicalProperties
+from .text import RichText
+
+
+class PivotSource(Serialisable):
+
+ tagname = "pivotSource"
+
+ name = NestedText(expected_type=str)
+ fmtId = NestedInteger(expected_type=int)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('name', 'fmtId')
+
+ def __init__(self,
+ name=None,
+ fmtId=None,
+ extLst=None,
+ ):
+ self.name = name
+ self.fmtId = fmtId
+
+
+class PivotFormat(Serialisable):
+
+ tagname = "pivotFmt"
+
+ idx = NestedInteger(nested=True)
+ spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
+ graphicalProperties = Alias("spPr")
+ txPr = Typed(expected_type=RichText, allow_none=True)
+ TextBody = Alias("txPr")
+ marker = Typed(expected_type=Marker, allow_none=True)
+ dLbl = Typed(expected_type=DataLabel, allow_none=True)
+ DataLabel = Alias("dLbl")
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('idx', 'spPr', 'txPr', 'marker', 'dLbl')
+
+ def __init__(self,
+ idx=0,
+ spPr=None,
+ txPr=None,
+ marker=None,
+ dLbl=None,
+ extLst=None,
+ ):
+ self.idx = idx
+ self.spPr = spPr
+ self.txPr = txPr
+ self.marker = marker
+ self.dLbl = dLbl
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/plotarea.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/plotarea.py
new file mode 100644
index 00000000..268bfbc4
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/plotarea.py
@@ -0,0 +1,162 @@
+# Copyright (c) 2010-2024 openpyxl
+
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ Typed,
+ Alias,
+)
+from openpyxl.descriptors.excel import (
+ ExtensionList,
+)
+from openpyxl.descriptors.sequence import (
+ MultiSequence,
+ MultiSequencePart,
+)
+from openpyxl.descriptors.nested import (
+ NestedBool,
+)
+
+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,
+)
+
+
+class DataTable(Serialisable):
+
+ tagname = "dTable"
+
+ showHorzBorder = NestedBool(allow_none=True)
+ showVertBorder = NestedBool(allow_none=True)
+ showOutline = NestedBool(allow_none=True)
+ showKeys = NestedBool(allow_none=True)
+ spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
+ graphicalProperties = Alias('spPr')
+ txPr = Typed(expected_type=RichText, allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('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
+
+
+class PlotArea(Serialisable):
+
+ tagname = "plotArea"
+
+ layout = Typed(expected_type=Layout, allow_none=True)
+ dTable = Typed(expected_type=DataTable, allow_none=True)
+ spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
+ graphicalProperties = Alias("spPr")
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ # at least one chart
+ _charts = MultiSequence()
+ areaChart = MultiSequencePart(expected_type=AreaChart, store="_charts")
+ area3DChart = MultiSequencePart(expected_type=AreaChart3D, store="_charts")
+ lineChart = MultiSequencePart(expected_type=LineChart, store="_charts")
+ line3DChart = MultiSequencePart(expected_type=LineChart3D, store="_charts")
+ stockChart = MultiSequencePart(expected_type=StockChart, store="_charts")
+ radarChart = MultiSequencePart(expected_type=RadarChart, store="_charts")
+ scatterChart = MultiSequencePart(expected_type=ScatterChart, store="_charts")
+ pieChart = MultiSequencePart(expected_type=PieChart, store="_charts")
+ pie3DChart = MultiSequencePart(expected_type=PieChart3D, store="_charts")
+ doughnutChart = MultiSequencePart(expected_type=DoughnutChart, store="_charts")
+ barChart = MultiSequencePart(expected_type=BarChart, store="_charts")
+ bar3DChart = MultiSequencePart(expected_type=BarChart3D, store="_charts")
+ ofPieChart = MultiSequencePart(expected_type=ProjectedPieChart, store="_charts")
+ surfaceChart = MultiSequencePart(expected_type=SurfaceChart, store="_charts")
+ surface3DChart = MultiSequencePart(expected_type=SurfaceChart3D, store="_charts")
+ bubbleChart = MultiSequencePart(expected_type=BubbleChart, store="_charts")
+
+ # axes
+ _axes = MultiSequence()
+ valAx = MultiSequencePart(expected_type=NumericAxis, store="_axes")
+ catAx = MultiSequencePart(expected_type=TextAxis, store="_axes")
+ dateAx = MultiSequencePart(expected_type=DateAxis, store="_axes")
+ serAx = MultiSequencePart(expected_type=SeriesAxis, store="_axes")
+
+ __elements__ = ('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 = _charts
+ self._axes = _axes
+
+
+ def to_tree(self, tagname=None, idx=None, namespace=None):
+ axIds = {ax.axId for ax in self._axes}
+ for chart in self._charts:
+ for id, axis in chart._axes.items():
+ if id not in axIds:
+ setattr(self, axis.tagname, axis)
+ axIds.add(id)
+
+ return super().to_tree(tagname)
+
+
+ @classmethod
+ def from_tree(cls, node):
+ self = super().from_tree(node)
+ axes = dict((axis.axId, axis) for axis in self._axes)
+ for chart in self._charts:
+ if isinstance(chart, (ScatterChart, BubbleChart)):
+ x, y = (axes[axId] for axId in chart.axId)
+ chart.x_axis = x
+ chart.y_axis = y
+ continue
+
+ for axId in chart.axId:
+ axis = axes.get(axId)
+ if axis is None and isinstance(chart, _3DBase):
+ # Series Axis can be optional
+ chart.z_axis = 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
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/print_settings.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/print_settings.py
new file mode 100644
index 00000000..65137310
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/print_settings.py
@@ -0,0 +1,57 @@
+# Copyright (c) 2010-2024 openpyxl
+
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ Float,
+ Typed,
+ Alias,
+)
+
+from openpyxl.worksheet.page import PrintPageSetup
+from openpyxl.worksheet.header_footer import HeaderFooter
+
+
+class PageMargins(Serialisable):
+ """
+ Identical to openpyxl.worksheet.page.Pagemargins but element names are different :-/
+ """
+ tagname = "pageMargins"
+
+ l = Float()
+ left = Alias('l')
+ r = Float()
+ right = Alias('r')
+ t = Float()
+ top = Alias('t')
+ b = Float()
+ bottom = Alias('b')
+ header = Float()
+ footer = Float()
+
+ def __init__(self, l=0.75, r=0.75, t=1, b=1, header=0.5, footer=0.5):
+ self.l = l
+ self.r = r
+ self.t = t
+ self.b = b
+ self.header = header
+ self.footer = footer
+
+
+class PrintSettings(Serialisable):
+
+ tagname = "printSettings"
+
+ headerFooter = Typed(expected_type=HeaderFooter, allow_none=True)
+ pageMargins = Typed(expected_type=PageMargins, allow_none=True)
+ pageSetup = Typed(expected_type=PrintPageSetup, allow_none=True)
+
+ __elements__ = ("headerFooter", "pageMargins", "pageMargins")
+
+ def __init__(self,
+ headerFooter=None,
+ pageMargins=None,
+ pageSetup=None,
+ ):
+ self.headerFooter = headerFooter
+ self.pageMargins = pageMargins
+ self.pageSetup = pageSetup
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/radar_chart.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/radar_chart.py
new file mode 100644
index 00000000..fa3aa0da
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/radar_chart.py
@@ -0,0 +1,55 @@
+# Copyright (c) 2010-2024 openpyxl
+
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ Sequence,
+ Typed,
+ Alias,
+)
+from openpyxl.descriptors.excel import ExtensionList
+from openpyxl.descriptors.nested import (
+ NestedBool,
+ NestedInteger,
+ NestedSet
+)
+
+from ._chart import ChartBase
+from .axis import TextAxis, NumericAxis
+from .series import Series
+from .label import DataLabelList
+
+
+class RadarChart(ChartBase):
+
+ tagname = "radarChart"
+
+ radarStyle = NestedSet(values=(['standard', 'marker', 'filled']))
+ type = Alias("radarStyle")
+ varyColors = NestedBool(nested=True, allow_none=True)
+ ser = Sequence(expected_type=Series, allow_none=True)
+ dLbls = Typed(expected_type=DataLabelList, allow_none=True)
+ dataLabels = Alias("dLbls")
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ _series_type = "radar"
+
+ x_axis = Typed(expected_type=TextAxis)
+ y_axis = Typed(expected_type=NumericAxis)
+
+ __elements__ = ('radarStyle', 'varyColors', 'ser', 'dLbls', 'axId')
+
+ def __init__(self,
+ radarStyle="standard",
+ varyColors=None,
+ ser=(),
+ dLbls=None,
+ extLst=None,
+ **kw
+ ):
+ self.radarStyle = radarStyle
+ self.varyColors = varyColors
+ self.ser = ser
+ self.dLbls = dLbls
+ self.x_axis = TextAxis()
+ self.y_axis = NumericAxis()
+ super().__init__(**kw)
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/reader.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/reader.py
new file mode 100644
index 00000000..0ef719f9
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/reader.py
@@ -0,0 +1,32 @@
+# Copyright (c) 2010-2024 openpyxl
+
+"""
+Read a chart
+"""
+
+def read_chart(chartspace):
+ cs = chartspace
+ plot = cs.chart.plotArea
+
+ chart = plot._charts[0]
+ chart._charts = plot._charts
+
+ chart.title = cs.chart.title
+ chart.display_blanks = cs.chart.dispBlanksAs
+ chart.visible_cells_only = cs.chart.plotVisOnly
+ chart.layout = plot.layout
+ chart.legend = cs.chart.legend
+
+ # 3d attributes
+ chart.floor = cs.chart.floor
+ chart.sideWall = cs.chart.sideWall
+ chart.backWall = cs.chart.backWall
+ chart.pivotSource = cs.pivotSource
+ chart.pivotFormats = cs.chart.pivotFmts
+ chart.idx_base = min((s.idx for s in chart.series), default=0)
+ chart._reindex()
+
+ # Border, fill, etc.
+ chart.graphical_properties = cs.graphical_properties
+
+ return chart
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/reference.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/reference.py
new file mode 100644
index 00000000..dc102791
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/reference.py
@@ -0,0 +1,124 @@
+# Copyright (c) 2010-2024 openpyxl
+
+from itertools import chain
+
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ MinMax,
+ Typed,
+ String,
+ Strict,
+)
+from openpyxl.worksheet.worksheet import Worksheet
+from openpyxl.utils import (
+ get_column_letter,
+ range_to_tuple,
+ quote_sheetname
+)
+
+
+class DummyWorksheet:
+
+
+ def __init__(self, title):
+ self.title = title
+
+
+class Reference(Strict):
+
+ """
+ Normalise cell range references
+ """
+
+ min_row = MinMax(min=1, max=1000000, expected_type=int)
+ max_row = MinMax(min=1, max=1000000, expected_type=int)
+ min_col = MinMax(min=1, max=16384, expected_type=int)
+ max_col = MinMax(min=1, max=16384, expected_type=int)
+ range_string = String(allow_none=True)
+
+ def __init__(self,
+ worksheet=None,
+ min_col=None,
+ min_row=None,
+ max_col=None,
+ max_row=None,
+ range_string=None
+ ):
+ if range_string is not None:
+ sheetname, boundaries = range_to_tuple(range_string)
+ min_col, min_row, max_col, max_row = boundaries
+ worksheet = DummyWorksheet(sheetname)
+
+ self.worksheet = worksheet
+ self.min_col = min_col
+ self.min_row = min_row
+ if max_col is None:
+ max_col = min_col
+ self.max_col = max_col
+ if max_row is None:
+ max_row = min_row
+ self.max_row = max_row
+
+
+ def __repr__(self):
+ return str(self)
+
+
+ def __str__(self):
+ fmt = u"{0}!${1}${2}:${3}${4}"
+ if (self.min_col == self.max_col
+ and self.min_row == self.max_row):
+ fmt = u"{0}!${1}${2}"
+ return fmt.format(self.sheetname,
+ get_column_letter(self.min_col), self.min_row,
+ get_column_letter(self.max_col), self.max_row
+ )
+
+
+ __str__ = __str__
+
+
+
+ def __len__(self):
+ if self.min_row == self.max_row:
+ return 1 + self.max_col - self.min_col
+ return 1 + self.max_row - self.min_row
+
+
+ def __eq__(self, other):
+ return str(self) == str(other)
+
+
+ @property
+ def rows(self):
+ """
+ Return all rows in the range
+ """
+ for row in range(self.min_row, self.max_row+1):
+ yield Reference(self.worksheet, self.min_col, row, self.max_col, row)
+
+
+ @property
+ def cols(self):
+ """
+ Return all columns in the range
+ """
+ for col in range(self.min_col, self.max_col+1):
+ yield Reference(self.worksheet, col, self.min_row, col, self.max_row)
+
+
+ def pop(self):
+ """
+ Return and remove the first cell
+ """
+ cell = "{0}{1}".format(get_column_letter(self.min_col), self.min_row)
+ if self.min_row == self.max_row:
+ self.min_col += 1
+ else:
+ self.min_row += 1
+ return cell
+
+
+ @property
+ def sheetname(self):
+ return quote_sheetname(self.worksheet.title)
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/scatter_chart.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/scatter_chart.py
new file mode 100644
index 00000000..2699239e
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/scatter_chart.py
@@ -0,0 +1,53 @@
+# Copyright (c) 2010-2024 openpyxl
+
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ Typed,
+ Sequence,
+ Alias
+)
+from openpyxl.descriptors.excel import ExtensionList
+from openpyxl.descriptors.nested import (
+ NestedNoneSet,
+ NestedBool,
+)
+
+from ._chart import ChartBase
+from .axis import NumericAxis, TextAxis
+from .series import XYSeries
+from .label import DataLabelList
+
+
+class ScatterChart(ChartBase):
+
+ tagname = "scatterChart"
+
+ scatterStyle = NestedNoneSet(values=(['line', 'lineMarker', 'marker', 'smooth', 'smoothMarker']))
+ varyColors = NestedBool(allow_none=True)
+ ser = Sequence(expected_type=XYSeries, allow_none=True)
+ dLbls = Typed(expected_type=DataLabelList, allow_none=True)
+ dataLabels = Alias("dLbls")
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ x_axis = Typed(expected_type=(NumericAxis, TextAxis))
+ y_axis = Typed(expected_type=NumericAxis)
+
+ _series_type = "scatter"
+
+ __elements__ = ('scatterStyle', 'varyColors', 'ser', 'dLbls', 'axId',)
+
+ def __init__(self,
+ scatterStyle=None,
+ varyColors=None,
+ ser=(),
+ dLbls=None,
+ extLst=None,
+ **kw
+ ):
+ self.scatterStyle = scatterStyle
+ self.varyColors = varyColors
+ self.ser = ser
+ self.dLbls = dLbls
+ self.x_axis = NumericAxis(axId=10, crossAx=20)
+ self.y_axis = NumericAxis(axId=20, crossAx=10)
+ super().__init__(**kw)
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/series.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/series.py
new file mode 100644
index 00000000..f1403a6c
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/series.py
@@ -0,0 +1,197 @@
+# Copyright (c) 2010-2024 openpyxl
+
+
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ Typed,
+ String,
+ Integer,
+ Bool,
+ Alias,
+ Sequence,
+)
+from openpyxl.descriptors.excel import ExtensionList
+from openpyxl.descriptors.nested import (
+ NestedInteger,
+ NestedBool,
+ NestedNoneSet,
+ NestedText,
+)
+
+from .shapes import GraphicalProperties
+from .data_source import (
+ AxDataSource,
+ NumDataSource,
+ NumRef,
+ StrRef,
+)
+from .error_bar import ErrorBars
+from .label import DataLabelList
+from .marker import DataPoint, PictureOptions, Marker
+from .trendline import Trendline
+
+attribute_mapping = {
+ 'area': ('idx', 'order', 'tx', 'spPr', 'pictureOptions', 'dPt', 'dLbls', 'errBars',
+ 'trendline', 'cat', 'val',),
+ 'bar':('idx', 'order','tx', 'spPr', 'invertIfNegative', 'pictureOptions', 'dPt',
+ 'dLbls', 'trendline', 'errBars', 'cat', 'val', 'shape'),
+ 'bubble':('idx','order', 'tx', 'spPr', 'invertIfNegative', 'dPt', 'dLbls',
+ 'trendline', 'errBars', 'xVal', 'yVal', 'bubbleSize', 'bubble3D'),
+ 'line':('idx', 'order', 'tx', 'spPr', 'marker', 'dPt', 'dLbls', 'trendline',
+ 'errBars', 'cat', 'val', 'smooth'),
+ 'pie':('idx', 'order', 'tx', 'spPr', 'explosion', 'dPt', 'dLbls', 'cat', 'val'),
+ 'radar':('idx', 'order', 'tx', 'spPr', 'marker', 'dPt', 'dLbls', 'cat', 'val'),
+ 'scatter':('idx', 'order', 'tx', 'spPr', 'marker', 'dPt', 'dLbls', 'trendline',
+ 'errBars', 'xVal', 'yVal', 'smooth'),
+ 'surface':('idx', 'order', 'tx', 'spPr', 'cat', 'val'),
+ }
+
+
+class SeriesLabel(Serialisable):
+
+ tagname = "tx"
+
+ strRef = Typed(expected_type=StrRef, allow_none=True)
+ v = NestedText(expected_type=str, allow_none=True)
+ value = Alias('v')
+
+ __elements__ = ('strRef', 'v')
+
+ def __init__(self,
+ strRef=None,
+ v=None):
+ self.strRef = strRef
+ self.v = v
+
+
+class Series(Serialisable):
+
+ """
+ Generic series object. Should not be instantiated directly.
+ User the chart.Series factory instead.
+ """
+
+ tagname = "ser"
+
+ idx = NestedInteger()
+ order = NestedInteger()
+ tx = Typed(expected_type=SeriesLabel, allow_none=True)
+ title = Alias('tx')
+ spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
+ graphicalProperties = Alias('spPr')
+
+ # area chart
+ pictureOptions = Typed(expected_type=PictureOptions, allow_none=True)
+ dPt = Sequence(expected_type=DataPoint, allow_none=True)
+ data_points = Alias("dPt")
+ dLbls = Typed(expected_type=DataLabelList, allow_none=True)
+ labels = Alias("dLbls")
+ trendline = Typed(expected_type=Trendline, allow_none=True)
+ errBars = Typed(expected_type=ErrorBars, allow_none=True)
+ cat = Typed(expected_type=AxDataSource, allow_none=True)
+ identifiers = Alias("cat")
+ val = Typed(expected_type=NumDataSource, allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ #bar chart
+ invertIfNegative = NestedBool(allow_none=True)
+ shape = NestedNoneSet(values=(['cone', 'coneToMax', 'box', 'cylinder', 'pyramid', 'pyramidToMax']))
+
+ #bubble chart
+ xVal = Typed(expected_type=AxDataSource, allow_none=True)
+ yVal = Typed(expected_type=NumDataSource, allow_none=True)
+ bubbleSize = Typed(expected_type=NumDataSource, allow_none=True)
+ zVal = Alias("bubbleSize")
+ bubble3D = NestedBool(allow_none=True)
+
+ #line chart
+ marker = Typed(expected_type=Marker, allow_none=True)
+ smooth = NestedBool(allow_none=True)
+
+ #pie chart
+ explosion = NestedInteger(allow_none=True)
+
+ __elements__ = ()
+
+
+ def __init__(self,
+ idx=0,
+ order=0,
+ tx=None,
+ spPr=None,
+ pictureOptions=None,
+ dPt=(),
+ dLbls=None,
+ trendline=None,
+ errBars=None,
+ cat=None,
+ val=None,
+ invertIfNegative=None,
+ shape=None,
+ xVal=None,
+ yVal=None,
+ bubbleSize=None,
+ bubble3D=None,
+ marker=None,
+ smooth=None,
+ explosion=None,
+ extLst=None,
+ ):
+ self.idx = idx
+ self.order = order
+ self.tx = tx
+ if spPr is None:
+ spPr = GraphicalProperties()
+ self.spPr = spPr
+ self.pictureOptions = pictureOptions
+ self.dPt = dPt
+ self.dLbls = dLbls
+ self.trendline = trendline
+ self.errBars = errBars
+ self.cat = cat
+ self.val = val
+ self.invertIfNegative = invertIfNegative
+ self.shape = shape
+ self.xVal = xVal
+ self.yVal = yVal
+ self.bubbleSize = bubbleSize
+ self.bubble3D = bubble3D
+ if marker is None:
+ marker = Marker()
+ self.marker = marker
+ self.smooth = smooth
+ self.explosion = explosion
+
+
+ def to_tree(self, tagname=None, idx=None):
+ """The index can need rebasing"""
+ if idx is not None:
+ if self.order == self.idx:
+ self.order = idx # rebase the order if the index has been rebased
+ self.idx = idx
+ return super().to_tree(tagname)
+
+
+class XYSeries(Series):
+
+ """Dedicated series for charts that have x and y series"""
+
+ idx = Series.idx
+ order = Series.order
+ tx = Series.tx
+ spPr = Series.spPr
+
+ dPt = Series.dPt
+ dLbls = Series.dLbls
+ trendline = Series.trendline
+ errBars = Series.errBars
+ xVal = Series.xVal
+ yVal = Series.yVal
+
+ invertIfNegative = Series.invertIfNegative
+
+ bubbleSize = Series.bubbleSize
+ bubble3D = Series.bubble3D
+
+ marker = Series.marker
+ smooth = Series.smooth
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/series_factory.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/series_factory.py
new file mode 100644
index 00000000..90b368d9
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/series_factory.py
@@ -0,0 +1,41 @@
+# Copyright (c) 2010-2024 openpyxl
+
+from .data_source import NumDataSource, NumRef, AxDataSource
+from .reference import Reference
+from .series import Series, XYSeries, SeriesLabel, StrRef
+from openpyxl.utils import rows_from_range, quote_sheetname
+
+
+def SeriesFactory(values, xvalues=None, zvalues=None, title=None, title_from_data=False):
+ """
+ Convenience Factory for creating chart data series.
+ """
+
+ if not isinstance(values, Reference):
+ values = Reference(range_string=values)
+
+ if title_from_data:
+ cell = values.pop()
+ title = u"{0}!{1}".format(values.sheetname, cell)
+ title = SeriesLabel(strRef=StrRef(title))
+ elif title is not None:
+ title = SeriesLabel(v=title)
+
+ source = NumDataSource(numRef=NumRef(f=values))
+ if xvalues is not None:
+ if not isinstance(xvalues, Reference):
+ xvalues = Reference(range_string=xvalues)
+ series = XYSeries()
+ series.yVal = source
+ series.xVal = AxDataSource(numRef=NumRef(f=xvalues))
+ if zvalues is not None:
+ if not isinstance(zvalues, Reference):
+ zvalues = Reference(range_string=zvalues)
+ series.zVal = NumDataSource(NumRef(f=zvalues))
+ else:
+ series = Series()
+ series.val = source
+
+ if title is not None:
+ series.title = title
+ return series
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/shapes.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/shapes.py
new file mode 100644
index 00000000..7736c1ad
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/shapes.py
@@ -0,0 +1,89 @@
+# Copyright (c) 2010-2024 openpyxl
+
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ Typed,
+ Alias
+)
+from openpyxl.descriptors.nested import (
+ EmptyTag
+)
+from openpyxl.drawing.colors import ColorChoiceDescriptor
+from openpyxl.drawing.fill import *
+from openpyxl.drawing.line import LineProperties
+from openpyxl.drawing.geometry import (
+ Shape3D,
+ Scene3D,
+ Transform2D,
+ CustomGeometry2D,
+ PresetGeometry2D,
+)
+
+
+class GraphicalProperties(Serialisable):
+
+ """
+ Somewhat vaguely 21.2.2.197 says this:
+
+ This element specifies the formatting for the parent chart element. The
+ custGeom, prstGeom, scene3d, and xfrm elements are not supported. The
+ bwMode attribute is not supported.
+
+ This doesn't leave much. And the element is used in different places.
+ """
+
+ tagname = "spPr"
+
+ bwMode = NoneSet(values=(['clr', 'auto', 'gray', 'ltGray', 'invGray',
+ 'grayWhite', 'blackGray', 'blackWhite', 'black', 'white', 'hidden']
+ )
+ )
+
+ xfrm = Typed(expected_type=Transform2D, allow_none=True)
+ transform = Alias('xfrm')
+ custGeom = Typed(expected_type=CustomGeometry2D, allow_none=True) # either or
+ prstGeom = Typed(expected_type=PresetGeometry2D, allow_none=True)
+
+ # fills one of
+ noFill = EmptyTag(namespace=DRAWING_NS)
+ solidFill = ColorChoiceDescriptor()
+ gradFill = Typed(expected_type=GradientFillProperties, allow_none=True)
+ pattFill = Typed(expected_type=PatternFillProperties, allow_none=True)
+
+ ln = Typed(expected_type=LineProperties, allow_none=True)
+ line = Alias('ln')
+ scene3d = Typed(expected_type=Scene3D, allow_none=True)
+ sp3d = Typed(expected_type=Shape3D, allow_none=True)
+ shape3D = Alias('sp3d')
+ extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
+
+ __elements__ = ('xfrm', 'prstGeom', 'noFill', 'solidFill', 'gradFill', 'pattFill',
+ 'ln', 'scene3d', 'sp3d')
+
+ def __init__(self,
+ bwMode=None,
+ xfrm=None,
+ noFill=None,
+ solidFill=None,
+ gradFill=None,
+ pattFill=None,
+ ln=None,
+ scene3d=None,
+ custGeom=None,
+ prstGeom=None,
+ sp3d=None,
+ extLst=None,
+ ):
+ self.bwMode = bwMode
+ self.xfrm = xfrm
+ self.noFill = noFill
+ self.solidFill = solidFill
+ self.gradFill = gradFill
+ self.pattFill = pattFill
+ if ln is None:
+ ln = LineProperties()
+ self.ln = ln
+ self.custGeom = custGeom
+ self.prstGeom = prstGeom
+ self.scene3d = scene3d
+ self.sp3d = sp3d
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/stock_chart.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/stock_chart.py
new file mode 100644
index 00000000..119c7901
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/stock_chart.py
@@ -0,0 +1,54 @@
+# Copyright (c) 2010-2024 openpyxl
+
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ Typed,
+ Sequence,
+ Alias,
+)
+from openpyxl.descriptors.excel import ExtensionList
+
+from ._chart import ChartBase
+from .axis import TextAxis, NumericAxis, ChartLines
+from .updown_bars import UpDownBars
+from .label import DataLabelList
+from .series import Series
+
+
+class StockChart(ChartBase):
+
+ tagname = "stockChart"
+
+ ser = Sequence(expected_type=Series) #min 3, max4
+ dLbls = Typed(expected_type=DataLabelList, allow_none=True)
+ dataLabels = Alias('dLbls')
+ dropLines = Typed(expected_type=ChartLines, allow_none=True)
+ hiLowLines = Typed(expected_type=ChartLines, allow_none=True)
+ upDownBars = Typed(expected_type=UpDownBars, allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ x_axis = Typed(expected_type=TextAxis)
+ y_axis = Typed(expected_type=NumericAxis)
+
+ _series_type = "line"
+
+ __elements__ = ('ser', 'dLbls', 'dropLines', 'hiLowLines', 'upDownBars',
+ 'axId')
+
+ def __init__(self,
+ ser=(),
+ dLbls=None,
+ dropLines=None,
+ hiLowLines=None,
+ upDownBars=None,
+ extLst=None,
+ **kw
+ ):
+ self.ser = ser
+ self.dLbls = dLbls
+ self.dropLines = dropLines
+ self.hiLowLines = hiLowLines
+ self.upDownBars = upDownBars
+ self.x_axis = TextAxis()
+ self.y_axis = NumericAxis()
+ super().__init__(**kw)
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/surface_chart.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/surface_chart.py
new file mode 100644
index 00000000..5f388e14
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/surface_chart.py
@@ -0,0 +1,119 @@
+# Copyright (c) 2010-2024 openpyxl
+
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ Typed,
+ Integer,
+ Bool,
+ Alias,
+ Sequence,
+)
+from openpyxl.descriptors.excel import ExtensionList
+from openpyxl.descriptors.nested import (
+ NestedInteger,
+ NestedBool,
+)
+
+from ._chart import ChartBase
+from ._3d import _3DBase
+from .axis import TextAxis, NumericAxis, SeriesAxis
+from .shapes import GraphicalProperties
+from .series import Series
+
+
+class BandFormat(Serialisable):
+
+ tagname = "bandFmt"
+
+ idx = NestedInteger()
+ spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
+ graphicalProperties = Alias("spPr")
+
+ __elements__ = ('idx', 'spPr')
+
+ def __init__(self,
+ idx=0,
+ spPr=None,
+ ):
+ self.idx = idx
+ self.spPr = spPr
+
+
+class BandFormatList(Serialisable):
+
+ tagname = "bandFmts"
+
+ bandFmt = Sequence(expected_type=BandFormat, allow_none=True)
+
+ __elements__ = ('bandFmt',)
+
+ def __init__(self,
+ bandFmt=(),
+ ):
+ self.bandFmt = bandFmt
+
+
+class _SurfaceChartBase(ChartBase):
+
+ wireframe = NestedBool(allow_none=True)
+ ser = Sequence(expected_type=Series, allow_none=True)
+ bandFmts = Typed(expected_type=BandFormatList, allow_none=True)
+
+ _series_type = "surface"
+
+ __elements__ = ('wireframe', 'ser', 'bandFmts')
+
+ def __init__(self,
+ wireframe=None,
+ ser=(),
+ bandFmts=None,
+ **kw
+ ):
+ self.wireframe = wireframe
+ self.ser = ser
+ self.bandFmts = bandFmts
+ super().__init__(**kw)
+
+
+class SurfaceChart3D(_SurfaceChartBase, _3DBase):
+
+ tagname = "surface3DChart"
+
+ wireframe = _SurfaceChartBase.wireframe
+ ser = _SurfaceChartBase.ser
+ bandFmts = _SurfaceChartBase.bandFmts
+
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ x_axis = Typed(expected_type=TextAxis)
+ y_axis = Typed(expected_type=NumericAxis)
+ z_axis = Typed(expected_type=SeriesAxis)
+
+ __elements__ = _SurfaceChartBase.__elements__ + ('axId',)
+
+ def __init__(self, **kw):
+ self.x_axis = TextAxis()
+ self.y_axis = NumericAxis()
+ self.z_axis = SeriesAxis()
+ super(SurfaceChart3D, self).__init__(**kw)
+
+
+class SurfaceChart(SurfaceChart3D):
+
+ tagname = "surfaceChart"
+
+ wireframe = _SurfaceChartBase.wireframe
+ ser = _SurfaceChartBase.ser
+ bandFmts = _SurfaceChartBase.bandFmts
+
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = SurfaceChart3D.__elements__
+
+ def __init__(self, **kw):
+ super().__init__(**kw)
+ self.y_axis.delete = True
+ self.view3D.x_rotation = 90
+ self.view3D.y_rotation = 0
+ self.view3D.perspective = False
+ self.view3D.right_angle_axes = False
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/text.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/text.py
new file mode 100644
index 00000000..bd034c24
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/text.py
@@ -0,0 +1,78 @@
+# Copyright (c) 2010-2024 openpyxl
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ Typed,
+ Alias,
+ Sequence,
+)
+
+
+from openpyxl.drawing.text import (
+ RichTextProperties,
+ ListStyle,
+ Paragraph,
+)
+
+from .data_source import StrRef
+
+
+class RichText(Serialisable):
+
+ """
+ From the specification: 21.2.2.216
+
+ This element specifies text formatting. The lstStyle element is not supported.
+ """
+
+ tagname = "rich"
+
+ bodyPr = Typed(expected_type=RichTextProperties)
+ properties = Alias("bodyPr")
+ lstStyle = Typed(expected_type=ListStyle, allow_none=True)
+ p = Sequence(expected_type=Paragraph)
+ paragraphs = Alias('p')
+
+ __elements__ = ("bodyPr", "lstStyle", "p")
+
+ def __init__(self,
+ bodyPr=None,
+ lstStyle=None,
+ p=None,
+ ):
+ if bodyPr is None:
+ bodyPr = RichTextProperties()
+ self.bodyPr = bodyPr
+ self.lstStyle = lstStyle
+ if p is None:
+ p = [Paragraph()]
+ self.p = p
+
+
+class Text(Serialisable):
+
+ """
+ The value can be either a cell reference or a text element
+ If both are present then the reference will be used.
+ """
+
+ tagname = "tx"
+
+ strRef = Typed(expected_type=StrRef, allow_none=True)
+ rich = Typed(expected_type=RichText, allow_none=True)
+
+ __elements__ = ("strRef", "rich")
+
+ def __init__(self,
+ strRef=None,
+ rich=None
+ ):
+ self.strRef = strRef
+ if rich is None:
+ rich = RichText()
+ self.rich = rich
+
+
+ def to_tree(self, tagname=None, idx=None, namespace=None):
+ if self.strRef and self.rich:
+ self.rich = None # can only have one
+ return super().to_tree(tagname, idx, namespace)
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/title.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/title.py
new file mode 100644
index 00000000..10f79d7a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/title.py
@@ -0,0 +1,76 @@
+# Copyright (c) 2010-2024 openpyxl
+
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ Typed,
+ Alias,
+)
+
+from openpyxl.descriptors.excel import ExtensionList
+from openpyxl.descriptors.nested import NestedBool
+
+from .text import Text, RichText
+from .layout import Layout
+from .shapes import GraphicalProperties
+
+from openpyxl.drawing.text import (
+ Paragraph,
+ RegularTextRun,
+ LineBreak,
+ ParagraphProperties,
+ CharacterProperties,
+)
+
+
+class Title(Serialisable):
+ tagname = "title"
+
+ tx = Typed(expected_type=Text, allow_none=True)
+ text = Alias('tx')
+ layout = Typed(expected_type=Layout, allow_none=True)
+ overlay = NestedBool(allow_none=True)
+ spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
+ graphicalProperties = Alias('spPr')
+ txPr = Typed(expected_type=RichText, allow_none=True)
+ body = Alias('txPr')
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('tx', 'layout', 'overlay', 'spPr', 'txPr')
+
+ def __init__(self,
+ tx=None,
+ layout=None,
+ overlay=None,
+ spPr=None,
+ txPr=None,
+ extLst=None,
+ ):
+ if tx is None:
+ tx = Text()
+ self.tx = tx
+ self.layout = layout
+ self.overlay = overlay
+ self.spPr = spPr
+ self.txPr = txPr
+
+
+
+def title_maker(text):
+ title = Title()
+ paraprops = ParagraphProperties()
+ paraprops.defRPr = CharacterProperties()
+ paras = [Paragraph(r=[RegularTextRun(t=s)], pPr=paraprops) for s in text.split("\n")]
+
+ title.tx.rich.paragraphs = paras
+ return title
+
+
+class TitleDescriptor(Typed):
+
+ expected_type = Title
+ allow_none = True
+
+ def __set__(self, instance, value):
+ if isinstance(value, str):
+ value = title_maker(value)
+ super().__set__(instance, value)
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/trendline.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/trendline.py
new file mode 100644
index 00000000..bf6d2366
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/trendline.py
@@ -0,0 +1,98 @@
+# Copyright (c) 2010-2024 openpyxl
+
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import (
+ Typed,
+ String,
+ Alias
+)
+from openpyxl.descriptors.excel import ExtensionList
+from openpyxl.descriptors.nested import (
+ NestedBool,
+ NestedInteger,
+ NestedFloat,
+ NestedSet
+)
+
+from .data_source import NumFmt
+from .shapes import GraphicalProperties
+from .text import RichText, Text
+from .layout import Layout
+
+
+class TrendlineLabel(Serialisable):
+
+ tagname = "trendlineLbl"
+
+ layout = Typed(expected_type=Layout, allow_none=True)
+ tx = Typed(expected_type=Text, allow_none=True)
+ numFmt = Typed(expected_type=NumFmt, allow_none=True)
+ spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
+ graphicalProperties = Alias("spPr")
+ txPr = Typed(expected_type=RichText, allow_none=True)
+ textProperties = Alias("txPr")
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('layout', 'tx', 'numFmt', 'spPr', 'txPr')
+
+ def __init__(self,
+ layout=None,
+ tx=None,
+ numFmt=None,
+ spPr=None,
+ txPr=None,
+ extLst=None,
+ ):
+ self.layout = layout
+ self.tx = tx
+ self.numFmt = numFmt
+ self.spPr = spPr
+ self.txPr = txPr
+
+
+class Trendline(Serialisable):
+
+ tagname = "trendline"
+
+ name = String(allow_none=True)
+ spPr = Typed(expected_type=GraphicalProperties, allow_none=True)
+ graphicalProperties = Alias('spPr')
+ trendlineType = NestedSet(values=(['exp', 'linear', 'log', 'movingAvg', 'poly', 'power']))
+ order = NestedInteger(allow_none=True)
+ period = NestedInteger(allow_none=True)
+ forward = NestedFloat(allow_none=True)
+ backward = NestedFloat(allow_none=True)
+ intercept = NestedFloat(allow_none=True)
+ dispRSqr = NestedBool(allow_none=True)
+ dispEq = NestedBool(allow_none=True)
+ trendlineLbl = Typed(expected_type=TrendlineLabel, allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('spPr', 'trendlineType', 'order', 'period', 'forward',
+ 'backward', 'intercept', 'dispRSqr', 'dispEq', 'trendlineLbl')
+
+ def __init__(self,
+ name=None,
+ spPr=None,
+ trendlineType='linear',
+ order=None,
+ period=None,
+ forward=None,
+ backward=None,
+ intercept=None,
+ dispRSqr=None,
+ dispEq=None,
+ trendlineLbl=None,
+ extLst=None,
+ ):
+ self.name = name
+ self.spPr = spPr
+ self.trendlineType = trendlineType
+ self.order = order
+ self.period = period
+ self.forward = forward
+ self.backward = backward
+ self.intercept = intercept
+ self.dispRSqr = dispRSqr
+ self.dispEq = dispEq
+ self.trendlineLbl = trendlineLbl
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/chart/updown_bars.py b/.venv/lib/python3.12/site-packages/openpyxl/chart/updown_bars.py
new file mode 100644
index 00000000..6de7ab8a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/chart/updown_bars.py
@@ -0,0 +1,31 @@
+# Copyright (c) 2010-2024 openpyxl
+
+from openpyxl.descriptors.serialisable import Serialisable
+from openpyxl.descriptors import Typed
+from openpyxl.descriptors.excel import ExtensionList
+
+from .shapes import GraphicalProperties
+from .axis import ChartLines
+from .descriptors import NestedGapAmount
+
+
+class UpDownBars(Serialisable):
+
+ tagname = "upbars"
+
+ gapWidth = NestedGapAmount()
+ upBars = Typed(expected_type=ChartLines, allow_none=True)
+ downBars = Typed(expected_type=ChartLines, allow_none=True)
+ extLst = Typed(expected_type=ExtensionList, allow_none=True)
+
+ __elements__ = ('gapWidth', 'upBars', 'downBars')
+
+ def __init__(self,
+ gapWidth=150,
+ upBars=None,
+ downBars=None,
+ extLst=None,
+ ):
+ self.gapWidth = gapWidth
+ self.upBars = upBars
+ self.downBars = downBars