ps-python-pptx 1.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pptx/__init__.py +84 -0
- pptx/action.py +270 -0
- pptx/api.py +49 -0
- pptx/chart/__init__.py +0 -0
- pptx/chart/axis.py +523 -0
- pptx/chart/category.py +200 -0
- pptx/chart/chart.py +280 -0
- pptx/chart/data.py +864 -0
- pptx/chart/datalabel.py +288 -0
- pptx/chart/legend.py +79 -0
- pptx/chart/marker.py +70 -0
- pptx/chart/plot.py +412 -0
- pptx/chart/point.py +101 -0
- pptx/chart/series.py +258 -0
- pptx/chart/xlsx.py +272 -0
- pptx/chart/xmlwriter.py +1840 -0
- pptx/dml/__init__.py +0 -0
- pptx/dml/chtfmt.py +40 -0
- pptx/dml/color.py +301 -0
- pptx/dml/effect.py +41 -0
- pptx/dml/fill.py +468 -0
- pptx/dml/line.py +100 -0
- pptx/enum/__init__.py +0 -0
- pptx/enum/action.py +71 -0
- pptx/enum/base.py +175 -0
- pptx/enum/chart.py +492 -0
- pptx/enum/dml.py +405 -0
- pptx/enum/lang.py +685 -0
- pptx/enum/shapes.py +1029 -0
- pptx/enum/text.py +371 -0
- pptx/exc.py +23 -0
- pptx/media.py +197 -0
- pptx/opc/__init__.py +0 -0
- pptx/opc/constants.py +331 -0
- pptx/opc/oxml.py +188 -0
- pptx/opc/package.py +762 -0
- pptx/opc/packuri.py +109 -0
- pptx/opc/serialized.py +296 -0
- pptx/opc/shared.py +20 -0
- pptx/opc/spec.py +44 -0
- pptx/oxml/__init__.py +492 -0
- pptx/oxml/action.py +53 -0
- pptx/oxml/chart/__init__.py +0 -0
- pptx/oxml/chart/axis.py +297 -0
- pptx/oxml/chart/chart.py +282 -0
- pptx/oxml/chart/datalabel.py +252 -0
- pptx/oxml/chart/legend.py +72 -0
- pptx/oxml/chart/marker.py +61 -0
- pptx/oxml/chart/plot.py +345 -0
- pptx/oxml/chart/series.py +254 -0
- pptx/oxml/chart/shared.py +219 -0
- pptx/oxml/coreprops.py +288 -0
- pptx/oxml/dml/__init__.py +0 -0
- pptx/oxml/dml/color.py +111 -0
- pptx/oxml/dml/fill.py +197 -0
- pptx/oxml/dml/line.py +12 -0
- pptx/oxml/ns.py +129 -0
- pptx/oxml/presentation.py +130 -0
- pptx/oxml/shapes/__init__.py +19 -0
- pptx/oxml/shapes/autoshape.py +455 -0
- pptx/oxml/shapes/connector.py +107 -0
- pptx/oxml/shapes/graphfrm.py +342 -0
- pptx/oxml/shapes/groupshape.py +280 -0
- pptx/oxml/shapes/picture.py +270 -0
- pptx/oxml/shapes/shared.py +523 -0
- pptx/oxml/simpletypes.py +740 -0
- pptx/oxml/slide.py +347 -0
- pptx/oxml/table.py +588 -0
- pptx/oxml/text.py +748 -0
- pptx/oxml/theme.py +29 -0
- pptx/oxml/xmlchemy.py +717 -0
- pptx/package.py +222 -0
- pptx/parts/__init__.py +0 -0
- pptx/parts/chart.py +95 -0
- pptx/parts/coreprops.py +167 -0
- pptx/parts/embeddedpackage.py +93 -0
- pptx/parts/image.py +275 -0
- pptx/parts/media.py +37 -0
- pptx/parts/presentation.py +126 -0
- pptx/parts/slide.py +297 -0
- pptx/parts/theme.py +13 -0
- pptx/presentation.py +113 -0
- pptx/py.typed +0 -0
- pptx/shapes/__init__.py +26 -0
- pptx/shapes/autoshape.py +355 -0
- pptx/shapes/base.py +293 -0
- pptx/shapes/connector.py +297 -0
- pptx/shapes/freeform.py +337 -0
- pptx/shapes/graphfrm.py +166 -0
- pptx/shapes/group.py +69 -0
- pptx/shapes/picture.py +203 -0
- pptx/shapes/placeholder.py +407 -0
- pptx/shapes/shapetree.py +1190 -0
- pptx/shared.py +82 -0
- pptx/slide.py +577 -0
- pptx/spec.py +632 -0
- pptx/table.py +520 -0
- pptx/templates/default.pptx +0 -0
- pptx/templates/docx-icon.emf +0 -0
- pptx/templates/generic-icon.emf +0 -0
- pptx/templates/notes.xml +23 -0
- pptx/templates/notesMaster.xml +352 -0
- pptx/templates/pptx-icon.emf +0 -0
- pptx/templates/theme.xml +321 -0
- pptx/templates/xlsx-icon.emf +0 -0
- pptx/text/__init__.py +0 -0
- pptx/text/fonts.py +399 -0
- pptx/text/layout.py +325 -0
- pptx/text/text.py +770 -0
- pptx/theme.py +135 -0
- pptx/types.py +36 -0
- pptx/util.py +284 -0
- ps_python_pptx-1.1.0.dist-info/METADATA +75 -0
- ps_python_pptx-1.1.0.dist-info/RECORD +117 -0
- ps_python_pptx-1.1.0.dist-info/WHEEL +5 -0
- ps_python_pptx-1.1.0.dist-info/licenses/LICENSE +20 -0
- ps_python_pptx-1.1.0.dist-info/top_level.txt +1 -0
pptx/chart/category.py
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"""Category-related objects.
|
|
2
|
+
|
|
3
|
+
The |category.Categories| object is returned by ``Plot.categories`` and contains zero or
|
|
4
|
+
more |category.Category| objects, each representing one of the category labels
|
|
5
|
+
associated with the plot. Categories can be hierarchical, so there are members allowing
|
|
6
|
+
discovery of the depth of that hierarchy and providing means to navigate it.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from collections.abc import Sequence
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Categories(Sequence):
|
|
15
|
+
"""
|
|
16
|
+
A sequence of |category.Category| objects, each representing a category
|
|
17
|
+
label on the chart. Provides properties for dealing with hierarchical
|
|
18
|
+
categories.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(self, xChart):
|
|
22
|
+
super(Categories, self).__init__()
|
|
23
|
+
self._xChart = xChart
|
|
24
|
+
|
|
25
|
+
def __getitem__(self, idx):
|
|
26
|
+
pt = self._xChart.cat_pts[idx]
|
|
27
|
+
return Category(pt, idx)
|
|
28
|
+
|
|
29
|
+
def __iter__(self):
|
|
30
|
+
cat_pts = self._xChart.cat_pts
|
|
31
|
+
for idx, pt in enumerate(cat_pts):
|
|
32
|
+
yield Category(pt, idx)
|
|
33
|
+
|
|
34
|
+
def __len__(self):
|
|
35
|
+
# a category can be "null", meaning the Excel cell for it is empty.
|
|
36
|
+
# In this case, there is no c:pt element for it. The "empty" category
|
|
37
|
+
# will, however, be accounted for in c:cat//c:ptCount/@val, which
|
|
38
|
+
# reflects the true length of the categories collection.
|
|
39
|
+
return self._xChart.cat_pt_count
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def depth(self):
|
|
43
|
+
"""
|
|
44
|
+
Return an integer representing the number of hierarchical levels in
|
|
45
|
+
this category collection. Returns 1 for non-hierarchical categories
|
|
46
|
+
and 0 if no categories are present (generally meaning no series are
|
|
47
|
+
present).
|
|
48
|
+
"""
|
|
49
|
+
cat = self._xChart.cat
|
|
50
|
+
if cat is None:
|
|
51
|
+
return 0
|
|
52
|
+
if cat.multiLvlStrRef is None:
|
|
53
|
+
return 1
|
|
54
|
+
return len(cat.lvls)
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def flattened_labels(self):
|
|
58
|
+
"""
|
|
59
|
+
Return a sequence of tuples, each containing the flattened hierarchy
|
|
60
|
+
of category labels for a leaf category. Each tuple is in parent ->
|
|
61
|
+
child order, e.g. ``('US', 'CA', 'San Francisco')``, with the leaf
|
|
62
|
+
category appearing last. If this categories collection is
|
|
63
|
+
non-hierarchical, each tuple will contain only a leaf category label.
|
|
64
|
+
If the plot has no series (and therefore no categories), an empty
|
|
65
|
+
tuple is returned.
|
|
66
|
+
"""
|
|
67
|
+
cat = self._xChart.cat
|
|
68
|
+
if cat is None:
|
|
69
|
+
return ()
|
|
70
|
+
|
|
71
|
+
if cat.multiLvlStrRef is None:
|
|
72
|
+
return tuple([(category.label,) for category in self])
|
|
73
|
+
|
|
74
|
+
return tuple(
|
|
75
|
+
[
|
|
76
|
+
tuple([category.label for category in reversed(flat_cat)])
|
|
77
|
+
for flat_cat in self._iter_flattened_categories()
|
|
78
|
+
]
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def levels(self):
|
|
83
|
+
"""
|
|
84
|
+
Return a sequence of |CategoryLevel| objects representing the
|
|
85
|
+
hierarchy of this category collection. The sequence is empty when the
|
|
86
|
+
category collection is not hierarchical, that is, contains only
|
|
87
|
+
leaf-level categories. The levels are ordered from the leaf level to
|
|
88
|
+
the root level; so the first level will contain the same categories
|
|
89
|
+
as this category collection.
|
|
90
|
+
"""
|
|
91
|
+
cat = self._xChart.cat
|
|
92
|
+
if cat is None:
|
|
93
|
+
return []
|
|
94
|
+
return [CategoryLevel(lvl) for lvl in cat.lvls]
|
|
95
|
+
|
|
96
|
+
def _iter_flattened_categories(self):
|
|
97
|
+
"""
|
|
98
|
+
Generate a ``tuple`` object for each leaf category in this
|
|
99
|
+
collection, containing the leaf category followed by its "parent"
|
|
100
|
+
categories, e.g. ``('San Francisco', 'CA', 'USA'). Each tuple will be
|
|
101
|
+
the same length as the number of levels (excepting certain edge
|
|
102
|
+
cases which I believe always indicate a chart construction error).
|
|
103
|
+
"""
|
|
104
|
+
levels = self.levels
|
|
105
|
+
if not levels:
|
|
106
|
+
return
|
|
107
|
+
leaf_level, remaining_levels = levels[0], levels[1:]
|
|
108
|
+
for category in leaf_level:
|
|
109
|
+
yield self._parentage((category,), remaining_levels)
|
|
110
|
+
|
|
111
|
+
def _parentage(self, categories, levels):
|
|
112
|
+
"""
|
|
113
|
+
Return a tuple formed by recursively concatenating *categories* with
|
|
114
|
+
its next ancestor from *levels*. The idx value of the first category
|
|
115
|
+
in *categories* determines parentage in all levels. The returned
|
|
116
|
+
sequence is in child -> parent order. A parent category is the
|
|
117
|
+
Category object in a next level having the maximum idx value not
|
|
118
|
+
exceeding that of the leaf category.
|
|
119
|
+
"""
|
|
120
|
+
# exhausting levels is the expected recursion termination condition
|
|
121
|
+
if not levels:
|
|
122
|
+
return tuple(categories)
|
|
123
|
+
|
|
124
|
+
# guard against edge case where next level is present but empty. That
|
|
125
|
+
# situation is not prohibited for some reason.
|
|
126
|
+
if not levels[0]:
|
|
127
|
+
return tuple(categories)
|
|
128
|
+
|
|
129
|
+
parent_level, remaining_levels = levels[0], levels[1:]
|
|
130
|
+
leaf_node = categories[0]
|
|
131
|
+
|
|
132
|
+
# Make the first parent the default. A possible edge case is where no
|
|
133
|
+
# parent is defined for one or more leading values, e.g. idx > 0 for
|
|
134
|
+
# the first parent.
|
|
135
|
+
parent = parent_level[0]
|
|
136
|
+
for category in parent_level:
|
|
137
|
+
if category.idx > leaf_node.idx:
|
|
138
|
+
break
|
|
139
|
+
parent = category
|
|
140
|
+
|
|
141
|
+
extended_categories = tuple(categories) + (parent,)
|
|
142
|
+
return self._parentage(extended_categories, remaining_levels)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class Category(str):
|
|
146
|
+
"""
|
|
147
|
+
An extension of `str` that provides the category label as its string
|
|
148
|
+
value, and additional attributes representing other aspects of the
|
|
149
|
+
category.
|
|
150
|
+
"""
|
|
151
|
+
|
|
152
|
+
def __new__(cls, pt, *args):
|
|
153
|
+
category_label = "" if pt is None else pt.v.text
|
|
154
|
+
return str.__new__(cls, category_label)
|
|
155
|
+
|
|
156
|
+
def __init__(self, pt, idx=None):
|
|
157
|
+
"""
|
|
158
|
+
*idx* is a required attribute of a c:pt element, but must be
|
|
159
|
+
specified when pt is None, as when a "placeholder" category is
|
|
160
|
+
created to represent a missing c:pt element.
|
|
161
|
+
"""
|
|
162
|
+
self._element = self._pt = pt
|
|
163
|
+
self._idx = idx
|
|
164
|
+
|
|
165
|
+
@property
|
|
166
|
+
def idx(self):
|
|
167
|
+
"""
|
|
168
|
+
Return an integer representing the index reference of this category.
|
|
169
|
+
For a leaf node, the index identifies the category. For a parent (or
|
|
170
|
+
other ancestor) category, the index specifies the first leaf category
|
|
171
|
+
that ancestor encloses.
|
|
172
|
+
"""
|
|
173
|
+
if self._pt is None:
|
|
174
|
+
return self._idx
|
|
175
|
+
return self._pt.idx
|
|
176
|
+
|
|
177
|
+
@property
|
|
178
|
+
def label(self):
|
|
179
|
+
"""
|
|
180
|
+
Return the label of this category as a string.
|
|
181
|
+
"""
|
|
182
|
+
return str(self)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
class CategoryLevel(Sequence):
|
|
186
|
+
"""
|
|
187
|
+
A sequence of |category.Category| objects representing a single level in
|
|
188
|
+
a hierarchical category collection. This object is only used when the
|
|
189
|
+
categories are hierarchical, meaning they have more than one level and
|
|
190
|
+
higher level categories group those at lower levels.
|
|
191
|
+
"""
|
|
192
|
+
|
|
193
|
+
def __init__(self, lvl):
|
|
194
|
+
self._element = self._lvl = lvl
|
|
195
|
+
|
|
196
|
+
def __getitem__(self, offset):
|
|
197
|
+
return Category(self._lvl.pt_lst[offset])
|
|
198
|
+
|
|
199
|
+
def __len__(self):
|
|
200
|
+
return len(self._lvl.pt_lst)
|
pptx/chart/chart.py
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
"""Chart-related objects such as Chart and ChartTitle."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Sequence
|
|
6
|
+
|
|
7
|
+
from pptx.chart.axis import CategoryAxis, DateAxis, ValueAxis
|
|
8
|
+
from pptx.chart.legend import Legend
|
|
9
|
+
from pptx.chart.plot import PlotFactory, PlotTypeInspector
|
|
10
|
+
from pptx.chart.series import SeriesCollection
|
|
11
|
+
from pptx.chart.xmlwriter import SeriesXmlRewriterFactory
|
|
12
|
+
from pptx.dml.chtfmt import ChartFormat
|
|
13
|
+
from pptx.shared import ElementProxy, PartElementProxy
|
|
14
|
+
from pptx.text.text import Font, TextFrame
|
|
15
|
+
from pptx.util import lazyproperty
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Chart(PartElementProxy):
|
|
19
|
+
"""A chart object."""
|
|
20
|
+
|
|
21
|
+
def __init__(self, chartSpace, chart_part):
|
|
22
|
+
super(Chart, self).__init__(chartSpace, chart_part)
|
|
23
|
+
self._chartSpace = chartSpace
|
|
24
|
+
|
|
25
|
+
@property
|
|
26
|
+
def category_axis(self):
|
|
27
|
+
"""
|
|
28
|
+
The category axis of this chart. In the case of an XY or Bubble
|
|
29
|
+
chart, this is the X axis. Raises |ValueError| if no category
|
|
30
|
+
axis is defined (as is the case for a pie chart, for example).
|
|
31
|
+
"""
|
|
32
|
+
catAx_lst = self._chartSpace.catAx_lst
|
|
33
|
+
if catAx_lst:
|
|
34
|
+
return CategoryAxis(catAx_lst[0])
|
|
35
|
+
|
|
36
|
+
dateAx_lst = self._chartSpace.dateAx_lst
|
|
37
|
+
if dateAx_lst:
|
|
38
|
+
return DateAxis(dateAx_lst[0])
|
|
39
|
+
|
|
40
|
+
valAx_lst = self._chartSpace.valAx_lst
|
|
41
|
+
if valAx_lst:
|
|
42
|
+
return ValueAxis(valAx_lst[0])
|
|
43
|
+
|
|
44
|
+
raise ValueError("chart has no category axis")
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def chart_style(self):
|
|
48
|
+
"""
|
|
49
|
+
Read/write integer index of chart style used to format this chart.
|
|
50
|
+
Range is from 1 to 48. Value is |None| if no explicit style has been
|
|
51
|
+
assigned, in which case the default chart style is used. Assigning
|
|
52
|
+
|None| causes any explicit setting to be removed. The integer index
|
|
53
|
+
corresponds to the style's position in the chart style gallery in the
|
|
54
|
+
PowerPoint UI.
|
|
55
|
+
"""
|
|
56
|
+
style = self._chartSpace.style
|
|
57
|
+
if style is None:
|
|
58
|
+
return None
|
|
59
|
+
return style.val
|
|
60
|
+
|
|
61
|
+
@chart_style.setter
|
|
62
|
+
def chart_style(self, value):
|
|
63
|
+
self._chartSpace._remove_style()
|
|
64
|
+
if value is None:
|
|
65
|
+
return
|
|
66
|
+
self._chartSpace._add_style(val=value)
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def chart_title(self):
|
|
70
|
+
"""A |ChartTitle| object providing access to title properties.
|
|
71
|
+
|
|
72
|
+
Calling this property is destructive in the sense it adds a chart
|
|
73
|
+
title element (`c:title`) to the chart XML if one is not already
|
|
74
|
+
present. Use :attr:`has_title` to test for presence of a chart title
|
|
75
|
+
non-destructively.
|
|
76
|
+
"""
|
|
77
|
+
return ChartTitle(self._element.get_or_add_title())
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def chart_type(self):
|
|
81
|
+
"""Member of :ref:`XlChartType` enumeration specifying type of this chart.
|
|
82
|
+
|
|
83
|
+
If the chart has two plots, for example, a line plot overlayed on a bar plot,
|
|
84
|
+
the type reported is for the first (back-most) plot. Read-only.
|
|
85
|
+
"""
|
|
86
|
+
first_plot = self.plots[0]
|
|
87
|
+
return PlotTypeInspector.chart_type(first_plot)
|
|
88
|
+
|
|
89
|
+
@lazyproperty
|
|
90
|
+
def font(self):
|
|
91
|
+
"""Font object controlling text format defaults for this chart."""
|
|
92
|
+
defRPr = self._chartSpace.get_or_add_txPr().p_lst[0].get_or_add_pPr().get_or_add_defRPr()
|
|
93
|
+
return Font(defRPr)
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def has_legend(self):
|
|
97
|
+
"""
|
|
98
|
+
Read/write boolean, |True| if the chart has a legend. Assigning
|
|
99
|
+
|True| causes a legend to be added to the chart if it doesn't already
|
|
100
|
+
have one. Assigning False removes any existing legend definition
|
|
101
|
+
along with any existing legend settings.
|
|
102
|
+
"""
|
|
103
|
+
return self._chartSpace.chart.has_legend
|
|
104
|
+
|
|
105
|
+
@has_legend.setter
|
|
106
|
+
def has_legend(self, value):
|
|
107
|
+
self._chartSpace.chart.has_legend = bool(value)
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def has_title(self):
|
|
111
|
+
"""Read/write boolean, specifying whether this chart has a title.
|
|
112
|
+
|
|
113
|
+
Assigning |True| causes a title to be added if not already present.
|
|
114
|
+
Assigning |False| removes any existing title along with its text and
|
|
115
|
+
settings.
|
|
116
|
+
"""
|
|
117
|
+
title = self._chartSpace.chart.title
|
|
118
|
+
if title is None:
|
|
119
|
+
return False
|
|
120
|
+
return True
|
|
121
|
+
|
|
122
|
+
@has_title.setter
|
|
123
|
+
def has_title(self, value):
|
|
124
|
+
chart = self._chartSpace.chart
|
|
125
|
+
if bool(value) is False:
|
|
126
|
+
chart._remove_title()
|
|
127
|
+
autoTitleDeleted = chart.get_or_add_autoTitleDeleted()
|
|
128
|
+
autoTitleDeleted.val = True
|
|
129
|
+
return
|
|
130
|
+
chart.get_or_add_title()
|
|
131
|
+
|
|
132
|
+
@property
|
|
133
|
+
def legend(self):
|
|
134
|
+
"""
|
|
135
|
+
A |Legend| object providing access to the properties of the legend
|
|
136
|
+
for this chart.
|
|
137
|
+
"""
|
|
138
|
+
legend_elm = self._chartSpace.chart.legend
|
|
139
|
+
if legend_elm is None:
|
|
140
|
+
return None
|
|
141
|
+
return Legend(legend_elm)
|
|
142
|
+
|
|
143
|
+
@lazyproperty
|
|
144
|
+
def plots(self):
|
|
145
|
+
"""
|
|
146
|
+
The sequence of plots in this chart. A plot, called a *chart group*
|
|
147
|
+
in the Microsoft API, is a distinct sequence of one or more series
|
|
148
|
+
depicted in a particular charting type. For example, a chart having
|
|
149
|
+
a series plotted as a line overlaid on three series plotted as
|
|
150
|
+
columns would have two plots; the first corresponding to the three
|
|
151
|
+
column series and the second to the line series. Plots are sequenced
|
|
152
|
+
in the order drawn, i.e. back-most to front-most. Supports *len()*,
|
|
153
|
+
membership (e.g. ``p in plots``), iteration, slicing, and indexed
|
|
154
|
+
access (e.g. ``plot = plots[i]``).
|
|
155
|
+
"""
|
|
156
|
+
plotArea = self._chartSpace.chart.plotArea
|
|
157
|
+
return _Plots(plotArea, self)
|
|
158
|
+
|
|
159
|
+
def replace_data(self, chart_data):
|
|
160
|
+
"""
|
|
161
|
+
Use the categories and series values in the |ChartData| object
|
|
162
|
+
*chart_data* to replace those in the XML and Excel worksheet for this
|
|
163
|
+
chart.
|
|
164
|
+
"""
|
|
165
|
+
rewriter = SeriesXmlRewriterFactory(self.chart_type, chart_data)
|
|
166
|
+
rewriter.replace_series_data(self._chartSpace)
|
|
167
|
+
self._workbook.update_from_xlsx_blob(chart_data.xlsx_blob)
|
|
168
|
+
|
|
169
|
+
@lazyproperty
|
|
170
|
+
def series(self):
|
|
171
|
+
"""
|
|
172
|
+
A |SeriesCollection| object containing all the series in this
|
|
173
|
+
chart. When the chart has multiple plots, all the series for the
|
|
174
|
+
first plot appear before all those for the second, and so on. Series
|
|
175
|
+
within a plot have an explicit ordering and appear in that sequence.
|
|
176
|
+
"""
|
|
177
|
+
return SeriesCollection(self._chartSpace.plotArea)
|
|
178
|
+
|
|
179
|
+
@property
|
|
180
|
+
def value_axis(self):
|
|
181
|
+
"""
|
|
182
|
+
The |ValueAxis| object providing access to properties of the value
|
|
183
|
+
axis of this chart. Raises |ValueError| if the chart has no value
|
|
184
|
+
axis.
|
|
185
|
+
"""
|
|
186
|
+
valAx_lst = self._chartSpace.valAx_lst
|
|
187
|
+
if not valAx_lst:
|
|
188
|
+
raise ValueError("chart has no value axis")
|
|
189
|
+
|
|
190
|
+
idx = 1 if len(valAx_lst) > 1 else 0
|
|
191
|
+
return ValueAxis(valAx_lst[idx])
|
|
192
|
+
|
|
193
|
+
@property
|
|
194
|
+
def _workbook(self):
|
|
195
|
+
"""
|
|
196
|
+
The |ChartWorkbook| object providing access to the Excel source data
|
|
197
|
+
for this chart.
|
|
198
|
+
"""
|
|
199
|
+
return self.part.chart_workbook
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
class ChartTitle(ElementProxy):
|
|
203
|
+
"""Provides properties for manipulating a chart title."""
|
|
204
|
+
|
|
205
|
+
# This shares functionality with AxisTitle, which could be factored out
|
|
206
|
+
# into a base class, perhaps pptx.chart.shared.BaseTitle. I suspect they
|
|
207
|
+
# actually differ in certain fuller behaviors, but at present they're
|
|
208
|
+
# essentially identical.
|
|
209
|
+
|
|
210
|
+
def __init__(self, title):
|
|
211
|
+
super(ChartTitle, self).__init__(title)
|
|
212
|
+
self._title = title
|
|
213
|
+
|
|
214
|
+
@lazyproperty
|
|
215
|
+
def format(self):
|
|
216
|
+
"""|ChartFormat| object providing access to line and fill formatting.
|
|
217
|
+
|
|
218
|
+
Return the |ChartFormat| object providing shape formatting properties
|
|
219
|
+
for this chart title, such as its line color and fill.
|
|
220
|
+
"""
|
|
221
|
+
return ChartFormat(self._title)
|
|
222
|
+
|
|
223
|
+
@property
|
|
224
|
+
def has_text_frame(self):
|
|
225
|
+
"""Read/write Boolean specifying whether this title has a text frame.
|
|
226
|
+
|
|
227
|
+
Return |True| if this chart title has a text frame, and |False|
|
|
228
|
+
otherwise. Assigning |True| causes a text frame to be added if not
|
|
229
|
+
already present. Assigning |False| causes any existing text frame to
|
|
230
|
+
be removed along with its text and formatting.
|
|
231
|
+
"""
|
|
232
|
+
if self._title.tx_rich is None:
|
|
233
|
+
return False
|
|
234
|
+
return True
|
|
235
|
+
|
|
236
|
+
@has_text_frame.setter
|
|
237
|
+
def has_text_frame(self, value):
|
|
238
|
+
if bool(value) is False:
|
|
239
|
+
self._title._remove_tx()
|
|
240
|
+
return
|
|
241
|
+
self._title.get_or_add_tx_rich()
|
|
242
|
+
|
|
243
|
+
@property
|
|
244
|
+
def text_frame(self):
|
|
245
|
+
"""|TextFrame| instance for this chart title.
|
|
246
|
+
|
|
247
|
+
Return a |TextFrame| instance allowing read/write access to the text
|
|
248
|
+
of this chart title and its text formatting properties. Accessing this
|
|
249
|
+
property is destructive in the sense it adds a text frame if one is
|
|
250
|
+
not present. Use :attr:`has_text_frame` to test for the presence of
|
|
251
|
+
a text frame non-destructively.
|
|
252
|
+
"""
|
|
253
|
+
rich = self._title.get_or_add_tx_rich()
|
|
254
|
+
return TextFrame(rich, self)
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
class _Plots(Sequence):
|
|
258
|
+
"""
|
|
259
|
+
The sequence of plots in a chart, such as a bar plot or a line plot. Most
|
|
260
|
+
charts have only a single plot. The concept is necessary when two chart
|
|
261
|
+
types are displayed in a single set of axes, like a bar plot with
|
|
262
|
+
a superimposed line plot.
|
|
263
|
+
"""
|
|
264
|
+
|
|
265
|
+
def __init__(self, plotArea, chart):
|
|
266
|
+
super(_Plots, self).__init__()
|
|
267
|
+
self._plotArea = plotArea
|
|
268
|
+
self._chart = chart
|
|
269
|
+
|
|
270
|
+
def __getitem__(self, index):
|
|
271
|
+
xCharts = self._plotArea.xCharts
|
|
272
|
+
if isinstance(index, slice):
|
|
273
|
+
plots = [PlotFactory(xChart, self._chart) for xChart in xCharts]
|
|
274
|
+
return plots[index]
|
|
275
|
+
else:
|
|
276
|
+
xChart = xCharts[index]
|
|
277
|
+
return PlotFactory(xChart, self._chart)
|
|
278
|
+
|
|
279
|
+
def __len__(self):
|
|
280
|
+
return len(self._plotArea.xCharts)
|