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/table.py
ADDED
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
"""Table-related objects such as Table and Cell."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Iterator
|
|
6
|
+
from uuid import UUID
|
|
7
|
+
|
|
8
|
+
from pptx.dml.fill import FillFormat
|
|
9
|
+
from pptx.oxml.ns import qn
|
|
10
|
+
from pptx.oxml.table import TcRange
|
|
11
|
+
from pptx.oxml.xmlchemy import OxmlElement
|
|
12
|
+
from pptx.shapes import Subshape
|
|
13
|
+
from pptx.text.text import TextFrame
|
|
14
|
+
from pptx.util import Emu, lazyproperty
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from pptx.enum.text import MSO_VERTICAL_ANCHOR
|
|
18
|
+
from pptx.oxml.table import CT_Table, CT_TableCell, CT_TableCol, CT_TableRow
|
|
19
|
+
from pptx.parts.slide import BaseSlidePart
|
|
20
|
+
from pptx.shapes.graphfrm import GraphicFrame
|
|
21
|
+
from pptx.types import ProvidesPart
|
|
22
|
+
from pptx.util import Length
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class Table(object):
|
|
26
|
+
"""A DrawingML table object.
|
|
27
|
+
|
|
28
|
+
Not intended to be constructed directly, use
|
|
29
|
+
:meth:`.Slide.shapes.add_table` to add a table to a slide.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
def __init__(self, tbl: CT_Table, graphic_frame: GraphicFrame):
|
|
33
|
+
super(Table, self).__init__()
|
|
34
|
+
self._tbl = tbl
|
|
35
|
+
self._graphic_frame = graphic_frame
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def style_id(self) -> str | None:
|
|
39
|
+
"""GUID of the referenced table style. None selects the presentation default."""
|
|
40
|
+
properties = self._tbl.tblPr
|
|
41
|
+
style = None if properties is None else properties.find(qn("a:tableStyleId"))
|
|
42
|
+
return None if style is None else style.text
|
|
43
|
+
|
|
44
|
+
@style_id.setter
|
|
45
|
+
def style_id(self, value: str | None):
|
|
46
|
+
if value is not None:
|
|
47
|
+
if not isinstance(value, str):
|
|
48
|
+
raise TypeError("style_id must be a GUID string or None")
|
|
49
|
+
value = "{" + str(UUID(value)).upper() + "}"
|
|
50
|
+
properties = self._tbl.get_or_add_tblPr()
|
|
51
|
+
for style in list(properties.findall(qn("a:tableStyleId"))):
|
|
52
|
+
properties.remove(style)
|
|
53
|
+
if value is not None:
|
|
54
|
+
style = OxmlElement("a:tableStyleId")
|
|
55
|
+
style.text = value
|
|
56
|
+
properties.insert_element_before(style, "a:extLst")
|
|
57
|
+
|
|
58
|
+
def cell(self, row_idx: int, col_idx: int) -> _Cell:
|
|
59
|
+
"""Return cell at `row_idx`, `col_idx`.
|
|
60
|
+
|
|
61
|
+
Return value is an instance of |_Cell|. `row_idx` and `col_idx` are zero-based, e.g.
|
|
62
|
+
cell(0, 0) is the top, left cell in the table.
|
|
63
|
+
"""
|
|
64
|
+
return _Cell(self._tbl.tc(row_idx, col_idx), self)
|
|
65
|
+
|
|
66
|
+
@lazyproperty
|
|
67
|
+
def columns(self) -> _ColumnCollection:
|
|
68
|
+
"""|_ColumnCollection| instance for this table.
|
|
69
|
+
|
|
70
|
+
Provides access to |_Column| objects representing the table's columns. |_Column| objects
|
|
71
|
+
are accessed using list notation, e.g. `col = tbl.columns[0]`.
|
|
72
|
+
"""
|
|
73
|
+
return _ColumnCollection(self._tbl, self)
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def first_col(self) -> bool:
|
|
77
|
+
"""When `True`, indicates first column should have distinct formatting.
|
|
78
|
+
|
|
79
|
+
Read/write. Distinct formatting is used, for example, when the first column contains row
|
|
80
|
+
headings (is a side-heading column).
|
|
81
|
+
"""
|
|
82
|
+
return self._tbl.firstCol
|
|
83
|
+
|
|
84
|
+
@first_col.setter
|
|
85
|
+
def first_col(self, value: bool):
|
|
86
|
+
self._tbl.firstCol = value
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def first_row(self) -> bool:
|
|
90
|
+
"""When `True`, indicates first row should have distinct formatting.
|
|
91
|
+
|
|
92
|
+
Read/write. Distinct formatting is used, for example, when the first row contains column
|
|
93
|
+
headings.
|
|
94
|
+
"""
|
|
95
|
+
return self._tbl.firstRow
|
|
96
|
+
|
|
97
|
+
@first_row.setter
|
|
98
|
+
def first_row(self, value: bool):
|
|
99
|
+
self._tbl.firstRow = value
|
|
100
|
+
|
|
101
|
+
@property
|
|
102
|
+
def horz_banding(self) -> bool:
|
|
103
|
+
"""When `True`, indicates rows should have alternating shading.
|
|
104
|
+
|
|
105
|
+
Read/write. Used to allow rows to be traversed more easily without losing track of which
|
|
106
|
+
row is being read.
|
|
107
|
+
"""
|
|
108
|
+
return self._tbl.bandRow
|
|
109
|
+
|
|
110
|
+
@horz_banding.setter
|
|
111
|
+
def horz_banding(self, value: bool):
|
|
112
|
+
self._tbl.bandRow = value
|
|
113
|
+
|
|
114
|
+
def iter_cells(self) -> Iterator[_Cell]:
|
|
115
|
+
"""Generate _Cell object for each cell in this table.
|
|
116
|
+
|
|
117
|
+
Each grid cell is generated in left-to-right, top-to-bottom order.
|
|
118
|
+
"""
|
|
119
|
+
return (_Cell(tc, self) for tc in self._tbl.iter_tcs())
|
|
120
|
+
|
|
121
|
+
@property
|
|
122
|
+
def last_col(self) -> bool:
|
|
123
|
+
"""When `True`, indicates the rightmost column should have distinct formatting.
|
|
124
|
+
|
|
125
|
+
Read/write. Used, for example, when a row totals column appears at the far right of the
|
|
126
|
+
table.
|
|
127
|
+
"""
|
|
128
|
+
return self._tbl.lastCol
|
|
129
|
+
|
|
130
|
+
@last_col.setter
|
|
131
|
+
def last_col(self, value: bool):
|
|
132
|
+
self._tbl.lastCol = value
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def last_row(self) -> bool:
|
|
136
|
+
"""When `True`, indicates the bottom row should have distinct formatting.
|
|
137
|
+
|
|
138
|
+
Read/write. Used, for example, when a totals row appears as the bottom row.
|
|
139
|
+
"""
|
|
140
|
+
return self._tbl.lastRow
|
|
141
|
+
|
|
142
|
+
@last_row.setter
|
|
143
|
+
def last_row(self, value: bool):
|
|
144
|
+
self._tbl.lastRow = value
|
|
145
|
+
|
|
146
|
+
def notify_height_changed(self) -> None:
|
|
147
|
+
"""Called by a row when its height changes.
|
|
148
|
+
|
|
149
|
+
Triggers the graphic frame to recalculate its total height (as the sum of the row
|
|
150
|
+
heights).
|
|
151
|
+
"""
|
|
152
|
+
new_table_height = Emu(sum([row.height for row in self.rows]))
|
|
153
|
+
self._graphic_frame.height = new_table_height
|
|
154
|
+
|
|
155
|
+
def notify_width_changed(self) -> None:
|
|
156
|
+
"""Called by a column when its width changes.
|
|
157
|
+
|
|
158
|
+
Triggers the graphic frame to recalculate its total width (as the sum of the column
|
|
159
|
+
widths).
|
|
160
|
+
"""
|
|
161
|
+
new_table_width = Emu(sum([col.width for col in self.columns]))
|
|
162
|
+
self._graphic_frame.width = new_table_width
|
|
163
|
+
|
|
164
|
+
@property
|
|
165
|
+
def part(self) -> BaseSlidePart:
|
|
166
|
+
"""The package part containing this table."""
|
|
167
|
+
return self._graphic_frame.part
|
|
168
|
+
|
|
169
|
+
@lazyproperty
|
|
170
|
+
def rows(self):
|
|
171
|
+
"""|_RowCollection| instance for this table.
|
|
172
|
+
|
|
173
|
+
Provides access to |_Row| objects representing the table's rows. |_Row| objects are
|
|
174
|
+
accessed using list notation, e.g. `col = tbl.rows[0]`.
|
|
175
|
+
"""
|
|
176
|
+
return _RowCollection(self._tbl, self)
|
|
177
|
+
|
|
178
|
+
@property
|
|
179
|
+
def vert_banding(self) -> bool:
|
|
180
|
+
"""When `True`, indicates columns should have alternating shading.
|
|
181
|
+
|
|
182
|
+
Read/write. Used to allow columns to be traversed more easily without losing track of
|
|
183
|
+
which column is being read.
|
|
184
|
+
"""
|
|
185
|
+
return self._tbl.bandCol
|
|
186
|
+
|
|
187
|
+
@vert_banding.setter
|
|
188
|
+
def vert_banding(self, value: bool):
|
|
189
|
+
self._tbl.bandCol = value
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
class _Cell(Subshape):
|
|
193
|
+
"""Table cell"""
|
|
194
|
+
|
|
195
|
+
def __init__(self, tc: CT_TableCell, parent: ProvidesPart):
|
|
196
|
+
super(_Cell, self).__init__(parent)
|
|
197
|
+
self._tc = tc
|
|
198
|
+
|
|
199
|
+
def __eq__(self, other: object) -> bool:
|
|
200
|
+
"""|True| if this object proxies the same element as `other`.
|
|
201
|
+
|
|
202
|
+
Equality for proxy objects is defined as referring to the same XML element, whether or not
|
|
203
|
+
they are the same proxy object instance.
|
|
204
|
+
"""
|
|
205
|
+
if not isinstance(other, type(self)):
|
|
206
|
+
return False
|
|
207
|
+
return self._tc is other._tc
|
|
208
|
+
|
|
209
|
+
def __ne__(self, other: object) -> bool:
|
|
210
|
+
if not isinstance(other, type(self)):
|
|
211
|
+
return True
|
|
212
|
+
return self._tc is not other._tc
|
|
213
|
+
|
|
214
|
+
@lazyproperty
|
|
215
|
+
def fill(self) -> FillFormat:
|
|
216
|
+
"""|FillFormat| instance for this cell.
|
|
217
|
+
|
|
218
|
+
Provides access to fill properties such as foreground color.
|
|
219
|
+
"""
|
|
220
|
+
tcPr = self._tc.get_or_add_tcPr()
|
|
221
|
+
return FillFormat.from_fill_parent(tcPr)
|
|
222
|
+
|
|
223
|
+
@property
|
|
224
|
+
def is_merge_origin(self) -> bool:
|
|
225
|
+
"""True if this cell is the top-left grid cell in a merged cell."""
|
|
226
|
+
return self._tc.is_merge_origin
|
|
227
|
+
|
|
228
|
+
@property
|
|
229
|
+
def is_spanned(self) -> bool:
|
|
230
|
+
"""True if this cell is spanned by a merge-origin cell.
|
|
231
|
+
|
|
232
|
+
A merge-origin cell "spans" the other grid cells in its merge range, consuming their area
|
|
233
|
+
and "shadowing" the spanned grid cells.
|
|
234
|
+
|
|
235
|
+
Note this value is |False| for a merge-origin cell. A merge-origin cell spans other grid
|
|
236
|
+
cells, but is not itself a spanned cell.
|
|
237
|
+
"""
|
|
238
|
+
return self._tc.is_spanned
|
|
239
|
+
|
|
240
|
+
@property
|
|
241
|
+
def margin_left(self) -> Length:
|
|
242
|
+
"""Left margin of cells.
|
|
243
|
+
|
|
244
|
+
Read/write. If assigned |None|, the default value is used, 0.1 inches for left and right
|
|
245
|
+
margins and 0.05 inches for top and bottom.
|
|
246
|
+
"""
|
|
247
|
+
return self._tc.marL
|
|
248
|
+
|
|
249
|
+
@margin_left.setter
|
|
250
|
+
def margin_left(self, margin_left: Length | None):
|
|
251
|
+
self._validate_margin_value(margin_left)
|
|
252
|
+
self._tc.marL = margin_left
|
|
253
|
+
|
|
254
|
+
@property
|
|
255
|
+
def margin_right(self) -> Length:
|
|
256
|
+
"""Right margin of cell."""
|
|
257
|
+
return self._tc.marR
|
|
258
|
+
|
|
259
|
+
@margin_right.setter
|
|
260
|
+
def margin_right(self, margin_right: Length | None):
|
|
261
|
+
self._validate_margin_value(margin_right)
|
|
262
|
+
self._tc.marR = margin_right
|
|
263
|
+
|
|
264
|
+
@property
|
|
265
|
+
def margin_top(self) -> Length:
|
|
266
|
+
"""Top margin of cell."""
|
|
267
|
+
return self._tc.marT
|
|
268
|
+
|
|
269
|
+
@margin_top.setter
|
|
270
|
+
def margin_top(self, margin_top: Length | None):
|
|
271
|
+
self._validate_margin_value(margin_top)
|
|
272
|
+
self._tc.marT = margin_top
|
|
273
|
+
|
|
274
|
+
@property
|
|
275
|
+
def margin_bottom(self) -> Length:
|
|
276
|
+
"""Bottom margin of cell."""
|
|
277
|
+
return self._tc.marB
|
|
278
|
+
|
|
279
|
+
@margin_bottom.setter
|
|
280
|
+
def margin_bottom(self, margin_bottom: Length | None):
|
|
281
|
+
self._validate_margin_value(margin_bottom)
|
|
282
|
+
self._tc.marB = margin_bottom
|
|
283
|
+
|
|
284
|
+
def merge(self, other_cell: _Cell) -> None:
|
|
285
|
+
"""Create merged cell from this cell to `other_cell`.
|
|
286
|
+
|
|
287
|
+
This cell and `other_cell` specify opposite corners of the merged cell range. Either
|
|
288
|
+
diagonal of the cell region may be specified in either order, e.g. self=bottom-right,
|
|
289
|
+
other_cell=top-left, etc.
|
|
290
|
+
|
|
291
|
+
Raises |ValueError| if the specified range already contains merged cells anywhere within
|
|
292
|
+
its extents or if `other_cell` is not in the same table as `self`.
|
|
293
|
+
"""
|
|
294
|
+
tc_range = TcRange(self._tc, other_cell._tc)
|
|
295
|
+
|
|
296
|
+
if not tc_range.in_same_table:
|
|
297
|
+
raise ValueError("other_cell from different table")
|
|
298
|
+
if tc_range.contains_merged_cell:
|
|
299
|
+
raise ValueError("range contains one or more merged cells")
|
|
300
|
+
|
|
301
|
+
tc_range.move_content_to_origin()
|
|
302
|
+
|
|
303
|
+
row_count, col_count = tc_range.dimensions
|
|
304
|
+
|
|
305
|
+
for tc in tc_range.iter_top_row_tcs():
|
|
306
|
+
tc.rowSpan = row_count
|
|
307
|
+
for tc in tc_range.iter_left_col_tcs():
|
|
308
|
+
tc.gridSpan = col_count
|
|
309
|
+
for tc in tc_range.iter_except_left_col_tcs():
|
|
310
|
+
tc.hMerge = True
|
|
311
|
+
for tc in tc_range.iter_except_top_row_tcs():
|
|
312
|
+
tc.vMerge = True
|
|
313
|
+
|
|
314
|
+
@property
|
|
315
|
+
def span_height(self) -> int:
|
|
316
|
+
"""int count of rows spanned by this cell.
|
|
317
|
+
|
|
318
|
+
The value of this property may be misleading (often 1) on cells where `.is_merge_origin`
|
|
319
|
+
is not |True|, since only a merge-origin cell contains complete span information. This
|
|
320
|
+
property is only intended for use on cells known to be a merge origin by testing
|
|
321
|
+
`.is_merge_origin`.
|
|
322
|
+
"""
|
|
323
|
+
return self._tc.rowSpan
|
|
324
|
+
|
|
325
|
+
@property
|
|
326
|
+
def span_width(self) -> int:
|
|
327
|
+
"""int count of columns spanned by this cell.
|
|
328
|
+
|
|
329
|
+
The value of this property may be misleading (often 1) on cells where `.is_merge_origin`
|
|
330
|
+
is not |True|, since only a merge-origin cell contains complete span information. This
|
|
331
|
+
property is only intended for use on cells known to be a merge origin by testing
|
|
332
|
+
`.is_merge_origin`.
|
|
333
|
+
"""
|
|
334
|
+
return self._tc.gridSpan
|
|
335
|
+
|
|
336
|
+
def split(self) -> None:
|
|
337
|
+
"""Remove merge from this (merge-origin) cell.
|
|
338
|
+
|
|
339
|
+
The merged cell represented by this object will be "unmerged", yielding a separate
|
|
340
|
+
unmerged cell for each grid cell previously spanned by this merge.
|
|
341
|
+
|
|
342
|
+
Raises |ValueError| when this cell is not a merge-origin cell. Test with
|
|
343
|
+
`.is_merge_origin` before calling.
|
|
344
|
+
"""
|
|
345
|
+
if not self.is_merge_origin:
|
|
346
|
+
raise ValueError("not a merge-origin cell; only a merge-origin cell can be split")
|
|
347
|
+
|
|
348
|
+
tc_range = TcRange.from_merge_origin(self._tc)
|
|
349
|
+
|
|
350
|
+
for tc in tc_range.iter_tcs():
|
|
351
|
+
tc.rowSpan = tc.gridSpan = 1
|
|
352
|
+
tc.hMerge = tc.vMerge = False
|
|
353
|
+
|
|
354
|
+
@property
|
|
355
|
+
def text(self) -> str:
|
|
356
|
+
"""Textual content of cell as a single string.
|
|
357
|
+
|
|
358
|
+
The returned string will contain a newline character (`"\\n"`) separating each paragraph
|
|
359
|
+
and a vertical-tab (`"\\v"`) character for each line break (soft carriage return) in the
|
|
360
|
+
cell's text.
|
|
361
|
+
|
|
362
|
+
Assignment to `text` replaces all text currently contained in the cell. A newline
|
|
363
|
+
character (`"\\n"`) in the assigned text causes a new paragraph to be started. A
|
|
364
|
+
vertical-tab (`"\\v"`) character in the assigned text causes a line-break (soft
|
|
365
|
+
carriage-return) to be inserted. (The vertical-tab character appears in clipboard text
|
|
366
|
+
copied from PowerPoint as its encoding of line-breaks.)
|
|
367
|
+
"""
|
|
368
|
+
return self.text_frame.text
|
|
369
|
+
|
|
370
|
+
@text.setter
|
|
371
|
+
def text(self, text: str):
|
|
372
|
+
self.text_frame.text = text
|
|
373
|
+
|
|
374
|
+
@property
|
|
375
|
+
def text_frame(self) -> TextFrame:
|
|
376
|
+
"""|TextFrame| containing the text that appears in the cell."""
|
|
377
|
+
txBody = self._tc.get_or_add_txBody()
|
|
378
|
+
return TextFrame(txBody, self)
|
|
379
|
+
|
|
380
|
+
@property
|
|
381
|
+
def vertical_anchor(self) -> MSO_VERTICAL_ANCHOR | None:
|
|
382
|
+
"""Vertical alignment of this cell.
|
|
383
|
+
|
|
384
|
+
This value is a member of the :ref:`MsoVerticalAnchor` enumeration or |None|. A value of
|
|
385
|
+
|None| indicates the cell has no explicitly applied vertical anchor setting and its
|
|
386
|
+
effective value is inherited from its style-hierarchy ancestors.
|
|
387
|
+
|
|
388
|
+
Assigning |None| to this property causes any explicitly applied vertical anchor setting to
|
|
389
|
+
be cleared and inheritance of its effective value to be restored.
|
|
390
|
+
"""
|
|
391
|
+
return self._tc.anchor
|
|
392
|
+
|
|
393
|
+
@vertical_anchor.setter
|
|
394
|
+
def vertical_anchor(self, mso_anchor_idx: MSO_VERTICAL_ANCHOR | None):
|
|
395
|
+
self._tc.anchor = mso_anchor_idx
|
|
396
|
+
|
|
397
|
+
@staticmethod
|
|
398
|
+
def _validate_margin_value(margin_value: Length | None) -> None:
|
|
399
|
+
"""Raise ValueError if `margin_value` is not a positive integer value or |None|."""
|
|
400
|
+
if not isinstance(margin_value, int) and margin_value is not None:
|
|
401
|
+
tmpl = "margin value must be integer or None, got '%s'"
|
|
402
|
+
raise TypeError(tmpl % margin_value)
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
class _Column(Subshape):
|
|
406
|
+
"""Table column"""
|
|
407
|
+
|
|
408
|
+
def __init__(self, gridCol: CT_TableCol, parent: _ColumnCollection):
|
|
409
|
+
super(_Column, self).__init__(parent)
|
|
410
|
+
self._parent = parent
|
|
411
|
+
self._gridCol = gridCol
|
|
412
|
+
|
|
413
|
+
@property
|
|
414
|
+
def width(self) -> Length:
|
|
415
|
+
"""Width of column in EMU."""
|
|
416
|
+
return self._gridCol.w
|
|
417
|
+
|
|
418
|
+
@width.setter
|
|
419
|
+
def width(self, width: Length):
|
|
420
|
+
self._gridCol.w = width
|
|
421
|
+
self._parent.notify_width_changed()
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
class _Row(Subshape):
|
|
425
|
+
"""Table row"""
|
|
426
|
+
|
|
427
|
+
def __init__(self, tr: CT_TableRow, parent: _RowCollection):
|
|
428
|
+
super(_Row, self).__init__(parent)
|
|
429
|
+
self._parent = parent
|
|
430
|
+
self._tr = tr
|
|
431
|
+
|
|
432
|
+
@property
|
|
433
|
+
def cells(self):
|
|
434
|
+
"""Read-only reference to collection of cells in row.
|
|
435
|
+
|
|
436
|
+
An individual cell is referenced using list notation, e.g. `cell = row.cells[0]`.
|
|
437
|
+
"""
|
|
438
|
+
return _CellCollection(self._tr, self)
|
|
439
|
+
|
|
440
|
+
@property
|
|
441
|
+
def height(self) -> Length:
|
|
442
|
+
"""Height of row in EMU."""
|
|
443
|
+
return self._tr.h
|
|
444
|
+
|
|
445
|
+
@height.setter
|
|
446
|
+
def height(self, height: Length):
|
|
447
|
+
self._tr.h = height
|
|
448
|
+
self._parent.notify_height_changed()
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
class _CellCollection(Subshape):
|
|
452
|
+
"""Horizontal sequence of row cells"""
|
|
453
|
+
|
|
454
|
+
def __init__(self, tr: CT_TableRow, parent: _Row):
|
|
455
|
+
super(_CellCollection, self).__init__(parent)
|
|
456
|
+
self._parent = parent
|
|
457
|
+
self._tr = tr
|
|
458
|
+
|
|
459
|
+
def __getitem__(self, idx: int) -> _Cell:
|
|
460
|
+
"""Provides indexed access, (e.g. 'cells[0]')."""
|
|
461
|
+
if idx < 0 or idx >= len(self._tr.tc_lst):
|
|
462
|
+
msg = "cell index [%d] out of range" % idx
|
|
463
|
+
raise IndexError(msg)
|
|
464
|
+
return _Cell(self._tr.tc_lst[idx], self)
|
|
465
|
+
|
|
466
|
+
def __iter__(self) -> Iterator[_Cell]:
|
|
467
|
+
"""Provides iterability."""
|
|
468
|
+
return (_Cell(tc, self) for tc in self._tr.tc_lst)
|
|
469
|
+
|
|
470
|
+
def __len__(self) -> int:
|
|
471
|
+
"""Supports len() function (e.g. 'len(cells) == 1')."""
|
|
472
|
+
return len(self._tr.tc_lst)
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
class _ColumnCollection(Subshape):
|
|
476
|
+
"""Sequence of table columns."""
|
|
477
|
+
|
|
478
|
+
def __init__(self, tbl: CT_Table, parent: Table):
|
|
479
|
+
super(_ColumnCollection, self).__init__(parent)
|
|
480
|
+
self._parent = parent
|
|
481
|
+
self._tbl = tbl
|
|
482
|
+
|
|
483
|
+
def __getitem__(self, idx: int):
|
|
484
|
+
"""Provides indexed access, (e.g. 'columns[0]')."""
|
|
485
|
+
if idx < 0 or idx >= len(self._tbl.tblGrid.gridCol_lst):
|
|
486
|
+
msg = "column index [%d] out of range" % idx
|
|
487
|
+
raise IndexError(msg)
|
|
488
|
+
return _Column(self._tbl.tblGrid.gridCol_lst[idx], self)
|
|
489
|
+
|
|
490
|
+
def __len__(self):
|
|
491
|
+
"""Supports len() function (e.g. 'len(columns) == 1')."""
|
|
492
|
+
return len(self._tbl.tblGrid.gridCol_lst)
|
|
493
|
+
|
|
494
|
+
def notify_width_changed(self):
|
|
495
|
+
"""Called by a column when its width changes. Pass along to parent."""
|
|
496
|
+
self._parent.notify_width_changed()
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
class _RowCollection(Subshape):
|
|
500
|
+
"""Sequence of table rows"""
|
|
501
|
+
|
|
502
|
+
def __init__(self, tbl: CT_Table, parent: Table):
|
|
503
|
+
super(_RowCollection, self).__init__(parent)
|
|
504
|
+
self._parent = parent
|
|
505
|
+
self._tbl = tbl
|
|
506
|
+
|
|
507
|
+
def __getitem__(self, idx: int) -> _Row:
|
|
508
|
+
"""Provides indexed access, (e.g. 'rows[0]')."""
|
|
509
|
+
if idx < 0 or idx >= len(self):
|
|
510
|
+
msg = "row index [%d] out of range" % idx
|
|
511
|
+
raise IndexError(msg)
|
|
512
|
+
return _Row(self._tbl.tr_lst[idx], self)
|
|
513
|
+
|
|
514
|
+
def __len__(self):
|
|
515
|
+
"""Supports len() function (e.g. 'len(rows) == 1')."""
|
|
516
|
+
return len(self._tbl.tr_lst)
|
|
517
|
+
|
|
518
|
+
def notify_height_changed(self):
|
|
519
|
+
"""Called by a row when its height changes. Pass along to parent."""
|
|
520
|
+
self._parent.notify_height_changed()
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
pptx/templates/notes.xml
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
|
|
2
|
+
<p:notes xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
|
|
3
|
+
<p:cSld>
|
|
4
|
+
<p:spTree>
|
|
5
|
+
<p:nvGrpSpPr>
|
|
6
|
+
<p:cNvPr id="1" name=""/>
|
|
7
|
+
<p:cNvGrpSpPr/>
|
|
8
|
+
<p:nvPr/>
|
|
9
|
+
</p:nvGrpSpPr>
|
|
10
|
+
<p:grpSpPr>
|
|
11
|
+
<a:xfrm>
|
|
12
|
+
<a:off x="0" y="0"/>
|
|
13
|
+
<a:ext cx="0" cy="0"/>
|
|
14
|
+
<a:chOff x="0" y="0"/>
|
|
15
|
+
<a:chExt cx="0" cy="0"/>
|
|
16
|
+
</a:xfrm>
|
|
17
|
+
</p:grpSpPr>
|
|
18
|
+
</p:spTree>
|
|
19
|
+
</p:cSld>
|
|
20
|
+
<p:clrMapOvr>
|
|
21
|
+
<a:masterClrMapping/>
|
|
22
|
+
</p:clrMapOvr>
|
|
23
|
+
</p:notes>
|