diff options
Diffstat (limited to '.venv/lib/python3.12/site-packages/pptx/oxml/chart/chart.py')
-rw-r--r-- | .venv/lib/python3.12/site-packages/pptx/oxml/chart/chart.py | 282 |
1 files changed, 282 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/pptx/oxml/chart/chart.py b/.venv/lib/python3.12/site-packages/pptx/oxml/chart/chart.py new file mode 100644 index 00000000..f4cd0dc7 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/pptx/oxml/chart/chart.py @@ -0,0 +1,282 @@ +"""Custom element classes for top-level chart-related XML elements.""" + +from __future__ import annotations + +from typing import cast + +from pptx.oxml import parse_xml +from pptx.oxml.chart.shared import CT_Title +from pptx.oxml.ns import nsdecls, qn +from pptx.oxml.simpletypes import ST_Style, XsdString +from pptx.oxml.text import CT_TextBody +from pptx.oxml.xmlchemy import ( + BaseOxmlElement, + OneAndOnlyOne, + RequiredAttribute, + ZeroOrMore, + ZeroOrOne, +) + + +class CT_Chart(BaseOxmlElement): + """`c:chart` custom element class.""" + + _tag_seq = ( + "c:title", + "c:autoTitleDeleted", + "c:pivotFmts", + "c:view3D", + "c:floor", + "c:sideWall", + "c:backWall", + "c:plotArea", + "c:legend", + "c:plotVisOnly", + "c:dispBlanksAs", + "c:showDLblsOverMax", + "c:extLst", + ) + title = ZeroOrOne("c:title", successors=_tag_seq[1:]) + autoTitleDeleted = ZeroOrOne("c:autoTitleDeleted", successors=_tag_seq[2:]) + plotArea = OneAndOnlyOne("c:plotArea") + legend = ZeroOrOne("c:legend", successors=_tag_seq[9:]) + rId: str = RequiredAttribute("r:id", XsdString) # pyright: ignore[reportAssignmentType] + + @property + def has_legend(self): + """ + True if this chart has a legend defined, False otherwise. + """ + legend = self.legend + if legend is None: + return False + return True + + @has_legend.setter + def has_legend(self, bool_value): + """ + Add, remove, or leave alone the ``<c:legend>`` child element depending + on current state and *bool_value*. If *bool_value* is |True| and no + ``<c:legend>`` element is present, a new default element is added. + When |False|, any existing legend element is removed. + """ + if bool(bool_value) is False: + self._remove_legend() + else: + if self.legend is None: + self._add_legend() + + @staticmethod + def new_chart(rId: str) -> CT_Chart: + """Return a new `c:chart` element.""" + return cast(CT_Chart, parse_xml(f'<c:chart {nsdecls("c")} {nsdecls("r")} r:id="{rId}"/>')) + + def _new_title(self): + return CT_Title.new_title() + + +class CT_ChartSpace(BaseOxmlElement): + """`c:chartSpace` root element of a chart part.""" + + _tag_seq = ( + "c:date1904", + "c:lang", + "c:roundedCorners", + "c:style", + "c:clrMapOvr", + "c:pivotSource", + "c:protection", + "c:chart", + "c:spPr", + "c:txPr", + "c:externalData", + "c:printSettings", + "c:userShapes", + "c:extLst", + ) + date1904 = ZeroOrOne("c:date1904", successors=_tag_seq[1:]) + style = ZeroOrOne("c:style", successors=_tag_seq[4:]) + chart = OneAndOnlyOne("c:chart") + txPr = ZeroOrOne("c:txPr", successors=_tag_seq[10:]) + externalData = ZeroOrOne("c:externalData", successors=_tag_seq[11:]) + del _tag_seq + + @property + def catAx_lst(self): + return self.chart.plotArea.catAx_lst + + @property + def date_1904(self): + """ + Return |True| if the `c:date1904` child element resolves truthy, + |False| otherwise. This value indicates whether date number values + are based on the 1900 or 1904 epoch. + """ + date1904 = self.date1904 + if date1904 is None: + return False + return date1904.val + + @property + def dateAx_lst(self): + return self.xpath("c:chart/c:plotArea/c:dateAx") + + def get_or_add_title(self): + """Return the `c:title` grandchild, newly created if not present.""" + return self.chart.get_or_add_title() + + @property + def plotArea(self): + """ + Return the required `c:chartSpace/c:chart/c:plotArea` grandchild + element. + """ + return self.chart.plotArea + + @property + def valAx_lst(self): + return self.chart.plotArea.valAx_lst + + @property + def xlsx_part_rId(self): + """ + The string in the required ``r:id`` attribute of the + `<c:externalData>` child, or |None| if no externalData element is + present. + """ + externalData = self.externalData + if externalData is None: + return None + return externalData.rId + + def _add_externalData(self): + """ + Always add a ``<c:autoUpdate val="0"/>`` child so auto-updating + behavior is off by default. + """ + externalData = self._new_externalData() + externalData._add_autoUpdate(val=False) + self._insert_externalData(externalData) + return externalData + + def _new_txPr(self): + return CT_TextBody.new_txPr() + + +class CT_ExternalData(BaseOxmlElement): + """ + `<c:externalData>` element, defining link to embedded Excel package part + containing the chart data. + """ + + autoUpdate = ZeroOrOne("c:autoUpdate") + rId = RequiredAttribute("r:id", XsdString) + + +class CT_PlotArea(BaseOxmlElement): + """ + ``<c:plotArea>`` element. + """ + + catAx = ZeroOrMore("c:catAx") + valAx = ZeroOrMore("c:valAx") + + def iter_sers(self): + """ + Generate each of the `c:ser` elements in this chart, ordered first by + the document order of the containing xChart element, then by their + ordering within the xChart element (not necessarily document order). + """ + for xChart in self.iter_xCharts(): + for ser in xChart.iter_sers(): + yield ser + + def iter_xCharts(self): + """ + Generate each xChart child element in document. + """ + plot_tags = ( + qn("c:area3DChart"), + qn("c:areaChart"), + qn("c:bar3DChart"), + qn("c:barChart"), + qn("c:bubbleChart"), + qn("c:doughnutChart"), + qn("c:line3DChart"), + qn("c:lineChart"), + qn("c:ofPieChart"), + qn("c:pie3DChart"), + qn("c:pieChart"), + qn("c:radarChart"), + qn("c:scatterChart"), + qn("c:stockChart"), + qn("c:surface3DChart"), + qn("c:surfaceChart"), + ) + + for child in self.iterchildren(): + if child.tag not in plot_tags: + continue + yield child + + @property + def last_ser(self): + """ + Return the last `<c:ser>` element in the last xChart element, based + on series order (not necessarily the same element as document order). + """ + last_xChart = self.xCharts[-1] + sers = last_xChart.sers + if not sers: + return None + return sers[-1] + + @property + def next_idx(self): + """ + Return the next available `c:ser/c:idx` value within the scope of + this chart, the maximum idx value found on existing series, + incremented by one. + """ + idx_vals = [s.idx.val for s in self.sers] + if not idx_vals: + return 0 + return max(idx_vals) + 1 + + @property + def next_order(self): + """ + Return the next available `c:ser/c:order` value within the scope of + this chart, the maximum order value found on existing series, + incremented by one. + """ + order_vals = [s.order.val for s in self.sers] + if not order_vals: + return 0 + return max(order_vals) + 1 + + @property + def sers(self): + """ + Return a sequence containing all the `c:ser` elements in this chart, + ordered first by the document order of the containing xChart element, + then by their ordering within the xChart element (not necessarily + document order). + """ + return tuple(self.iter_sers()) + + @property + def xCharts(self): + """ + Return a sequence containing all the `c:{x}Chart` elements in this + chart, in document order. + """ + return tuple(self.iter_xCharts()) + + +class CT_Style(BaseOxmlElement): + """ + ``<c:style>`` element; defines the chart style. + """ + + val = RequiredAttribute("val", ST_Style) |