Python
Python
Release 0.6.22
Steve Canny
1 Philosophy 3
2 Feature Support 5
3 New features/releases 7
4 User Guide 9
5 Community Guide 51
6 API Documentation 61
Index 517
i
ii
python-pptx Documentation, Release 0.6.22
Contents 1
python-pptx Documentation, Release 0.6.22
2 Contents
CHAPTER 1
Philosophy
python-pptx aims to broadly support the PowerPoint format (PPTX, PowerPoint 2007 and later), but its primary com-
mitment is to be _industrial-grade_, that is, suitable for use in a commercial setting. Maintaining this robustness
requires a high engineering standard which includes a comprehensive two-level (e2e + unit) testing regimen. This
discipline comes at a cost in development effort/time, but we consider reliability to be an essential requirement.
3
python-pptx Documentation, Release 0.6.22
4 Chapter 1. Philosophy
CHAPTER 2
Feature Support
5
python-pptx Documentation, Release 0.6.22
New features/releases
New features are generally added via sponsorship. If there’s a new feature you need for your use case, feel free to
reach out at the email address on the github.com/scanny profile page. Many of the most used features such as charts
were added this way.
7
python-pptx Documentation, Release 0.6.22
User Guide
4.1 Introduction
python-pptx is a Python library for creating and updating PowerPoint (.pptx) files.
A typical use would be generating a customized PowerPoint presentation from database content, downloadble by
clicking a link in a web application. Several developers have used it to automate production of presentation-ready
engineering status reports based on information held in their work management system. It could also be used for
making bulk updates to a library of presentations or simply to automate the production of a slide or two that would be
tedious to get right by hand.
This user guide is tutorial in nature, introducing concepts along with code examples that I hope will allow you to learn
what you need while addressing the real-life PowerPoint challenges you’re working on.
The MIT License (MIT) Copyright (c) 2013 Steve Canny, https://github.com/scanny
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associ-
ated documentation files (the “Software”), to deal in the Software without restriction, including without
limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARIS-
ING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
9
python-pptx Documentation, Release 0.6.22
4.2 Installing
python-pptx depends on the lxml package and Pillow, the modern version of the Python Imaging Library (PIL).
The charting features depend on XlsxWriter. Both pip and easy_install will take care of satisfying these
dependencies for you, but if you use the setup.py installation method you will need to install the dependencies
yourself.
Currently python-pptx requires Python 2.7 or 3.3 or later. The tests are run against 2.7 and 3.8 on Travis CI.
4.2.1 Dependencies
A quick way to get started is by trying out some of the examples below to get a feel for how to use python-pptx.
The API documentation can help you with the fine details of calling signatures and behaviors.
prs = Presentation()
title_slide_layout = prs.slide_layouts[0]
slide = prs.slides.add_slide(title_slide_layout)
title = slide.shapes.title
subtitle = slide.placeholders[1]
prs.save('test.pptx')
prs = Presentation()
bullet_slide_layout = prs.slide_layouts[1]
slide = prs.slides.add_slide(bullet_slide_layout)
shapes = slide.shapes
title_shape = shapes.title
body_shape = shapes.placeholders[1]
tf = body_shape.text_frame
tf.text = 'Find the bullet slide layout'
p = tf.add_paragraph()
p.text = 'Use _TextFrame.text for first bullet'
p.level = 1
p = tf.add_paragraph()
p.text = 'Use _TextFrame.add_paragraph() for subsequent bullets'
p.level = 2
prs.save('test.pptx')
Not all shapes can contain text, but those that do always have at least one paragraph, even if that paragraph is empty
and no text is visible within the shape. _BaseShape.has_text_frame can be used to determine whether a
shape can contain text. (All shapes subclass _BaseShape.) When _BaseShape.has_text_frame is True,
_BaseShape.text_frame.paragraphs[0] returns the first paragraph. The text of the first paragraph can
be set using text_frame.paragraphs[0].text. As a shortcut, the writable properties _BaseShape.text
and _TextFrame.text are provided to accomplish the same thing. Note that these last two calls delete all the
shape’s paragraphs except the first one before setting the text it contains.
prs = Presentation()
blank_slide_layout = prs.slide_layouts[6]
slide = prs.slides.add_slide(blank_slide_layout)
p = tf.add_paragraph()
p.text = "This is a second paragraph that's bold"
p.font.bold = True
p = tf.add_paragraph()
p.text = "This is a third paragraph that's big"
p.font.size = Pt(40)
prs.save('test.pptx')
img_path = 'monty-truth.png'
left = Inches(5)
height = Inches(5.5)
pic = slide.shapes.add_picture(img_path, left, top, height=height)
prs.save('test.pptx')
prs = Presentation()
title_only_slide_layout = prs.slide_layouts[5]
slide = prs.slides.add_slide(title_only_slide_layout)
shapes = slide.shapes
prs.save('test.pptx')
prs = Presentation()
title_only_slide_layout = prs.slide_layouts[5]
slide = prs.slides.add_slide(title_only_slide_layout)
shapes = slide.shapes
(continues on next page)
rows = cols = 2
left = top = Inches(2.0)
width = Inches(6.0)
height = Inches(0.8)
prs.save('test.pptx')
prs = Presentation(path_to_presentation)
python-pptx allows you to create new presentations as well as make changes to existing ones. Actually, it only lets
you make changes to existing presentations; it’s just that if you start with a presentation that doesn’t have any slides, it
feels at first like you’re creating one from scratch.
However, a lot of how a presentation looks is determined by the parts that are left when you delete all the slides,
specifically the theme, the slide master, and the slide layouts that derive from the master. Let’s walk through it a step
at a time using examples, starting with the two things you can do with a presentation, open it and save it.
The simplest way to get started is to open a new presentation without specifying a file to open:
from pptx import Presentation
prs = Presentation()
prs.save('test.pptx')
This creates a new presentation from the built-in default template and saves it unchanged to a file named ‘test.pptx’.
A couple things to note:
• The so-called “default template” is actually just a PowerPoint file that doesn’t have any slides in it, stored with
the installed python-pptx package. It’s the same as what you would get if you created a new presentation from
a fresh PowerPoint install, a 4x3 aspect ratio presentation based on the “White” template. Well, except it won’t
contain any slides. PowerPoint always adds a blank first slide by default.
• You don’t need to do anything to it before you save it. If you want to see exactly what that template contains,
just look in the ‘test.pptx’ file this creates.
• We’ve called it a template, but in fact it’s just a regular PowerPoint file with all the slides removed. Actual
PowerPoint template files (.potx files) are something a bit different. More on those later maybe, but you won’t
need them to work with python-pptx.
Okay, so if you want any control at all to speak of over the final presentation, or if you want to change an existing
presentation, you need to open one with a filename:
prs = Presentation('existing-prs-file.pptx')
prs.save('new-file-name.pptx')
Things to note:
• You can open any PowerPoint 2007 or later file this way (.ppt files from PowerPoint 2003 and earlier won’t
work). While you might not be able to manipulate all the contents yet, whatever is already in there will load and
save just fine. The feature set is still being built out, so you can’t add or change things like Notes Pages yet, but
if the presentation has them python-pptx is polite enough to leave them alone and smart enough to save them
without actually understanding what they are.
• If you use the same filename to open and save the file, python-pptx will obediently overwrite the original file
without a peep. You’ll want to make sure that’s what you intend.
python-pptx can open a presentation from a so-called file-like object. It can also save to a file-like object. This can be
handy when you want to get the source or target presentation over a network connection or from a database and don’t
want to (or aren’t allowed to) fuss with interacting with the file system. In practice this means you can pass an open
file or StringIO/BytesIO stream object to open or save a presentation like so:
f = open('foobar.pptx')
prs = Presentation(f)
f.close()
# or
Okay, so you’ve got a presentation open and are pretty sure you can save it somewhere later. Next step is to get a slide
in there . . .
Every slide in a presentation is based on a slide layout. Not surprising then that you have to specify which slide layout
to use when you create a new slide. Let’s take a minute to understand a few things about slide layouts that we’ll need
so the slide we add looks the way we want it to.
A slide layout is like a template for a slide. Whatever is on the slide layout “shows through” on a slide created with
it and formatting choices made on the slide layout are inherited by the slide. This is an important feature for getting
a professional-looking presentation deck, where all the slides are formatted consistently. Each slide layout is based
on the slide master in a similar way, so you can make presentation-wide formatting decisions on the slide master and
layout-specific decisions on the slide layouts. There can actually be multiple slide masters, but I’ll pretend for now
there’s only one. Usually there is.
The presentation themes that come with PowerPoint have about nine slide layouts, with names like Title, Title and
Content, Title Only, and Blank. Each has zero or more placeholders (mostly not zero), preformatted areas into which
you can place a title, multi-level bullets, an image, etc. More on those later.
The slide layouts in a standard PowerPoint theme always occur in the same sequence. This allows content from one
deck to be pasted into another and be connected with the right new slide layout:
• Title (presentation title slide)
• Title and Content
• Section Header (sometimes called Segue)
• Two Content (side by side bullet textboxes)
• Comparison (same but additional title for each side by side content box)
• Title Only
• Blank
• Content with Caption
• Picture with Caption
In python-pptx, these are prs.slide_layouts[0] through prs.slide_layouts[8]. However, there’s no
rule they have to appear in this order, it’s just a convention followed by the themes provided with PowerPoint. If the
deck you’re using as your template has different slide layouts or has them in a different order, you’ll have to work out
the slide layout indices for yourself. It’s pretty easy. Just open it up in Slide Master view in PowerPoint and count
down from the top, starting at zero.
Let’s use the Title and Content slide layout; a lot of slides do:
SLD_LAYOUT_TITLE_AND_CONTENT = 1
prs = Presentation()
slide_layout = prs.slide_layouts[SLD_LAYOUT_TITLE_AND_CONTENT]
slide = prs.slides.add_slide(slide_layout)
Right now, adding a slide is the only operation on the slide collection. On the backlog at the time of writing is deleting
a slide and moving a slide to a different position in the list. Copying a slide from one presentation to another turns
out to be pretty hard to get right in the general case, so that probably won’t come until more of the backlog is burned
down.
4.5.4 Up next . . .
Ok, now that we have a new slide, let’s talk about how to put something on it . . .
Pretty much anything on a slide is a shape; the only thing I can think of that can appear on a slide that’s not a shape
is a slide background. There are between six and ten different types of shape, depending how you count. I’ll explain
some of the general shape concepts you’ll need to make sense of how to work with them and then we’ll jump right
into working with the specific types.
Technically there are six and only six different types of shapes that can be placed on a slide:
auto shape This is a regular shape, like a rectangle, an ellipse, or a block arrow. They come in a large variety of
preset shapes, in the neighborhood of 180 different ones. An auto shape can have a fill and an outline, and can
contain text. Some auto shapes have adjustments, the little yellow diamonds you can drag to adjust how round
the corners of a rounded rectangle are for example. A text box is also an autoshape, a rectangular one, just by
default without a fill and without an outline.
picture A raster image, like a photograph or clip art is referred to as a picture in PowerPoint. It’s its own kind of shape
with different behaviors than an autoshape. Note that an auto shape can have a picture fill, in which an image
“shows through” as the background of the shape instead of a fill color or gradient. That’s a different thing. But
cool.
graphic frame This is the technical name for the container that holds a table, a chart, a smart art diagram, or media
clip. You can’t add one of these by itself, it just shows up in the file when you add a graphical object. You
probably won’t need to know anything more about these.
group shape In PowerPoint, a set of shapes can be grouped, allowing them to be selected, moved, resized, and even
filled as a unit. When you group a set of shapes a group shape gets created to contain those member shapes. You
can’t actually see these except by their bounding box when the group is selected.
line/connector Lines are different from auto shapes because, well, they’re linear. Some lines can be connected to
other shapes and stay connected when the other shape is moved. These aren’t supported yet either so I don’t
know much more about them. I’d better get to these soon though, they seem like they’d be very handy.
content part I actually have only the vaguest notion of what these are. It has something to do with embedding
“foreign” XML like SVG in with the presentation. I’m pretty sure PowerPoint itself doesn’t do anything with
these. My strategy is to ignore them. Working good so far.
As for real-life shapes, there are these nine types:
• shape shapes – auto shapes with fill and an outline
• text boxes – auto shapes with no fill and no outline
• placeholders – auto shapes that can appear on a slide layout or master and be inherited on slides that use that
layout, allowing content to be added that takes on the formatting of the placeholder
• line/connector – as described above
• picture – as described above
• table – that row and column thing
• chart – pie chart, line chart, etc.
• smart art – not supported yet, although preserved if present
• media clip – video or audio
Each slide has a shape tree that holds its shapes. It’s called a tree because it’s hierarchical in the general case; a node
in the shape tree can be a group shape which itself can contain shapes and has the same semantics as the shape tree.
For most purposes the shape tree has list semantics. You gain access to it like so:
shapes = slide.shapes
We’ll see a lot more of the shape tree in the next few sections.
4.6.2 Up next . . .
Okay. That should be enough noodle work to get started. Let’s move on to working with AutoShapes.
Auto shapes are regular shape shapes. Squares, circles, triangles, stars, that sort of thing. There are 182 different
auto shapes to choose from. 120 of these have adjustment “handles” you can use to change the shape, sometimes
dramatically.
Many shape types share a common set of properties. We’ll introduce many of them here because several of those
shapes are just a specialized form of AutoShape.
The following code adds a rounded rectangle shape, one inch square, and positioned one inch from the top-left corner
of the slide:
shapes = slide.shapes
left = top = width = height = Inches(1.0)
shape = shapes.add_shape(
MSO_SHAPE.ROUNDED_RECTANGLE, left, top, width, height
)
See the MSO_AUTO_SHAPE_TYPE enumeration page for a list of all 182 auto shape types.
In the prior example we set the position and dimension values to the expression Inches(1.0). What’s that about?
Internally, PowerPoint stores length values in English Metric Units (EMU). This term might be worth a quick
Googling, but the short story is EMU is an integer unit of length, 914400 to the inch. Most lengths in Office doc-
uments are stored in EMU. 914400 has the great virtue that it is evenly divisible by a great many common factors,
allowing exact conversion between inches and centimeters, for example. Being an integer, it can be represented exactly
across serializations and across platforms.
As you might imagine, working directly in EMU is inconvenient. To make it easier, python-pptx provides a collection
of value types to allow easy specification and conversion into convenient units:
All shapes have a position on their slide and have a size. In general, position and size are specified when the shape is
created. Position and size can also be read from existing shapes and changed:
4.7.4 Fill
AutoShapes have an outline around their outside edge. What appears within that outline is called the shape’s fill.
The most common type of fill is a solid color. A shape may also be filled with a gradient, a picture, a pattern (like
cross-hatching for example), or may have no fill (transparent).
When a color is used, it may be specified as a specific RGB value or a color from the theme palette.
Because there are so many options, the API for fill is a bit complex. This code sets the fill of a shape to red:
This sets it to the theme color that appears as ‘Accent 1 - 25% Darker’ in the toolbar palette:
This sets the shape fill to transparent, or ‘No Fill’ as it’s called in the PowerPoint UI:
>>> shape.fill.background()
As you can see, the first step is to specify the desired fill type by calling the corresponding method on fill. Doing so
actually changes the properties available on the fill object. For example, referencing .fore_color on a fill object
after calling its .background() method will raise an exception:
4.7.5 Line
The outline of an AutoShape can also be formatted, including setting its color, width, dash (solid, dashed, dotted, etc.),
line style (single, double, thick-thin, etc.), end cap, join type, and others. At the time of writing, color and width can
be set using python-pptx:
>>> line.fill.solid()
>>> line.fill.fore_color
This makes sense for line formatting because a shape outline is most frequently set to a solid color. Accessing the fill
directly is required, for example, to set the line to transparent:
>>> line.fill.background()
Line width
>>> line.width
9525
>>> line.width.pt
0.75
>>> line.width = Pt(2.0)
>>> line.width.pt
2.0
Many auto shapes have adjustments. In PowerPoint, these show up as little yellow diamonds you can drag to change
the look of the shape. They’re a little fiddly to work with via a program, but if you have the patience to get them right,
you can achieve some remarkable effects with great precision.
There are a few concepts it’s worthwhile to grasp before trying to do serious work with adjustments.
First, adjustments are particular to a specific auto shape type. Each auto shape has between zero and eight adjustments.
What each of them does is arbitrary and depends on the shape design.
Conceptually, adjustments are guides, in many ways like the light blue ones you can align to in the PowerPoint UI and
other drawing apps. These don’t show, but they operate in a similar way, each defining an x or y value that part of the
shape will align to, changing the proportions of the shape.
Adjustment values are large integers, each based on a nominal value of 100,000. The effective value of an adjustment
is proportional to the width or height of the shape. So a value of 50,000 for an x-coordinate adjustment corresponds to
half the width of the shape; a value of 75,000 for a y-coordinate adjustment corresponds to 3/4 of the shape height.
Adjustment values can be negative, generally indicating the coordinate is to the left or above the top left corner (origin)
of the shape. Values can also be subject to limits, meaning their effective value cannot be outside a prescribed range.
In practice this corresponds to a point not being able to extend beyond the left side of the shape, for example.
Spending some time fooling around with shape adjustments in PowerPoint is time well spent to build an intuitive sense
of how they behave. You also might want to have opc-diag installed so you can look at the XML values that are
generated by different adjustments as a head start on developing your adjustment code.
The following code formats a callout shape using its adjustments:
callout_sp = shapes.add_shape(
MSO_SHAPE.LINE_CALLOUT_2_ACCENT_BAR, left, top, width, height
)
Intuitively, a placeholder is a pre-formatted container into which content can be placed. By providing pre-set format-
ting to its content, it places many of the formatting choices in the hands of the template designer while allowing the
end-user to concentrate on the actual content. This speeds the presentation development process while encouraging
visual consistency in slides created from the same template.
While their typical end-user behaviors are relatively simple, the structures that support their operation are more com-
plex. This page is for those who want to better understand the architecture of the placeholder subsystem and perhaps
be less prone to confusion at its sometimes puzzling behavior. If you don’t care why they work and just want to know
how to work with them, you may want to skip forward to the following page Working with placeholders.
Placeholders are an orthogonal category of shape, which is to say multiple shape types can be placeholders. In
particular, the auto shape (p:sp element), picture (p:pic element), and graphic frame (p:graphicFrame) shape types
can be a placeholder. The group shape (p:grpSp), connector (p:cxnSp), and content part (p:contentPart) shapes cannot
be a placeholder. A graphic frame placeholder can contain a table, a chart, or SmartArt.
A placeholder on a slide can be empty or filled. This is most evident with a picture placeholder. When unpopulated,
a placeholder displays customizable prompt text. A rich content placeholder will also display one or more content
insertion buttons when empty.
A text-only placeholder enters “populated” mode when the first character of text is entered and returns to “unpop-
ulated” mode when the last character of text is removed. A rich-content placeholder enters populated mode when
content such as a picture is inserted and returns to unpopulated mode when that content is deleted. In order to delete
a populated placeholder, the shape must be deleted twice. The first delete removes the content and restores the place-
holder to unpopulated mode. An additional delete will remove the placeholder itself. A deleted placeholder can be
restored by reapplying the layout.
A placeholder appearing on a slide is only part of the overall placeholder mechanism. Placeholder behavior requires
three different categories of placeholder shape; those that exist on a slide master, those on a slide layout, and those that
ultimately appear on a slide in a presentation.
These three categories of placeholder participate in a property inheritance hierarchy, either as an inheritor, an inheritee,
or both. Placeholder shapes on masters are inheritees only. Conversely placeholder shapes on slides are inheritors
only. Placeholders on slide layouts are both, a possible inheritor from a slide master placeholder and an inheritee to
placeholders on slides linked to that layout.
A layout inherits from its master differently than a slide inherits from its layout. A layout placeholder inherits from the
master placeholder sharing the same type. A slide placeholder inherits from the layout placeholder having the same
idx value.
In general, all formatting properties are inherited from the “parent” placeholder. This includes position and size as well
as fill, line, and font. Any directly applied formatting overrides the corresponding inherited value. Directly applied
formatting can be removed be reapplying the layout.
4.8.5 Glossary
Placeholders can make adding content a lot easier. If you’ve ever added a new textbox to a slide from scratch and
noticed how many adjustments it took to get it the way you wanted you understand why. The placeholder is in the
right position with the right font size, paragraph alignment, bullet style, etc., etc. Basically you can just click and type
in some text and you’ve got a slide.
A placeholder can be also be used to place a rich-content object on a slide. A picture, table, or chart can each be
inserted into a placeholder and so take on the position and size of the placeholder, as well as certain of its formatting
attributes.
Every placeholder is also a shape, and so can be accessed using the shapes property of a slide. However, when
looking for a particular placeholder, the placeholders property can make things easier.
The most reliable way to access a known placeholder is by its idx value. The idx value of a placeholder is the integer
key of the slide layout placeholder it inherits properties from. As such, it remains stable throughout the life of the slide
and will be the same for any slide created using that layout.
It’s usually easy enough to take a look at the placeholders on a slide and pick out the one you want:
>>> slide.placeholders[1]
<pptx.parts.slide.PicturePlaceholder object at 0x10d094590>
>>> slide.placeholders[2].name
'Text Placeholder 3'
Note: Item access on the placeholders collection is like that of a dictionary rather than a list. While the key used
above is an integer, the lookup is on idx values, not position in a sequence. If the provided value does not match the
idx value of one of the placeholders, KeyError will be raised. idx values are not necessarily contiguous.
In general, the idx value of a placeholder from a built-in slide layout (one provided with PowerPoint) will be between
0 and 5. The title placeholder will always have idx 0 if present and any other placeholders will follow in sequence,
top to bottom and left to right. A placeholder added to a slide layout by a user in PowerPoint will receive an idx value
starting at 10.
A placeholder behaves differently that other shapes in some ways. In particular, the value of its shape_type attribute
is unconditionally MSO_SHAPE_TYPE.PLACEHOLDER regardless of what type of placeholder it is or what type of
content it contains:
To find out more, it’s necessary to inspect the contents of the placeholder’s placeholder_format attribute. All
shapes have this attribute, but accessing it on a non-placeholder shape raises ValueError. The is_placeholder
attribute can be used to determine whether a shape is a placeholder:
Another way a placeholder acts differently is that it inherits its position and size from its layout placeholder. This
inheritance is overridden if the position and size of a placeholder are changed.
Certain placeholder types have specialized methods for inserting content. In the current release, the picture, table, and
chart placeholders have content insertion methods. Text can be inserted into title and body placeholders in the same
way text is inserted into an auto shape.
PicturePlaceholder.insert_picture()
Note: A reference to a picture placeholder becomes invalid after its insert_picture() method is called. This is
because the process of inserting a picture replaces the original p:sp XML element with a new p:pic element containing
the picture. Any attempt to use the original placeholder reference after the call will raise AttributeError. The
new placeholder is the return value of the insert_picture() call and may also be obtained from the placeholders
collection using the same idx key.
A picture inserted in this way is stretched proportionately and cropped to fill the entire placeholder. Best results are
achieved when the aspect ratio of the source image and placeholder are the same. If the picture is taller in aspect than
the placeholder, its top and bottom are cropped evenly to fit. If it is wider, its left and right sides are cropped evenly.
Cropping can be adjusted using the crop properties on the placeholder, such as crop_bottom.
TablePlaceholder.insert_table()
The table placeholder has an insert_table() method. The built-in template has no layout containing a table
placeholder, so this example assumes a starting presentation named having-table-placeholder.pptx having
a table placeholder with idx 10 on its second slide layout:
>>> prs = Presentation('having-table-placeholder.pptx')
>>> slide = prs.slides.add_slide(prs.slide_layouts[1])
>>> placeholder = slide.placeholders[10] # idx key, not position
>>> placeholder.name
'Table Placeholder 1'
>>> placeholder.placeholder_format.type
TABLE (12)
>>> graphic_frame = placeholder.insert_table(rows=2, cols=2)
>>> table = graphic_frame.table
>>> len(table.rows), len(table.columns)
(2, 2)
A table inserted in this way has the position and width of the original placeholder. Its height is proportional to the
number of rows.
Like all rich-content insertion methods, a reference to a table placeholder becomes invalid after its
insert_table() method is called. This is because the process of inserting rich content replaces the original
p:sp XML element with a new element, a p:graphicFrame in this case, containing the rich-content object. Any at-
tempt to use the original placeholder reference after the call will raise AttributeError. The new placeholder is
the return value of the insert_table() call and may also be obtained from the placeholders collection using the
original idx key, 10 in this case.
Note: The return value of the insert_table() method is a PlaceholderGraphicFrame object, which has
all the properties and methods of a GraphicFrame object along with those specific to placeholders. The inserted
table is contained in the graphic frame and can be obtained using its table property.
ChartPlaceholder.insert_chart()
The chart placeholder has an insert_chart() method. The presentation template built into python-
pptx has no layout containing a chart placeholder, so this example assumes a starting presentation named
having-chart-placeholder.pptx having a chart placeholder with idx 10 on its second slide layout:
>>> from pptx.chart.data import ChartData
>>> from pptx.enum.chart import XL_CHART_TYPE
(continues on next page)
A chart inserted in this way has the position and size of the original placeholder.
Note the return value from insert_chart() is a PlaceholderGraphicFrame object, not the chart itself. A
PlaceholderGraphicFrame object has all the properties and methods of a GraphicFrame object along with
those specific to placeholders. The inserted chart is contained in the graphic frame and can be obtained using its
chart property.
Like all rich-content insertion methods, a reference to a chart placeholder becomes invalid after its
insert_chart() method is called. This is because the process of inserting rich content replaces the original
p:sp XML element with a new element, a p:graphicFrame in this case, containing the rich-content object. Any at-
tempt to use the original placeholder reference after the call will raise AttributeError. The new placeholder is
the return value of the insert_chart() call and may also be obtained from the placeholders collection using the
original idx key, 10 in this case.
Almost all slide layouts have a title placeholder, which any slide based on the layout inherits when the layout is applied.
Accessing a slide’s title is a common operation and there’s a dedicated attribute on the shape tree for it:
title_placeholder = slide.shapes.title
title_placeholder.text = 'Air-speed Velocity of Unladen Swallows'
Auto shapes and table cells can contain text. Other shapes can’t. Text is always manipulated the same way, regardless
of its container.
Text exists in a hierarchy of three levels:
• Shape.text_frame
• TextFrame.paragraphs
• _Paragraph.runs
All the text in a shape is contained in its text frame. A text frame has vertical alignment, margins, wrapping and auto-fit
behavior, a rotation angle, some possible 3D visual features, and can be set to format its text into multiple columns. It
also contains a sequence of paragraphs, which always contains at least one paragraph, even when empty.
A paragraph has line spacing, space before, space after, available bullet formatting, tabs, outline/indentation level, and
horizontal alignment. A paragraph can be empty, but if it contains any text, that text is contained in one or more runs.
A run exists to provide character level formatting, including font typeface, size, and color, an optional hyperlink target
URL, bold, italic, and underline styles, strikethrough, kerning, and a few capitalization styles like all caps.
Let’s run through these one by one. Only features available in the current release are shown.
As mentioned, not all shapes have a text frame. So if you’re not sure and you don’t want to catch the possible exception,
you’ll want to check before attempting to access it:
for shape in slide.shapes:
if not shape.has_text_frame:
continue
text_frame = shape.text_frame
# do things with the text frame
...
A text frame always contains at least one paragraph. This causes the process of getting multiple paragraphs into a
shape to be a little clunkier than one might like. Say for example you want a shape with three paragraphs:
paragraph_strs = [
'Egg, bacon, sausage and spam.',
'Spam, bacon, sausage and spam.',
'Spam, egg, spam, spam, bacon and spam.'
]
text_frame = shape.text_frame
text_frame.clear() # remove any existing paragraphs, leaving one empty one
p = text_frame.paragraphs[0]
p.text = paragraph_strs[0]
Only runs can actually contain text. Assigning a string to the .text attribute on a shape, text frame, or paragraph is
a shortcut method for placing text in a run contained by those objects. The following two snippets produce the same
result:
shape.text = 'foobar'
# is equivalent to ...
(continues on next page)
text_frame = shape.text_frame
text_frame.clear()
p = text_frame.paragraphs[0]
run = p.add_run()
run.text = 'foobar'
The following produces a shape with a single paragraph, a slightly wider bottom than top margin (these default to
0.05”), no left margin, text aligned top, and word wrapping turned off. In addition, the auto-size behavior is set to
adjust the width and height of the shape to fit its text. Note that vertical alignment is set on the text frame. Horizontal
alignment is set on each paragraph:
text_frame = shape.text_frame
text_frame.text = 'Spam, eggs, and spam'
text_frame.margin_bottom = Inches(0.08)
text_frame.margin_left = 0
text_frame.vertical_anchor = MSO_ANCHOR.TOP
text_frame.word_wrap = False
text_frame.auto_size = MSO_AUTO_SIZE.SHAPE_TO_FIT_TEXT
The possible values for TextFrame.auto_size and TextFrame.vertical_anchor are specified by the
enumeration MSO_AUTO_SIZE and MSO_VERTICAL_ANCHOR respectively.
The following produces a shape containing three left-aligned paragraphs, the second and third indented (like sub-
bullets) under the first:
paragraph_strs = [
'Egg, bacon, sausage and spam.',
'Spam, bacon, sausage and spam.',
'Spam, egg, spam, spam, bacon and spam.'
]
text_frame = shape.text_frame
text_frame.clear()
p = text_frame.paragraphs[0]
p.text = paragraph_strs[0]
p.alignment = PP_ALIGN.LEFT
Character level formatting is applied at the run level, using the .font attribute. The following formats a sentence in
18pt Calibri Bold and applies the theme color Accent 1.
from pptx.dml.color import RGBColor
from pptx.enum.dml import MSO_THEME_COLOR
from pptx.util import Pt
text_frame = shape.text_frame
text_frame.clear() # not necessary for newly-created shape
p = text_frame.paragraphs[0]
run = p.add_run()
run.text = 'Spam, eggs, and spam'
font = run.font
font.name = 'Calibri'
font.size = Pt(18)
font.bold = True
font.italic = None # cause value to be inherited from theme
font.color.theme_color = MSO_THEME_COLOR.ACCENT_1
If you prefer, you can set the font color to an absolute RGB value. Note that this will not change color when the theme
is changed:
font.color.rgb = RGBColor(0xFF, 0x7F, 0x50)
python-pptx supports adding charts and modifying existing ones. Most chart types other than 3D types are supported.
prs.save('chart-01.pptx')
The remaining code will leave out code we’ve already seen and only show imports, for example, when they’re used
for the first time, just to keep the focus on the new bits. Let’s create a multi-series chart to use for these examples:
chart_data = ChartData()
chart_data.categories = ['East', 'West', 'Midwest']
chart_data.add_series('Q1 Sales', (19.2, 21.4, 16.7))
chart_data.add_series('Q2 Sales', (22.3, 28.6, 15.2))
chart_data.add_series('Q3 Sales', (20.4, 26.3, 14.2))
graphic_frame = slide.shapes.add_chart(
XL_CHART_TYPE.COLUMN_CLUSTERED, x, y, cx, cy, chart_data
)
chart = graphic_frame.chart
Notice that we captured the shape reference returned by the add_chart() call as graphic_frame and then
extracted the chart object from the graphic frame using its chart property. We’ll need the chart reference to get to
the properties we’ll need in the next steps. The add_chart() method doesn’t directly return the chart object. That’s
because a chart is not itself a shape. Rather it’s a graphical (DrawingML) object contained in the graphic frame shape.
Tables work this way too, also being contained in a graphic frame shape.
The charts so far use a discrete set of values for the independent variable (the X axis, roughly speaking). These are
perfect when your values fall into a well-defined set of categories. However, there are many cases, particularly in
science and engineering, where the independent variable is a continuous value, such as temperature or frequency.
These are supported in PowerPoint by XY (aka. scatter) charts. A bubble chart is essentially an XY chart where the
marker size is used to reflect an additional value, effectively adding a third dimension to the chart.
Because the independent variable is continuous, in general, the series do not all share the same X values. This requires
a somewhat different data structure and that is provided for by distinct XyChartData and BubbleChartData
objects used to specify the data behind charts of these types:
chart_data = XyChartData()
chart = slide.shapes.add_chart(
XL_CHART_TYPE.XY_SCATTER, x, y, cx, cy, chart_data
).chart
Creation of a bubble chart is very similar, having an additional value for each data point that specifies the bubble size:
chart_data = BubbleChartData()
chart = slide.shapes.add_chart(
XL_CHART_TYPE.BUBBLE, x, y, cx, cy, chart_data
).chart
4.11.4 Axes
category_axis = chart.category_axis
category_axis.has_major_gridlines = True
category_axis.minor_tick_mark = XL_TICK_MARK.OUTSIDE
category_axis.tick_labels.font.italic = True
category_axis.tick_labels.font.size = Pt(24)
value_axis = chart.value_axis
value_axis.maximum_scale = 50.0
value_axis.minor_tick_mark = XL_TICK_MARK.OUTSIDE
value_axis.has_minor_gridlines = True
tick_labels = value_axis.tick_labels
tick_labels.number_format = '0"%"'
tick_labels.font.bold = True
tick_labels.font.size = Pt(14)
Okay, that was probably going a bit too far. But it gives us an idea of the kinds of things we can do with the value and
category axes. Let’s undo this part and go back to the version we had before.
Let’s add some data labels so we can see exactly what the value for each bar is:
plot = chart.plots[0]
plot.has_data_labels = True
data_labels = plot.data_labels
data_labels.font.size = Pt(13)
data_labels.font.color.rgb = RGBColor(0x0A, 0x42, 0x80)
data_labels.position = XL_LABEL_POSITION.INSIDE_END
Here we needed to access a Plot object to gain access to the data labels. A plot is like a sub-chart, containing one or
more series and drawn as a particular chart type, like column or line. This distinction is needed for charts that combine
more than one type, like a line chart appearing on top of a column chart. A chart like this would have two plot objects,
one for the series appearing as columns and the other for the lines. Most charts only have a single plot and python-pptx
doesn’t yet support creating multi-plot charts, but you can access multiple plots on a chart that already has them.
In the Microsoft API, the name ChartGroup is used for this object. I found that term confusing for a long time while I
was learning about MS Office charts so I chose the name Plot for that object in python-pptx.
4.11.6 Legend
A legend is often useful to have on a chart, to give a name to each series and help a reader tell which one is which:
chart.has_legend = True
chart.legend.position = XL_LEGEND_POSITION.RIGHT
chart.legend.include_in_layout = False
A line chart is added pretty much the same way as a bar or column chart, the main difference being the chart type
provided in the add_chart() call:
chart_data = ChartData()
chart_data.categories = ['Q1 Sales', 'Q2 Sales', 'Q3 Sales']
chart_data.add_series('West', (32.2, 28.4, 34.7))
chart_data.add_series('East', (24.3, 30.6, 20.2))
chart_data.add_series('Midwest', (20.4, 18.3, 26.2))
chart.has_legend = True
chart.legend.include_in_layout = False
chart.series[0].smooth = True
I switched the categories and series data here to better suit a line chart. You can see the line for the “West” region is
smoothed into a curve while the other two have their points connected with straight line segments.
A pie chart is a little special in that it only ever has a single series and doesn’t have any axes:
chart_data = ChartData()
chart_data.categories = ['West', 'East', 'North', 'South', 'Other']
chart_data.add_series('Series 1', (0.135, 0.324, 0.180, 0.235, 0.126))
chart = slide.shapes.add_chart(
XL_CHART_TYPE.PIE, x, y, cx, cy, chart_data
).chart
chart.has_legend = True
chart.legend.position = XL_LEGEND_POSITION.BOTTOM
chart.legend.include_in_layout = False
chart.plots[0].has_data_labels = True
data_labels = chart.plots[0].data_labels
data_labels.number_format = '0%'
data_labels.position = XL_LABEL_POSITION.OUTSIDE_END
This should be enough to get you started with adding charts to your presentation with python-pptx. There are more
details in the API documentation for charts here: Charts
About colors
By default, the colors assigned to each series in a chart are the theme colors Accent 1 through Accent 6, in that order.
If you have more than six series, darker and lighter versions of those same colors are used. While it’s possible to assign
specific colors to data points (bar, line, pie segment, etc.) for at least some chart types, the best strategy to start with is
changing the theme colors in your starting “template” presentation.
PowerPoint allows text and numbers to be presented in tabular form (aligned rows and columns) in a reasonably
flexible way. A PowerPoint table is not nearly as functional as an Excel spreadsheet, and is definitely less powerful
than a table in Microsoft Word, but it serves well for most presentation purposes.
4.12.1 Concepts
There are a few terms worth reviewing as a basis for understanding PowerPoint tables:
table A table is a matrix of cells arranged in aligned rows and columns. This orderly arrangement allows a reader
to more easily make sense of relatively large number of individual items. It is commonly used for displaying
numbers, but can also be used for blocks of text.
cell An individual content “container” within a table. A cell has a text-frame in which it holds that content. A
PowerPoint table cell can only contain text. I cannot hold images, other shapes, or other tables.
A cell has a background fill, borders, margins, and several other formatting settings that can be customized on a
cell-by-cell basis.
row A side-by-side sequence of cells running across the table, all sharing the same top and bottom boundary.
column A vertical sequence of cells spanning the height of the table, all sharing the same left and right boundary.
table grid, also cell grid The underlying cells in a PowerPoint table are strictly regular. In a three-by-three table
there are nine grid cells, three in each row and three in each column. The presence of merged cells can obscure
portions of the cell grid, but not change the number of cells in the grid. Access to a table cell in python-pptx is
always via that cell’s coordinates in the cell grid, which may not conform to its visual location (or lack thereof)
in the table.
merged cell A cell can be “merged” with adjacent cells, horizontally, vertically, or both, causing the resulting cell to
look and behave like a single cell that spans the area formerly occupied by those individual cells.
merge-origin cell The top-left grid-cell in a merged cell has certain special behaviors. The content of that cell is
what appears on the slide; content of any “spanned” cells is hidden. In python-pptx a merge-origin cell can be
identified with the _Cell.is_merge_origin property. Such a cell can report the size of the merged cell
with its span_height and span_width properties, and can be “unmerged” back to its underlying grid cells
using its split() method.
spanned-cell A grid-cell other than the merge-origin cell that is “occupied” by a merged cell is called a spanned cell.
Intuitively, the merge-origin cell “spans” the other grid cells within its area. A spanned cell can be identified
with its _Cell.is_spanned property. A merge-origin cell is not itself a spanned cell.
>>> shape
<pptx.shapes.graphfrm.GraphicFrame object at 0x1022816d0>
>>> shape.has_table
True
>>> table = shape.table
>>> table
<pptx.table.Table object at 0x1096f8d90>
A placeholder allows you to specify the position and size of a shape as part of the presentation “template”, and to place
a shape of your choosing into that placeholder when authoring a presentation based on that template. This can lead to
a better looking presentation, with objects appearing in a consistent location from slide-to-slide.
Placeholders come in different types, one of which is a table placeholder. A table placeholder behaves like other
placeholders except it can only accept insertion of a table. Other placeholder types accept text bullets or charts.
There is a subtle distinction between a layout placeholder and a slide placeholder. A layout placeholder appears in
a slide layout, and defines the position and size of the placeholder “cloned” from it onto each slide created with that
layout. As long as you don’t adjust the position or size of the slide placeholder, it will inherit it’s position and size
from the layout placeholder it derives from.
To insert a table into a table placeholder, you need a slide layout that includes a table placeholder, and you need to
create a slide using that layout. These examples assume that the third slide layout in template.pptx includes a table
placeholder:
Accessing the table placeholder. Generally, the easiest way to access a placeholder shape is to know its position in the
slide.shapes collection. If you always use the same template, it will always show up in the same position:
Inserting a table. A table is inserted into the placeholder by calling its insert_table() method and providing the
desired number of rows and columns:
The return value is a GraphicFrame shape containing the new table, not the table object itself. Use the table
property of that shape to access the table object:
The containing shape controls the position and size. Everything else, like accessing cells and their contents, is done
from the table object.
All content in a table is in a cell, so getting a reference to one of those is a good place to start:
The cell is specified by its row, column coordinates as zero-based offsets. The top-left cell is at row, column (0, 0).
Like an auto-shape, a cell has a text-frame and can contain arbitrary text divided into paragraphs and runs. Any desired
character formatting can be applied individually to each run.
Often however, cell text is just a simple string. For these cases the read/write _Cell.text property can be the
quickest way to set cell contents.
A merged cell is produced by specifying two diagonal cells. The merged cell will occupy all the grid cells in the
rectangular region specified by that diagonal:
A merged cell can be restored to its underlying grid cells by calling the split() method on its merge-origin cell.
Calling split() on a cell that is not a merge-origin raises ValueError:
Note that the content migration performed as part of the .merge() operation was not reversed.
def iter_merge_origins(table):
"""Generate each merge-origin cell in *table*.
def merged_cell_report(cell):
"""Return str summarizing position and size of merged *cell*."""
return (
'merged cell at row %d, col %d, %d cells high and %d cells wide'
% (cell.row_idx, cell.col_idx, cell.span_height, cell.span_width)
)
Use Case: Access only cells that display text (are not spanned):
def iter_visible_cells(table):
return (cell for cell in table.iter_cells() if not cell.is_spanned)
def has_merged_cells(table):
for cell in table.iter_cells():
if cell.is_merge_origin:
return True
return False
A slide can have notes associated with it. These are perhaps most commonly encountered in the notes pane, below the
slide in PowerPoint “Normal” view where it may say “Click to add notes”.
The notes added here appear each time that slide is present in the main pane. They also appear in Presenter View and
in Notes Page view, both available from the menu.
Notes can contain rich text, commonly bullets, bold, varying font sizes and colors, etc. The Notes Page view has
somewhat more powerful tools for editing the notes text than the note pane in Normal view.
In the API and the underlying XML, the object that contains the text is known as a Notes Slide. This is because
internally, a notes slide is actually a specialized instance of a slide. It contains shapes, many of which are placeholders,
and allows inserting of new shapes such as pictures (a logo perhaps) auto shapes, tables, and charts. Consequently,
working with a notes slide is very much like working with a regular slide.
Each slide can have zero or one notes slide. A notes slide is created the first time it is used, generally perhaps by
adding notes text to a slide. Once created, it stays, even if all the text is deleted.
A new notes slide is created using the Notes Master as a template. A presentation has no notes master when newly
created in PowerPoint. One is created according to a PowerPoint-internal preset default the first time it is needed,
which is generally when the first notes slide is created. It’s possible one can also be created by entering the Notes
Master view and almost certainly is created by editing the master found there (haven’t tried it though). A presentation
can have at most one notes master.
The notes master governs the look and feel of notes pages, which can be viewed on-screen but are really designed
for printing out. So if you want your notes page print-outs to look different from the default, you can make a lot of
customizations by editing the notes master. You access the notes master editor using View > Master > Notes Master
on the menu (on my version at least). Notes slides created using python-pptx will have the look and feel of the notes
master in the presentation file you opened to create the presentation.
On creation, certain placeholders (slide image, notes, slide number) are copied from the notes master onto the new
notes slide (if they have not been removed from the master). These “cloned” placeholders inherit position, size, and
formatting from their corresponding notes master placeholder. If the position, size, or formatting of a notes slide
placeholder is changed, the changed property is no long inherited (unchanged properties, however, continue to be
inherited).
Enough talk, let’s show some code. Let’s say you have a slide you’re working with and you want to see if it has a notes
slide yet:
>>> slide.has_notes_slide
False
What we haven’t explicitly seen so far is the shapes on a slide master. It’s easy to get started with that:
This notes placeholder is just like a body placeholder we saw a couple sections back. You can change its position,
size, and many other attributes, as well as get at its text via its text frame.
You can also access the other placeholders:
In the common case, the notes slide contains only placeholders. However, if you added an image, for example, to the
notes slide, that would show up as well. Note that if you added that image to the notes master, perhaps a logo, it would
appear on the notes slide “visually”, but would not appear as a shape in the notes slide shape collection. Rather, it is
visually “inherited” from the notes master.
The use case that drove me to begin work on this library has been to automate the building of slides that are tedious
to compose by hand. As an example, consider the task of composing a slide with an array of 10 headshot images of
folks in a particular department, with the person’s name and title next to their picture. After doing this a dozen times
and struggling to get all the alignment and sizes to the point where my attention to detail is satisfied, well, my coding
fingers got quite itchy.
However I believe a broader application will be server-side document generation on non-Windows server platforms,
Linux primarily I expect. In my organization, I have found an apparently insatiable demand for PowerPoint documents
as a means of communication. Once one rises beyond the level of project manager it seems the willingness to interpret
text longer than a bullet point atrophies quite rapidly and PowerPoint becomes an everyday medium. I’ve imagined
it might be pretty cool to be able to generate a “presentation-ready” deck for a salesperson that includes a particular
subset of the product catalog they could generate with a few clicks to use in a sales presentation, for example. As you
come up with applications I’d love to hear about them.
4.15 Concepts
python-pptx is completely object-oriented, and in general any operations you perform with it will be on an object. The
root object for a presentation is Presentation. API details are provided on the modules pages, but here are some
basics to get you started, especially some relationships you might find surprising at first.
A presentation is loaded by constructing a new Presentation instance, passing in the path to a presentation to be
loaded:
from pptx import Presentation
path = 'slide-deck-foo.pptx'
prs = Presentation(path)
python-pptx also contains a default template, and if you construct a Presentation instance without a path, a
presentation based on that default template is loaded. This can be handy when you want to get started quickly, and
most of the examples in this documentation use the default template.:
# start with default presentation
prs = Presentation()
Note that there is currently no distinction between templates and presentations in python-pptx as there is in the Pow-
erPoint® client, there are only presentations. To use a “template” for a presentation you simply create a presentation
with all the styles, logo, and layouts you want, delete all the slides (or leave some in if it suits), and then load that as
your starting place.
A presentation has a list of slide masters and a list of slides. Let’s start with a discussion of the slide masters.
One fact some find surprising (I did) is that a presentation file can have more than one slide master. It’s quite uncommon
in my experience to find presentations that make use of this feature, but it’s entirely supported. The only time I’ve seen
this happen is when slides from a “foreign” presentation are pasted into another deck; if you want the formatting and
backgrounds from the other deck to be preserved on the pasted-in slides, the slide master and its slide layouts need to
come with. Consequently, the presentation needs to maintain a list of slide masters, not just a single one, even though
perhaps 99% of the time you only ever use the one. To make things a little easier for the 99% situation, you can refer
to the first slide master as though it were the only one:
prs = Presentation()
slide_master = prs.slide_masters[0]
# is equivalent to
slide_master = prs.slide_master
Another fact that might be surprising is that slide layouts belong to a slide master, not directly to a presentation, so
normally you have to access the slide layouts via their slide master. Since this is subject to the same 99% situation
described above, the slide layouts belonging to the first slide master can also be accessed directly from the presentation
via syntactic sugar:
prs = Presentation()
title_slide_layout = prs.slide_masters[0].slide_layouts[0]
# is equivalent to:
title_slide_layout = prs.slide_layouts[0]
4.15.3 Slides
The slides in a presentation belong to the presentation object and are accessed using the slides attribute:
prs = Presentation(path)
first_slide = prs.slides[0]
Adding a slide
Adding a slide is accomplished by calling the add_slide() method on the slides attribute of the presentation.
A slide layout must be passed in to specify the layout the new slide should take on:
prs = Presentation()
title_slide_layout = prs.slide_layouts[0]
new_slide = prs.slides.add_slide(title_slide_layout)
Community Guide
5.2 Support
We’d love to hear from you if you like python-pptx, want a new feature, find a bug, need help using it, or just have a
word of encouragement.
The mailing list for python-pptx is python-pptx@googlegroups.com
The issue tracker is on github at scanny/python-pptx.
Feature requests are best broached initially on the mailing list, they can be added to the issue tracker once we’ve
clarified the best approach, particularly the appropriate API signature.
0.6.22 (2023-08-28)
51
python-pptx Documentation, Release 0.6.22
0.6.21 (2021-09-20)
0.6.20 (2021-09-14)
0.6.19 (2021-05-17)
• Add shapes.add_ole_object(), allowing arbitrary Excel or other binary file to be embedded as a shape on a slide.
The OLE object is represented as an icon.
0.6.18 (2019-05-02)
• .text property getters encode line-break as a vertical-tab (VT, ‘v’, ASCII 11/x0B). This is consistent with Pow-
erPoint’s copy/paste behavior and allows like-breaks (soft carriage-return) to be distinguished from paragraph
boundary. Previously, a line-break was encoded as a newline (‘n’) and was not distinguishable from a paragraph
boundary.
.text properties include Shape.text, _Cell.text, TextFrame.text, _Paragraph.text and _Run.text.
• .text property setters accept vertical-tab character and place a line-break element in that location. All other
control characters other than horizontal-tab (‘t’) and newline (‘n’) in range x00-x1F are accepted and escaped
with plain-text like “_x001B” for ESC (ASCII 27).
Previously a control character other than tab or newline in an assigned string would trigger an exception related
to invalid XML character.
0.6.17 (2018-12-16)
0.6.16 (2018-11-09)
0.6.15 (2018-09-24)
0.6.14 (2018-09-24)
• Add _Cell.merge()
• Add _Cell.split()
• Add _Cell.__eq__()
• Add _Cell.is_merge_origin
• Add _Cell.is_spanned
• Add _Cell.span_height
• Add _Cell.span_width
• Add _Cell.text getter
• Add Table.iter_cells()
• Move pptx.shapes.table module to pptx.table
• Add user documentation ‘Working with tables’
0.6.13 (2018-09-10)
• Add Chart.font
• Fix #293 Can’t hide title of single-series Chart
• Fix shape.width value is not type Emu
• Fix add a:defRPr with c:rich (fixes some font inheritance breakage)
0.6.12 (2018-08-11)
• Add Picture.auto_shape_type
• Remove Python 2.6 testing from build
• Update dependencies to avoid vulnerable Pillow version
• Fix #260, #301, #382, #401
• Add _Paragraph.add_line_break()
• Add Connector.line
0.6.11 (2018-07-25)
0.6.10 (2018-06-11)
• Add shape.shadow property to autoshape, connector, picture, and group shape, returning a ShadowFormat ob-
ject.
• Add ShadowFormat object with read/write (boolean) .inherit property.
• Fix #328 add support for 26+ series in a chart
0.6.9 (2018-05-08)
• Add Picture.crop_x setters, allowing picture cropping values to be set, in addition to interrogated.
• Add Slide.background and SlideMaster.background, allowing the background fill to be set for an individual slide
or for all slides based on a slide master.
• Add option shapes parameter to Shapes.add_group_shape, allowing a group shape to be formed from a number
of existing shapes.
• Improve efficiency of Shapes._next_shape_id property to improve performance on high shape-count slides.
0.6.8 (2018-04-18)
• Add GroupShape, providing properties specific to a group shape, including its shapes property.
• Add GroupShapes, providing access to shapes contained in a group shape.
• Add SlideShapes.add_group_shape(), allowing a group shape to be added to a slide.
• Add GroupShapes.add_group_shape(), allowing a group shape to be added to a group shape, enabling recursive,
multi-level groups.
• Add support for adding jump-to-named-slide behavior to shape and run hyperlinks.
0.6.7 (2017-10-30)
• Add SlideShapes.build_freeform(), allowing freeform shapes (such as maps) to be specified and added to a slide.
• Add support for patterned fills.
• Add LineFormat.dash_style to allow interrogation and setting of dashed line styles.
0.6.6 (2017-06-17)
0.6.5 (2017-03-21)
0.6.4 (2017-03-17)
0.6.3 (2017-02-28)
• add DataLabel.font
• add Axis.axis_title
0.6.2 (2017-01-03)
0.6.1 (2016-10-09)
0.6.0 (2016-08-18)
0.5.8 (2015-11-27)
0.5.7 (2015-01-17)
0.5.6 (2014-12-06)
0.5.5 (2014-11-17)
0.5.4 (2014-11-15)
• feature #43 - image native size in shapes.add_picture() is now calculated based on DPI attribute in image file, if
present, defaulting to 72 dpi.
• feature #113 - Add Paragraph.space_before, Paragraph.space_after, and Paragraph.line_spacing
0.5.3 (2014-11-09)
0.5.2 (2014-10-26)
0.5.1 (2014-09-22)
0.5.0 (2014-09-13)
• Add support for creating and manipulating bar, column, line, and pie charts
• Major refactoring of XML layer (oxml)
• Rationalized graphical object shape access Note backward incompatibilities below
BACKWARD INCOMPATIBILITIES:
A table is no longer treated as a shape. Rather it is a graphical object contained in a GraphicFrame shape, as are Chart
and SmartArt objects.
Example:
table = shapes.add_table(...)
# becomes
graphic_frame = shapes.add_table(...)
table = graphic_frame.table
# or
table = shapes.add_table(...).table
As the enclosing shape, the id, name, shape type, position, and size are attributes of the enclosing GraphicFrame
object.
The contents of a GraphicFrame shape can be identified using three available properties on a shape: has_table,
has_chart, and has_smart_art. The enclosed graphical object is obtained using the properties GraphicFrame.table
and GraphicFrame.chart. SmartArt is not yet supported. Accessing one of these properties on a GraphicFrame not
containing the corresponding object raises an exception.
0.4.2 (2014-04-29)
• fix: issue #88 – raises on supported image file having uppercase extension
• fix: issue #89 – raises on add_slide() where non-contiguous existing ids
0.4.1 (2014-04-29)
0.3.2 (2014-02-07)
• Hotfix: issue #80 generated presentations fail to load in Keynote and other Apple applications
0.3.1 (2014-01-10)
• Hotfix: failed to load certain presentations containing images with uppercase extension
0.3.0 (2013-12-12)
• Add read/write font color property supporting RGB, theme color, and inherit color types
• Add font typeface and italic support
• Add text frame margins and word-wrap
• Add support for external relationships, e.g. linked spreadsheet
• Add hyperlink support for text run in shape and table cell
• Add fill color and brightness for shape and table cell, fill can also be set to transparent (no fill)
• Add read/write position and size properties to shape and picture
• Replace PIL dependency with Pillow
• Restructure modules to better suit size of library
0.2.6 (2013-06-22)
0.2.5 (2013-06-11)
0.2.4 (2013-05-16)
• Add support for auto shapes (e.g. polygons, flowchart symbols, etc.)
0.2.3 (2013-05-05)
0.2.2 (2013-03-25)
• Add support for opening and saving a presentation from/to a file-like object.
• Refactor XML handling to use lxml objectify
0.2.1 (2013-02-25)
0.2.0 (2013-02-10)
API Documentation
6.1 Presentations
A presentation is opened using the Presentation() function, provided directly by the pptx package:
This function returns a Presentation object which is the root of a graph containing the components that constitute
a presentation, e.g. slides, shapes, etc. All existing presentation components are referenced by traversing the graph
and new objects are added to the graph by calling a method on that object’s container. Consequently, python-pptx
objects are generally not constructed directly.
Example:
# load a presentation
prs = Presentation(path_to_pptx_file)
This function is the only reference that must be imported to work with presentation files. Typical use interacts with
many other classes, but there is no need to construct them as they are accessed using a property or method of their
containing object.
pptx.Presentation(pptx=None)
Return a Presentation object loaded from pptx, where pptx can be either a path to a .pptx file (a string)
or a file-like object. If pptx is missing or None, the built-in default presentation “template” is loaded.
61
python-pptx Documentation, Release 0.6.22
class pptx.presentation.Presentation
PresentationML (PML) presentation.
Not intended to be constructed directly. Use pptx.Presentation() to open or create a presentation.
core_properties
Instance of CoreProperties holding the read/write Dublin Core document properties for this presen-
tation.
notes_master
Instance of NotesMaster for this presentation. If the presentation does not have a notes master, one is
created from a default template and returned. The same single instance is returned on each call.
save(file)
Save this presentation to file, where file can be either a path to a file (a string) or a file-like object.
slide_height
Height of slides in this presentation, in English Metric Units (EMU). Returns None if no slide width is
defined. Read/write.
slide_layouts
Sequence of SlideLayout instances belonging to the first SlideMaster of this presentation. A
presentation can have more than one slide master and each master will have its own set of layouts. This
property is a convenience for the common case where the presentation has only a single slide master.
slide_master
First SlideMaster object belonging to this presentation. Typically, presentations have only a single
slide master. This property provides simpler access in that common case.
slide_masters
Sequence of SlideMaster objects belonging to this presentation
slide_width
Width of slides in this presentation, in English Metric Units (EMU). Returns None if no slide width is
defined. Read/write.
slides
Slides object containing the slides in this presentation.
Each Presentation object has a CoreProperties object accessed via its core_properties attribute that
provides read/write access to the so-called core properties for the document. The core properties are author, category,
comments, content_status, created, identifier, keywords, language, last_modified_by, last_printed, modified, revision,
subject, title, and version.
Each property is one of three types, str, datetime.datetime, or int. String properties are limited in length
to 255 characters and return an empty string (‘’) if not set. Date properties are assigned and returned as datetime.
datetime objects without timezone, i.e. in UTC. Any timezone conversions are the responsibility of the client. Date
properties return None if not set.
python-pptx does not automatically set any of the document core properties other than to add a core properties part to
a presentation that doesn’t have one (very uncommon). If python-pptx adds a core properties part, it contains default
values for the title, last_modified_by, revision, and modified properties. Client code should change properties like
revision and last_modified_by explicitly if that behavior is desired.
class pptx.opc.coreprops.CoreProperties
author
string – An entity primarily responsible for making the content of the resource.
category
string – A categorization of the content of this package. Example values might include: Resume, Letter,
Financial Forecast, Proposal, or Technical Presentation.
comments
string – An account of the content of the resource.
content_status
string – completion status of the document, e.g. ‘draft’
created
datetime – time of intial creation of the document
identifier
string – An unambiguous reference to the resource within a given context, e.g. ISBN.
keywords
string – descriptive words or short phrases likely to be used as search terms for this document
language
string – language the document is written in
last_modified_by
string – name or other identifier (such as email address) of person who last modified the document
last_printed
datetime – time the document was last printed
modified
datetime – time the document was last modified
revision
int – number of this revision, incremented by the PowerPoint® client once each time the document is
saved. Note however that the revision number is not automatically incremented by python-pptx.
subject
string – The topic of the content of the resource.
title
string – The name given to the resource.
version
string – free-form version string
6.2 Slides
The Slides object is accessed using the slides property of Presentation. It is not intended to be constructed
directly.
class pptx.slide.Slides
Sequence of slides belonging to an instance of Presentation, having list semantics for access to individual
slides. Supports indexed access, len(), and iteration.
add_slide(slide_layout)
Return a newly added slide that inherits layout from slide_layout.
6.2. Slides 63
python-pptx Documentation, Release 0.6.22
get(slide_id, default=None)
Return the slide identified by integer slide_id in this presentation, or default if not found.
index(slide)
Map slide to an integer representing its zero-based position in this slide collection. Raises ValueError
on slide not present.
An individual Slide object is accessed by index from Slides or as the return value of add_slide().
class pptx.slide.Slide
Slide object. Provides access to shapes and slide-level properties.
background
_Background object providing slide background properties.
This property returns a _Background object whether or not the slide overrides the default background
or inherits it. Determining which of those conditions applies for this slide is accomplished using the
follow_master_background property.
The same _Background object is returned on every call for the same slide object.
element
The lxml element proxied by this object.
follow_master_background
True if this slide inherits the slide master background.
Assigning False causes background inheritance from the master to be interrupted; if there is no custom
background for this slide, a default background is added. If a custom background already exists for this
slide, assigning False has no effect.
Assigning True causes any custom background for this slide to be deleted and inheritance from the master
restored.
has_notes_slide
Return True if this slide has a notes slide, False otherwise. A notes slide is created by notes_slide
when one doesn’t exist; use this property to test for a notes slide without the possible side effect of creating
one.
name
String representing the internal name of this slide. Returns an empty string (‘’) if no name is assigned.
Assigning an empty string or None to this property causes any name to be removed.
notes_slide
Return the NotesSlide instance for this slide. If the slide does not have a notes slide, one is created.
The same single instance is returned on each call.
placeholders
Instance of SlidePlaceholders containing sequence of placeholder shapes in this slide.
shapes
Instance of SlideShapes containing sequence of shape objects appearing on this slide.
slide_id
The integer value that uniquely identifies this slide within this presentation. The slide id does not change
if the position of this slide in the slide sequence is changed by adding, rearranging, or deleting slides.
slide_layout
SlideLayout object this slide inherits appearance from.
The SlideLayouts object is accessed using the slide_layouts property of SlideMaster, typically:
As a convenience, since most presentations have only a single slide master, the SlideLayouts collection for the
first master may be accessed directly from the Presentation object:
The SlideMasters object is accessed using the slide_masters property of Presentation, typically:
6.2. Slides 65
python-pptx Documentation, Release 0.6.22
As a convenience, since most presentations have only a single slide master, the first master may be accessed directly
from the Presentation object without indexing the collection:
notes_placeholder
Return the notes placeholder on this notes slide, the shape that contains the actual notes text. Return None
if no notes placeholder is present; while this is probably uncommon, it can happen if the notes master does
not have a body placeholder, or if the notes placeholder has been deleted from the notes slide.
notes_text_frame
Return the text frame of the notes placeholder on this notes slide, or None if there is no notes placeholder.
This is a shortcut to accommodate the common case of simply adding “notes” text to the notes “page”.
part
The package part containing this object
placeholders
An instance of NotesSlidePlaceholders containing the sequence of placeholder shapes in this
notes slide.
shapes
An instance of NotesSlideShapes containing the sequence of shape objects appearing on this notes
slide.
6.3 Shapes
The following classes provide access to the shapes that appear on a slide and the collections that contain them.
6.3. Shapes 67
python-pptx Documentation, Release 0.6.22
ified position and size. width is evenly distributed between the columns of the new table. Likewise, height
is evenly distributed between the rows. Note that the .table property on the returned GraphicFrame
shape must be used to access the enclosed Table object.
add_textbox(left, top, width, height)
Return newly added text box shape appended to this shape tree.
The text box is of the specified size, located at the specified position on the slide.
build_freeform(start_x=0, start_y=0, scale=1.0)
Return FreeformBuilder object to specify a freeform shape.
The optional start_x and start_y arguments specify the starting pen position in local coordinates. They will
be rounded to the nearest integer before use and each default to zero.
The optional scale argument specifies the size of local coordinates proportional to slide coordinates (EMU).
If the vertical scale is different than the horizontal scale (local coordinate units are “rectangular”), a pair of
numeric values can be provided as the scale argument, e.g. scale=(1.0, 2.0). In this case the first number
is interpreted as the horizontal (X) scale and the second as the vertical (Y) scale.
A convenient method for calculating scale is to divide a Length object by an equivalent count of local
coordinate units, e.g. scale = Inches(1)/1000 for 1000 local units per inch.
element
The lxml element proxied by this object.
index(shape)
Return the index of shape in this sequence.
Raises ValueError if shape is not in the collection.
parent
The ancestor proxy object to this one. For example, the parent of a shape is generally the SlideShapes
object that contains it.
part
The package part containing this object
placeholders
Instance of SlidePlaceholders containing sequence of placeholder shapes in this slide.
title
The title placeholder shape on the slide or None if the slide has no title placeholder.
turbo_add_enabled
True if “turbo-add” mode is enabled. Read/Write.
EXPERIMENTAL: This feature can radically improve performance when adding large numbers (hundreds
of shapes) to a slide. It works by caching the last shape ID used and incrementing that value to assign the
next shape id. This avoids repeatedly searching all shape ids in the slide each time a new ID is required.
Performance is not noticeably improved for a slide with a relatively small number of shapes, but because
the search time rises with the square of the shape count, this option can be useful for optimizing generation
of a slide composed of many shapes.
Shape-id collisions can occur (causing a repair error on load) if more than one Slide object is used to
interact with the same slide in the presentation. Note that the Slides collection creates a new Slide
object each time a slide is accessed (e.g. slide = prs.slides[0], so you must be careful to limit use to a
single Slide object.
6.3. Shapes 69
python-pptx Documentation, Release 0.6.22
6.3. Shapes 71
python-pptx Documentation, Release 0.6.22
The following properties and methods are defined for AutoShapes, which include text boxes and placeholders.
class pptx.shapes.autoshape.Shape
A shape that can appear on a slide.
Corresponds to the <p:sp> element that can appear in any of the slide-type parts (slide, slideLayout, slideMas-
ter, notesPage, notesMaster, handoutMaster).
adjustments
Read-only reference to AdjustmentCollection instance for this shape
auto_shape_type
Enumeration value identifying the type of this auto shape, like MSO_SHAPE.ROUNDED_RECTANGLE.
Raises ValueError if this shape is not an auto shape.
fill
FillFormat instance for this shape, providing access to fill properties such as fill color.
has_text_frame
True if this shape can contain text. Always True for an AutoShape.
line
LineFormat instance for this shape, providing access to line properties such as line color.
shape_type
Unique integer identifying the type of this shape, like MSO_SHAPE_TYPE.TEXT_BOX.
text
Read/write. Unicode (str in Python 3) representation of shape text.
The returned string will contain a newline character ("\n") separating each paragraph and a vertical-tab
("\v") character for each line break (soft carriage return) in the shape’s text.
Assignment to text replaces all text previously contained in the shape, along with any paragraph or font
formatting applied to it. A newline character ("\n") in the assigned text causes a new paragraph to be
started. A vertical-tab ("\v") character in the assigned text causes a line-break (soft carriage-return) to be
inserted. (The vertical-tab character appears in clipboard text copied from PowerPoint as its encoding of
line-breaks.)
Either bytes (Python 2 str) or unicode (Python 3 str) can be assigned. Bytes can be 7-bit ASCII or UTF-8
encoded 8-bit bytes. Bytes values are converted to unicode assuming UTF-8 encoding (which also works
for ASCII).
text_frame
TextFrame instance for this shape.
Contains the text of the shape and provides access to text formatting properties.
6.3. Shapes 73
python-pptx Documentation, Release 0.6.22
AdjustmentCollection objects
An AutoShape is distinctive in that it can have adjustments, represented in the PowerPoint user interface as small
yellow diamonds that each allow a parameter of the shape, such as the angle of an arrowhead, to be adjusted.
The AdjustmentCollection object holds these adjustment values for an AutoShape, each of which is an
Adjustment instance.
The AdjustmentCollection instance for an AutoShape is accessed using the Shape.adjustments property
(read-only).
class pptx.shapes.autoshape.AdjustmentCollection(prstGeom)
Sequence of Adjustment instances for an auto shape, each representing an available adjustment for a shape
of its type. Supports len() and indexed access, e.g. shape.adjustments[1] = 0.15.
Adjustment objects
The following properties and methods are defined for Connector shapes:
class pptx.shapes.connector.Connector
Connector (line) shape.
A connector is a linear shape having end-points that can be connected to other objects (but not to other connec-
tors). A connector can be straight, have elbows, or can be curved.
begin_connect(shape, cxn_pt_idx)
EXPERIMENTAL - The current implementation only works properly with rectangular shapes, such as
pictures and rectangles. Use with other shape types may cause unexpected visual alignment of the con-
nected end-point and could lead to a load error if cxn_pt_idx exceeds the connection point count available
on the connected shape. That said, a quick test should reveal what to expect when using this method with
other shape types.
Connect the beginning of this connector to shape at the connection point specified by cxn_pt_idx. Each
shape has zero or more connection points and they are identified by index, starting with 0. Generally, the
first connection point of a shape is at the top center of its bounding box and numbering proceeds counter-
clockwise from there. However this is only a convention and may vary, especially with non built-in shapes.
begin_x
Return the X-position of the begin point of this connector, in English Metric Units (as a Length object).
begin_y
Return the Y-position of the begin point of this connector, in English Metric Units (as a Length object).
end_connect(shape, cxn_pt_idx)
EXPERIMENTAL - The current implementation only works properly with rectangular shapes, such as
pictures and rectangles. Use with other shape types may cause unexpected visual alignment of the con-
nected end-point and could lead to a load error if cxn_pt_idx exceeds the connection point count available
on the connected shape. That said, a quick test should reveal what to expect when using this method with
other shape types.
Connect the ending of this connector to shape at the connection point specified by cxn_pt_idx.
end_x
Return the X-position of the end point of this connector, in English Metric Units (as a Length object).
end_y
Return the Y-position of the end point of this connector, in English Metric Units (as a Length object).
line
LineFormat instance for this connector.
Provides access to line properties such as line color, width, and line style.
shape_type
Member of MSO_SHAPE_TYPE identifying the type of this shape.
Unconditionally MSO_SHAPE_TYPE.LINE for a Connector object.
The following properties and methods are defined for FreeformBuilder objects. A freeform builder is used to create a
shape with custom geometry:
class pptx.shapes.freeform.FreeformBuilder
Allows a freeform shape to be specified and created.
The initial pen position is provided on construction. From there, drawing proceeds using successive calls to
draw line segments. The freeform shape may be closed by calling the close() method.
A shape may have more than one contour, in which case overlapping areas are “subtracted”. A contour is a
sequence of line segments beginning with a “move-to” operation. A move-to operation is automatically inserted
in each new freeform; additional move-to ops can be inserted with the .move_to() method.
add_line_segments(vertices, close=True)
Add a straight line segment to each point in vertices.
vertices must be an iterable of (x, y) pairs (2-tuples). Each x and y value is rounded to the nearest integer
before use. The optional close parameter determines whether the resulting contour is closed or left open.
Returns this FreeformBuilder object so it can be used in chained calls.
convert_to_shape(origin_x=0, origin_y=0)
Return new freeform shape positioned relative to specified offset.
6.3. Shapes 75
python-pptx Documentation, Release 0.6.22
origin_x and origin_y locate the origin of the local coordinate system in slide coordinates (EMU), perhaps
most conveniently by use of a Length object.
Note that this method may be called more than once to add multiple shapes of the same geometry in
different locations on the slide.
move_to(x, y)
Move pen to (x, y) (local coordinates) without drawing line.
Returns this FreeformBuilder object so it can be used in chained calls.
The following properties and methods are defined for picture shapes.
class pptx.shapes.picture.Picture
A picture shape, one that places an image on a slide.
Based on the p:pic element.
click_action
ActionSetting instance providing access to click behaviors.
Click behaviors are hyperlink-like behaviors including jumping to a hyperlink (web page) or to another
slide in the presentation. The click action is that defined on the overall shape, not a run of text within the
shape. An ActionSetting object is always returned, even when no click behavior is defined on the
shape.
crop_bottom
float representing relative portion cropped from shape bottom.
Read/write. 1.0 represents 100%. For example, 25% is represented by 0.25. Negative values are valid as
are values greater than 1.0.
crop_left
float representing relative portion cropped from left of shape.
Read/write. 1.0 represents 100%. A negative value extends the side beyond the image boundary.
crop_right
float representing relative portion cropped from right of shape.
Read/write. 1.0 represents 100%.
crop_top
float representing relative portion cropped from shape top.
Read/write. 1.0 represents 100%.
element
lxml element for this shape, e.g. a CT_Shape instance.
Note that manipulating this element improperly can produce an invalid presentation file. Make sure you
know what you’re doing if you use this to change the underlying XML.
has_chart
True if this shape is a graphic frame containing a chart object. False otherwise. When True, the chart
object can be accessed using the .chart property.
has_table
True if this shape is a graphic frame containing a table object. False otherwise. When True, the table
object can be accessed using the .table property.
has_text_frame
True if this shape can contain text.
height
Read/write. Integer distance between top and bottom extents of shape in EMUs
is_placeholder
True if this shape is a placeholder. A shape is a placeholder if it has a <p:ph> element.
left
Read/write. Integer distance of the left edge of this shape from the left edge of the slide, in English Metric
Units (EMU)
line
An instance of LineFormat, providing access to the properties of the outline bordering this shape, such
as its color and width.
name
Name of this shape, e.g. ‘Picture 7’
part
The package part containing this shape.
A BaseSlidePart subclass in this case. Access to a slide part should only be required if you are
extending the behavior of python-pptx API objects.
placeholder_format
A _PlaceholderFormat object providing access to placeholder-specific properties such as place-
holder type. Raises ValueError on access if the shape is not a placeholder.
rotation
Read/write float. Degrees of clockwise rotation. Negative values can be assigned to indicate counter-
clockwise rotation, e.g. assigning -45.0 will change setting to 315.0.
shadow
ShadowFormat object providing access to shadow for this shape.
A ShadowFormat object is always returned, even when no shadow is explicitly defined on this shape
(i.e. it inherits its shadow behavior).
shape_id
Read-only positive integer identifying this shape.
The id of a shape is unique among all shapes on a slide.
top
Read/write. Integer distance of the top edge of this shape from the top edge of the slide, in English Metric
Units (EMU)
width
Read/write. Integer distance between left and right extents of shape in EMUs
auto_shape_type
Member of MSO_SHAPE indicating masking shape.
A picture can be masked by any of the so-called “auto-shapes” available in PowerPoint, such as an ellipse
or triangle. When a picture is masked by a shape, the shape assumes the same dimensions as the picture
and the portion of the picture outside the shape boundaries does not appear. Note the default value for a
newly-inserted picture is MSO_AUTO_SHAPE_TYPE.RECTANGLE, which performs no cropping because
the extents of the rectangle exactly correspond to the extents of the picture.
The available shapes correspond to the members of MSO_AUTO_SHAPE_TYPE.
6.3. Shapes 77
python-pptx Documentation, Release 0.6.22
The return value can also be None, indicating the picture either has no geometry (not expected) or has
custom geometry, like a freeform shape. A picture with no geometry will have no visible representation
on the slide, although it can be selected. This is because without geometry, there is no “inside-the-shape”
for it to appear in.
image
An Image object providing access to the properties and bytes of the image in this picture shape.
shape_type
Unique integer identifying the type of this shape, unconditionally MSO_SHAPE_TYPE.PICTURE in this
case.
The following properties and methods are defined for graphic frame shapes. A graphic frame is the shape containing
a table, chart, or smart art.
class pptx.shapes.graphfrm.GraphicFrame
Bases: pptx.shapes.base.BaseShape
Container shape for table, chart, smart art, and media objects.
Corresponds to a <p:graphicFrame> element in the shape tree.
chart
The Chart object containing the chart in this graphic frame.
Raises ValueError if this graphic frame does not contain a chart.
click_action
ActionSetting instance providing access to click behaviors.
Click behaviors are hyperlink-like behaviors including jumping to a hyperlink (web page) or to another
slide in the presentation. The click action is that defined on the overall shape, not a run of text within the
shape. An ActionSetting object is always returned, even when no click behavior is defined on the
shape.
element
lxml element for this shape, e.g. a CT_Shape instance.
Note that manipulating this element improperly can produce an invalid presentation file. Make sure you
know what you’re doing if you use this to change the underlying XML.
has_chart
True if this graphic frame contains a chart object. False otherwise.
When True, the chart object can be accessed using the .chart property.
has_table
True if this graphic frame contains a table object, False otherwise.
When True, the table object can be accessed using the .table property.
height
Read/write. Integer distance between top and bottom extents of shape in EMUs
left
Read/write. Integer distance of the left edge of this shape from the left edge of the slide, in English Metric
Units (EMU)
name
Name of this shape, e.g. ‘Picture 7’
ole_format
Optional _OleFormat object for this graphic-frame shape.
Raises ValueError on a GraphicFrame instance that does not contain an OLE object.
An shape that contains an OLE object will have .shape_type of either EMBEDDED_OLE_OBJECT or
LINKED_OLE_OBJECT.
rotation
Read/write float. Degrees of clockwise rotation. Negative values can be assigned to indicate counter-
clockwise rotation, e.g. assigning -45.0 will change setting to 315.0.
shadow
Unconditionally raises NotImplementedError.
Access to the shadow effect for graphic-frame objects is content-specific (i.e. different for charts, tables,
etc.) and has not yet been implemented.
shape_id
Read-only positive integer identifying this shape.
The id of a shape is unique among all shapes on a slide.
table
The Table object contained in this graphic frame. Raises ValueError if this graphic frame does not
contain a table.
top
Read/write. Integer distance of the top edge of this shape from the top edge of the slide, in English Metric
Units (EMU)
width
Read/write. Integer distance between left and right extents of shape in EMUs
The following properties and methods are defined for group shapes. A group shape acts as a container for other shapes.
Note that:
• A group shape has no text frame and cannot have one.
• A group shape cannot have a click action, such as a hyperlink.
class pptx.shapes.group.GroupShape
Bases: pptx.shapes.base.BaseShape
A shape that acts as a container for other shapes.
click_action
Unconditionally raises TypeError.
A group shape cannot have a click action or hover action.
element
lxml element for this shape, e.g. a CT_Shape instance.
Note that manipulating this element improperly can produce an invalid presentation file. Make sure you
know what you’re doing if you use this to change the underlying XML.
has_text_frame
Unconditionally False.
6.3. Shapes 79
python-pptx Documentation, Release 0.6.22
A group shape does not have a textframe and cannot itself contain text. This does not impact the ability of
shapes contained by the group to each have their own text.
height
Read/write. Integer distance between top and bottom extents of shape in EMUs
left
Read/write. Integer distance of the left edge of this shape from the left edge of the slide, in English Metric
Units (EMU)
name
Name of this shape, e.g. ‘Picture 7’
part
The package part containing this shape.
A BaseSlidePart subclass in this case. Access to a slide part should only be required if you are
extending the behavior of python-pptx API objects.
rotation
Read/write float. Degrees of clockwise rotation. Negative values can be assigned to indicate counter-
clockwise rotation, e.g. assigning -45.0 will change setting to 315.0.
shadow
ShadowFormat object representing shadow effect for this group.
A ShadowFormat object is always returned, even when no shadow is explicitly defined on this group
shape (i.e. when the group inherits its shadow behavior).
shape_id
Read-only positive integer identifying this shape.
The id of a shape is unique among all shapes on a slide.
shape_type
Member of MSO_SHAPE_TYPE identifying the type of this shape.
Unconditionally MSO_SHAPE_TYPE.GROUP in this case
shapes
GroupShapes object for this group.
The GroupShapes object provides access to the group’s member shapes and provides methods for
adding new ones.
top
Read/write. Integer distance of the top edge of this shape from the top edge of the slide, in English Metric
Units (EMU)
width
Read/write. Integer distance between left and right extents of shape in EMUs
6.4 Placeholders
The following classes represent placeholder shapes. A placeholder most commonly appears on a slide, but also appears
on a slide layout and a slide master. The role of a master placeholder and layout placeholder differs from that of a slide
placeholder and these roles are reflected in the distinct classes for each.
There are a larger variety of slide placeholders to accomodate their more complex and varied behaviors.
class pptx.shapes.placeholder.MasterPlaceholder
Placeholder shape on a slide master.
auto_shape_type
Enumeration value identifying the type of this auto shape, like MSO_SHAPE.ROUNDED_RECTANGLE.
Raises ValueError if this shape is not an auto shape.
click_action
ActionSetting instance providing access to click behaviors.
Click behaviors are hyperlink-like behaviors including jumping to a hyperlink (web page) or to another
slide in the presentation. The click action is that defined on the overall shape, not a run of text within the
shape. An ActionSetting object is always returned, even when no click behavior is defined on the
shape.
element
lxml element for this shape, e.g. a CT_Shape instance.
Note that manipulating this element improperly can produce an invalid presentation file. Make sure you
know what you’re doing if you use this to change the underlying XML.
fill
FillFormat instance for this shape, providing access to fill properties such as fill color.
has_text_frame
True if this shape can contain text. Always True for an AutoShape.
height
Read/write. Integer distance between top and bottom extents of shape in EMUs
is_placeholder
True if this shape is a placeholder. A shape is a placeholder if it has a <p:ph> element.
left
Read/write. Integer distance of the left edge of this shape from the left edge of the slide, in English Metric
Units (EMU)
line
LineFormat instance for this shape, providing access to line properties such as line color.
name
Name of this shape, e.g. ‘Picture 7’
placeholder_format
A _PlaceholderFormat object providing access to placeholder-specific properties such as place-
holder type. Raises ValueError on access if the shape is not a placeholder.
rotation
Read/write float. Degrees of clockwise rotation. Negative values can be assigned to indicate counter-
clockwise rotation, e.g. assigning -45.0 will change setting to 315.0.
shadow
ShadowFormat object providing access to shadow for this shape.
A ShadowFormat object is always returned, even when no shadow is explicitly defined on this shape
(i.e. it inherits its shadow behavior).
shape_id
Read-only positive integer identifying this shape.
The id of a shape is unique among all shapes on a slide.
6.4. Placeholders 81
python-pptx Documentation, Release 0.6.22
text
Read/write. Unicode (str in Python 3) representation of shape text.
The returned string will contain a newline character ("\n") separating each paragraph and a vertical-tab
("\v") character for each line break (soft carriage return) in the shape’s text.
Assignment to text replaces all text previously contained in the shape, along with any paragraph or font
formatting applied to it. A newline character ("\n") in the assigned text causes a new paragraph to be
started. A vertical-tab ("\v") character in the assigned text causes a line-break (soft carriage-return) to be
inserted. (The vertical-tab character appears in clipboard text copied from PowerPoint as its encoding of
line-breaks.)
Either bytes (Python 2 str) or unicode (Python 3 str) can be assigned. Bytes can be 7-bit ASCII or UTF-8
encoded 8-bit bytes. Bytes values are converted to unicode assuming UTF-8 encoding (which also works
for ASCII).
text_frame
TextFrame instance for this shape.
Contains the text of the shape and provides access to text formatting properties.
top
Read/write. Integer distance of the top edge of this shape from the top edge of the slide, in English Metric
Units (EMU)
width
Read/write. Integer distance between left and right extents of shape in EMUs
class pptx.shapes.placeholder.LayoutPlaceholder
Placeholder shape on a slide layout, providing differentiated behavior for slide layout placeholders, in particular,
inheriting shape properties from the master placeholder having the same type, when a matching one exists.
class pptx.shapes.placeholder.ChartPlaceholder
Placeholder shape that can only accept a chart.
adjustments
Read-only reference to AdjustmentCollection instance for this shape
auto_shape_type
Enumeration value identifying the type of this auto shape, like MSO_SHAPE.ROUNDED_RECTANGLE.
Raises ValueError if this shape is not an auto shape.
click_action
ActionSetting instance providing access to click behaviors.
Click behaviors are hyperlink-like behaviors including jumping to a hyperlink (web page) or to another
slide in the presentation. The click action is that defined on the overall shape, not a run of text within the
shape. An ActionSetting object is always returned, even when no click behavior is defined on the
shape.
element
lxml element for this shape, e.g. a CT_Shape instance.
Note that manipulating this element improperly can produce an invalid presentation file. Make sure you
know what you’re doing if you use this to change the underlying XML.
fill
FillFormat instance for this shape, providing access to fill properties such as fill color.
get_or_add_ln()
Return the <a:ln> element containing the line format properties XML for this shape.
height
The effective height of this placeholder shape; its directly-applied height if it has one, otherwise the height
of its parent layout placeholder.
insert_chart(chart_type, chart_data)
Return a PlaceholderGraphicFrame object containing a new chart of chart_type depicting
chart_data and having the same position and size as this placeholder. chart_type is one of the
XL_CHART_TYPE enumeration values. chart_data is a ChartData object populated with the categories
and series values for the chart. Note that the new Chart object is not returned directly. The chart object
may be accessed using the chart property of the returned PlaceholderGraphicFrame object.
is_placeholder
Boolean indicating whether this shape is a placeholder. Unconditionally True in this case.
left
The effective left of this placeholder shape; its directly-applied left if it has one, otherwise the left of its
parent layout placeholder.
line
LineFormat instance for this shape, providing access to line properties such as line color.
ln
The <a:ln> element containing the line format properties such as line color and width. None if no
<a:ln> element is present.
name
Name of this shape, e.g. ‘Picture 7’
placeholder_format
A _PlaceholderFormat object providing access to placeholder-specific properties such as place-
holder type. Raises ValueError on access if the shape is not a placeholder.
rotation
Read/write float. Degrees of clockwise rotation. Negative values can be assigned to indicate counter-
clockwise rotation, e.g. assigning -45.0 will change setting to 315.0.
shadow
ShadowFormat object providing access to shadow for this shape.
A ShadowFormat object is always returned, even when no shadow is explicitly defined on this shape
(i.e. it inherits its shadow behavior).
shape_id
Read-only positive integer identifying this shape.
The id of a shape is unique among all shapes on a slide.
shape_type
Member of MSO_SHAPE_TYPE specifying the type of this shape. Unconditionally MSO_SHAPE_TYPE.
PLACEHOLDER in this case. Read-only.
text
Read/write. Unicode (str in Python 3) representation of shape text.
The returned string will contain a newline character ("\n") separating each paragraph and a vertical-tab
("\v") character for each line break (soft carriage return) in the shape’s text.
6.4. Placeholders 83
python-pptx Documentation, Release 0.6.22
Assignment to text replaces all text previously contained in the shape, along with any paragraph or font
formatting applied to it. A newline character ("\n") in the assigned text causes a new paragraph to be
started. A vertical-tab ("\v") character in the assigned text causes a line-break (soft carriage-return) to be
inserted. (The vertical-tab character appears in clipboard text copied from PowerPoint as its encoding of
line-breaks.)
Either bytes (Python 2 str) or unicode (Python 3 str) can be assigned. Bytes can be 7-bit ASCII or UTF-8
encoded 8-bit bytes. Bytes values are converted to unicode assuming UTF-8 encoding (which also works
for ASCII).
text_frame
TextFrame instance for this shape.
Contains the text of the shape and provides access to text formatting properties.
top
The effective top of this placeholder shape; its directly-applied top if it has one, otherwise the top of its
parent layout placeholder.
width
The effective width of this placeholder shape; its directly-applied width if it has one, otherwise the width
of its parent layout placeholder.
class pptx.shapes.placeholder.PicturePlaceholder
Placeholder shape that can only accept a picture.
adjustments
Read-only reference to AdjustmentCollection instance for this shape
auto_shape_type
Enumeration value identifying the type of this auto shape, like MSO_SHAPE.ROUNDED_RECTANGLE.
Raises ValueError if this shape is not an auto shape.
click_action
ActionSetting instance providing access to click behaviors.
Click behaviors are hyperlink-like behaviors including jumping to a hyperlink (web page) or to another
slide in the presentation. The click action is that defined on the overall shape, not a run of text within the
shape. An ActionSetting object is always returned, even when no click behavior is defined on the
shape.
element
lxml element for this shape, e.g. a CT_Shape instance.
Note that manipulating this element improperly can produce an invalid presentation file. Make sure you
know what you’re doing if you use this to change the underlying XML.
fill
FillFormat instance for this shape, providing access to fill properties such as fill color.
get_or_add_ln()
Return the <a:ln> element containing the line format properties XML for this shape.
height
The effective height of this placeholder shape; its directly-applied height if it has one, otherwise the height
of its parent layout placeholder.
insert_picture(image_file)
Return a PlaceholderPicture object depicting the image in image_file.
image_file may be either a path (string) or a file-like object. The image is cropped to fill the entire space
of the placeholder. A PlaceholderPicture object has all the properties and methods of a Picture
shape except that the value of its shape_type property is MSO_SHAPE_TYPE.PLACEHOLDER instead
of MSO_SHAPE_TYPE.PICTURE.
is_placeholder
Boolean indicating whether this shape is a placeholder. Unconditionally True in this case.
left
The effective left of this placeholder shape; its directly-applied left if it has one, otherwise the left of its
parent layout placeholder.
line
LineFormat instance for this shape, providing access to line properties such as line color.
ln
The <a:ln> element containing the line format properties such as line color and width. None if no
<a:ln> element is present.
name
Name of this shape, e.g. ‘Picture 7’
placeholder_format
A _PlaceholderFormat object providing access to placeholder-specific properties such as place-
holder type. Raises ValueError on access if the shape is not a placeholder.
rotation
Read/write float. Degrees of clockwise rotation. Negative values can be assigned to indicate counter-
clockwise rotation, e.g. assigning -45.0 will change setting to 315.0.
shadow
ShadowFormat object providing access to shadow for this shape.
A ShadowFormat object is always returned, even when no shadow is explicitly defined on this shape
(i.e. it inherits its shadow behavior).
shape_id
Read-only positive integer identifying this shape.
The id of a shape is unique among all shapes on a slide.
shape_type
Member of MSO_SHAPE_TYPE specifying the type of this shape. Unconditionally MSO_SHAPE_TYPE.
PLACEHOLDER in this case. Read-only.
text
Read/write. Unicode (str in Python 3) representation of shape text.
The returned string will contain a newline character ("\n") separating each paragraph and a vertical-tab
("\v") character for each line break (soft carriage return) in the shape’s text.
Assignment to text replaces all text previously contained in the shape, along with any paragraph or font
formatting applied to it. A newline character ("\n") in the assigned text causes a new paragraph to be
started. A vertical-tab ("\v") character in the assigned text causes a line-break (soft carriage-return) to be
inserted. (The vertical-tab character appears in clipboard text copied from PowerPoint as its encoding of
line-breaks.)
Either bytes (Python 2 str) or unicode (Python 3 str) can be assigned. Bytes can be 7-bit ASCII or UTF-8
encoded 8-bit bytes. Bytes values are converted to unicode assuming UTF-8 encoding (which also works
6.4. Placeholders 85
python-pptx Documentation, Release 0.6.22
for ASCII).
text_frame
TextFrame instance for this shape.
Contains the text of the shape and provides access to text formatting properties.
top
The effective top of this placeholder shape; its directly-applied top if it has one, otherwise the top of its
parent layout placeholder.
width
The effective width of this placeholder shape; its directly-applied width if it has one, otherwise the width
of its parent layout placeholder.
class pptx.shapes.placeholder.TablePlaceholder
Placeholder shape that can only accept a table.
adjustments
Read-only reference to AdjustmentCollection instance for this shape
auto_shape_type
Enumeration value identifying the type of this auto shape, like MSO_SHAPE.ROUNDED_RECTANGLE.
Raises ValueError if this shape is not an auto shape.
click_action
ActionSetting instance providing access to click behaviors.
Click behaviors are hyperlink-like behaviors including jumping to a hyperlink (web page) or to another
slide in the presentation. The click action is that defined on the overall shape, not a run of text within the
shape. An ActionSetting object is always returned, even when no click behavior is defined on the
shape.
element
lxml element for this shape, e.g. a CT_Shape instance.
Note that manipulating this element improperly can produce an invalid presentation file. Make sure you
know what you’re doing if you use this to change the underlying XML.
fill
FillFormat instance for this shape, providing access to fill properties such as fill color.
get_or_add_ln()
Return the <a:ln> element containing the line format properties XML for this shape.
height
The effective height of this placeholder shape; its directly-applied height if it has one, otherwise the height
of its parent layout placeholder.
insert_table(rows, cols)
Return PlaceholderGraphicFrame object containing a rows by cols table.
The position and width of the table are those of the placeholder and its height is proportional to
the number of rows. A PlaceholderGraphicFrame object has all the properties and meth-
ods of a GraphicFrame shape except that the value of its shape_type property is uncondi-
tionally MSO_SHAPE_TYPE.PLACEHOLDER. Note that the return value is not the new table but
rather contains the new table. The table can be accessed using the table property of the returned
PlaceholderGraphicFrame object.
left
The effective left of this placeholder shape; its directly-applied left if it has one, otherwise the left of its
parent layout placeholder.
line
LineFormat instance for this shape, providing access to line properties such as line color.
ln
The <a:ln> element containing the line format properties such as line color and width. None if no
<a:ln> element is present.
name
Name of this shape, e.g. ‘Picture 7’
placeholder_format
A _PlaceholderFormat object providing access to placeholder-specific properties such as place-
holder type. Raises ValueError on access if the shape is not a placeholder.
rotation
Read/write float. Degrees of clockwise rotation. Negative values can be assigned to indicate counter-
clockwise rotation, e.g. assigning -45.0 will change setting to 315.0.
shadow
ShadowFormat object providing access to shadow for this shape.
A ShadowFormat object is always returned, even when no shadow is explicitly defined on this shape
(i.e. it inherits its shadow behavior).
shape_id
Read-only positive integer identifying this shape.
The id of a shape is unique among all shapes on a slide.
shape_type
Member of MSO_SHAPE_TYPE specifying the type of this shape. Unconditionally MSO_SHAPE_TYPE.
PLACEHOLDER in this case. Read-only.
text
Read/write. Unicode (str in Python 3) representation of shape text.
The returned string will contain a newline character ("\n") separating each paragraph and a vertical-tab
("\v") character for each line break (soft carriage return) in the shape’s text.
Assignment to text replaces all text previously contained in the shape, along with any paragraph or font
formatting applied to it. A newline character ("\n") in the assigned text causes a new paragraph to be
started. A vertical-tab ("\v") character in the assigned text causes a line-break (soft carriage-return) to be
inserted. (The vertical-tab character appears in clipboard text copied from PowerPoint as its encoding of
line-breaks.)
Either bytes (Python 2 str) or unicode (Python 3 str) can be assigned. Bytes can be 7-bit ASCII or UTF-8
encoded 8-bit bytes. Bytes values are converted to unicode assuming UTF-8 encoding (which also works
for ASCII).
text_frame
TextFrame instance for this shape.
Contains the text of the shape and provides access to text formatting properties.
top
The effective top of this placeholder shape; its directly-applied top if it has one, otherwise the top of its
parent layout placeholder.
6.4. Placeholders 87
python-pptx Documentation, Release 0.6.22
width
The effective width of this placeholder shape; its directly-applied width if it has one, otherwise the width
of its parent layout placeholder.
class pptx.shapes.placeholder.PlaceholderGraphicFrame
Placeholder shape populated with a table, chart, or smart art.
chart
The Chart object containing the chart in this graphic frame.
Raises ValueError if this graphic frame does not contain a chart.
click_action
ActionSetting instance providing access to click behaviors.
Click behaviors are hyperlink-like behaviors including jumping to a hyperlink (web page) or to another
slide in the presentation. The click action is that defined on the overall shape, not a run of text within the
shape. An ActionSetting object is always returned, even when no click behavior is defined on the
shape.
element
lxml element for this shape, e.g. a CT_Shape instance.
Note that manipulating this element improperly can produce an invalid presentation file. Make sure you
know what you’re doing if you use this to change the underlying XML.
has_chart
True if this graphic frame contains a chart object. False otherwise.
When True, the chart object can be accessed using the .chart property.
has_table
True if this graphic frame contains a table object, False otherwise.
When True, the table object can be accessed using the .table property.
height
Read/write. Integer distance between top and bottom extents of shape in EMUs
left
Read/write. Integer distance of the left edge of this shape from the left edge of the slide, in English Metric
Units (EMU)
name
Name of this shape, e.g. ‘Picture 7’
ole_format
Optional _OleFormat object for this graphic-frame shape.
Raises ValueError on a GraphicFrame instance that does not contain an OLE object.
An shape that contains an OLE object will have .shape_type of either EMBEDDED_OLE_OBJECT or
LINKED_OLE_OBJECT.
placeholder_format
A _PlaceholderFormat object providing access to placeholder-specific properties such as place-
holder type. Raises ValueError on access if the shape is not a placeholder.
rotation
Read/write float. Degrees of clockwise rotation. Negative values can be assigned to indicate counter-
clockwise rotation, e.g. assigning -45.0 will change setting to 315.0.
shadow
Unconditionally raises NotImplementedError.
Access to the shadow effect for graphic-frame objects is content-specific (i.e. different for charts, tables,
etc.) and has not yet been implemented.
shape_id
Read-only positive integer identifying this shape.
The id of a shape is unique among all shapes on a slide.
shape_type
Optional member of MSO_SHAPE_TYPE identifying the type of this shape.
Possible values are MSO_SHAPE_TYPE.CHART, MSO_SHAPE_TYPE.TABLE, MSO_SHAPE_TYPE.
EMBEDDED_OLE_OBJECT, MSO_SHAPE_TYPE.LINKED_OLE_OBJECT.
This value is None when none of these four types apply, for example when the shape contains SmartArt.
table
The Table object contained in this graphic frame. Raises ValueError if this graphic frame does not
contain a table.
top
Read/write. Integer distance of the top edge of this shape from the top edge of the slide, in English Metric
Units (EMU)
width
Read/write. Integer distance between left and right extents of shape in EMUs
class pptx.shapes.placeholder.PlaceholderPicture
Placeholder shape populated with a picture.
auto_shape_type
Member of MSO_SHAPE indicating masking shape.
A picture can be masked by any of the so-called “auto-shapes” available in PowerPoint, such as an ellipse
or triangle. When a picture is masked by a shape, the shape assumes the same dimensions as the picture
and the portion of the picture outside the shape boundaries does not appear. Note the default value for a
newly-inserted picture is MSO_AUTO_SHAPE_TYPE.RECTANGLE, which performs no cropping because
the extents of the rectangle exactly correspond to the extents of the picture.
The available shapes correspond to the members of MSO_AUTO_SHAPE_TYPE.
The return value can also be None, indicating the picture either has no geometry (not expected) or has
custom geometry, like a freeform shape. A picture with no geometry will have no visible representation
on the slide, although it can be selected. This is because without geometry, there is no “inside-the-shape”
for it to appear in.
click_action
ActionSetting instance providing access to click behaviors.
Click behaviors are hyperlink-like behaviors including jumping to a hyperlink (web page) or to another
slide in the presentation. The click action is that defined on the overall shape, not a run of text within the
6.4. Placeholders 89
python-pptx Documentation, Release 0.6.22
shape. An ActionSetting object is always returned, even when no click behavior is defined on the
shape.
crop_bottom
float representing relative portion cropped from shape bottom.
Read/write. 1.0 represents 100%. For example, 25% is represented by 0.25. Negative values are valid as
are values greater than 1.0.
crop_left
float representing relative portion cropped from left of shape.
Read/write. 1.0 represents 100%. A negative value extends the side beyond the image boundary.
crop_right
float representing relative portion cropped from right of shape.
Read/write. 1.0 represents 100%.
crop_top
float representing relative portion cropped from shape top.
Read/write. 1.0 represents 100%.
element
lxml element for this shape, e.g. a CT_Shape instance.
Note that manipulating this element improperly can produce an invalid presentation file. Make sure you
know what you’re doing if you use this to change the underlying XML.
height
The effective height of this placeholder shape; its directly-applied height if it has one, otherwise the height
of its parent layout placeholder.
image
An Image object providing access to the properties and bytes of the image in this picture shape.
is_placeholder
True if this shape is a placeholder. A shape is a placeholder if it has a <p:ph> element.
left
The effective left of this placeholder shape; its directly-applied left if it has one, otherwise the left of its
parent layout placeholder.
line
An instance of LineFormat, providing access to the properties of the outline bordering this shape, such
as its color and width.
name
Name of this shape, e.g. ‘Picture 7’
placeholder_format
A _PlaceholderFormat object providing access to placeholder-specific properties such as place-
holder type. Raises ValueError on access if the shape is not a placeholder.
rotation
Read/write float. Degrees of clockwise rotation. Negative values can be assigned to indicate counter-
clockwise rotation, e.g. assigning -45.0 will change setting to 315.0.
shadow
ShadowFormat object providing access to shadow for this shape.
A ShadowFormat object is always returned, even when no shadow is explicitly defined on this shape
(i.e. it inherits its shadow behavior).
shape_id
Read-only positive integer identifying this shape.
The id of a shape is unique among all shapes on a slide.
shape_type
Member of MSO_SHAPE_TYPE specifying the type of this shape. Unconditionally MSO_SHAPE_TYPE.
PLACEHOLDER in this case. Read-only.
top
The effective top of this placeholder shape; its directly-applied top if it has one, otherwise the top of its
parent layout placeholder.
width
The effective width of this placeholder shape; its directly-applied width if it has one, otherwise the width
of its parent layout placeholder.
class pptx.shapes.base._PlaceholderFormat
Accessed via the placeholder_format property of a placeholder shape, provides properties specific to
placeholders, such as the placeholder type.
element
The p:ph element proxied by this object.
idx
Integer placeholder ‘idx’ attribute.
type
Placeholder type, a member of the PP_PLACEHOLDER_TYPE enumeration, e.g.
PP_PLACEHOLDER.CHART
first_col
Read/write boolean property which, when true, indicates the first column should be formatted differently,
as for a side-heading column at the far left of the table.
first_row
Read/write boolean property which, when true, indicates the first row should be formatted differently, e.g.
for column headings.
horz_banding
Read/write boolean property which, when true, indicates the rows of the table should appear with alternat-
ing shading.
iter_cells()
Generate _Cell object for each cell in this table.
Each grid cell is generated in left-to-right, top-to-bottom order.
last_col
Read/write boolean property which, when true, indicates the last column should be formatted differently,
as for a row totals column at the far right of the table.
last_row
Read/write boolean property which, when true, indicates the last row should be formatted differently, as
for a totals row at the bottom of the table.
rows
_RowCollection instance for this table.
Provides access to _Row objects representing the table’s rows. _Row objects are accessed using list
notation, e.g. col = tbl.rows[0].
vert_banding
Read/write boolean property which, when true, indicates the columns of the table should appear with
alternating shading.
class pptx.table._Column
Table column
width
Width of column in EMU.
class pptx.table._Row
Table row
cells
Read-only reference to collection of cells in row. An individual cell is referenced using list notation, e.g.
cell = row.cells[0].
height
Height of row in EMU.
A _Cell object represents a single table cell at a particular row/column location in the table. _Cell objects are not
constructed directly. A reference to a _Cell object is obtained using the Table.cell() method, specifying the
cell’s row/column location. A cell object can also be obtained using the _Row.cells collection.
class pptx.table._Cell(tc, parent)
Table cell
fill
FillFormat instance for this cell, providing access to fill properties such as foreground color.
is_merge_origin
True if this cell is the top-left grid cell in a merged cell.
is_spanned
True if this cell is spanned by a merge-origin cell.
A merge-origin cell “spans” the other grid cells in its merge range, consuming their area and “shadowing”
the spanned grid cells.
Note this value is False for a merge-origin cell. A merge-origin cell spans other grid cells, but is not
itself a spanned cell.
margin_left
Read/write integer value of left margin of cell as a Length value object. If assigned None, the default
value is used, 0.1 inches for left and right margins and 0.05 inches for top and bottom.
margin_right
Right margin of cell.
margin_top
Top margin of cell.
margin_bottom
Bottom margin of cell.
merge(other_cell)
Create merged cell from this cell to other_cell.
This cell and other_cell specify opposite corners of the merged cell range. Either diagonal of the cell
region may be specified in either order, e.g. self=bottom-right, other_cell=top-left, etc.
Raises ValueError if the specified range already contains merged cells anywhere within its extents or
if other_cell is not in the same table as self.
span_height
int count of rows spanned by this cell.
The value of this property may be misleading (often 1) on cells where .is_merge_origin is not True, since
only a merge-origin cell contains complete span information. This property is only intended for use on
cells known to be a merge origin by testing .is_merge_origin.
span_width
int count of columns spanned by this cell.
The value of this property may be misleading (often 1) on cells where .is_merge_origin is not True, since
only a merge-origin cell contains complete span information. This property is only intended for use on
cells known to be a merge origin by testing .is_merge_origin.
split()
Remove merge from this (merge-origin) cell.
The merged cell represented by this object will be “unmerged”, yielding a separate unmerged cell for each
grid cell previously spanned by this merge.
Raises ValueError when this cell is not a merge-origin cell. Test with .is_merge_origin before calling.
text
Unicode (str in Python 3) representation of cell contents.
The returned string will contain a newline character ("\n") separating each paragraph and a vertical-tab
("\v") character for each line break (soft carriage return) in the cell’s text.
Assignment to text replaces all text currently contained in the cell. A newline character ("\n") in the
assigned text causes a new paragraph to be started. A vertical-tab ("\v") character in the assigned text
causes a line-break (soft carriage-return) to be inserted. (The vertical-tab character appears in clipboard
text copied from PowerPoint as its encoding of line-breaks.)
Either bytes (Python 2 str) or unicode (Python 3 str) can be assigned. Bytes can be 7-bit ASCII or UTF-8
encoded 8-bit bytes. Bytes values are converted to unicode assuming UTF-8 encoding (which correctly
decodes ASCII).
text_frame
TextFrame instance containing the text that appears in the cell.
vertical_anchor
Vertical alignment of this cell.
This value is a member of the MSO_VERTICAL_ANCHOR enumeration or None. A value of None
indicates the cell has no explicitly applied vertical anchor setting and its effective value is inherited from
its style-hierarchy ancestors.
Assigning None to this property causes any explicitly applied vertical anchor setting to be cleared and
inheritance of its effective value to be restored.
A ChartData object is used to specify the data depicted in a chart. It is used when creating a new chart and when
replacing the data for an existing chart. Most charts are created using a CategoryChartData object, however the
data for XY and bubble chart types is different enough that those each require a distinct chart data object.
class pptx.chart.data.ChartData(number_format=’General’)
ChartData is simply an alias for CategoryChartData and may be removed in a future release. All new
development should use CategoryChartData for creating or replacing the data in chart types other than
XY and Bubble.
class pptx.chart.data.CategoryChartData(number_format=’General’)
Accumulates data specifying the categories and series values for a chart and acts as a proxy for the chart data
table that will be written to an Excel worksheet. Used as a parameter in shapes.add_chart() and Chart.
replace_data().
This object is suitable for use with category charts, i.e. all those having a discrete set of label values (categories)
as the range of their independent variable (X-axis) values. Unlike the ChartData types for charts supporting
a continuous range of independent variable values (such as XyChartData), CategoryChartData has a single
collection of category (X) values and each data point in its series specifies only the Y value. The corresponding
X value is inferred by its position in the sequence.
add_category(label)
Return a newly created Category object having label and appended to the end of the category collection
for this chart. label can be a string, a number, a datetime.date, or datetime.datetime object. All category
labels in a chart must be the same type. All category labels in a chart having multi-level categories must
be strings.
add_series(name, values=(), number_format=None)
Add a series to this data set entitled name and having the data points specified by values, an iterable of
numeric values. number_format specifies how the series values will be displayed, and may be a string, e.g.
‘#,##0’ corresponding to an Excel number format.
categories
Categories object providing access to category-object hierarchy.
Assigning an iterable of category labels (strings, numbers, or dates) replaces the Categories object
with a new one containing a category for each label in the sequence.
Creating a chart from chart data having date categories will cause the chart to have a DateAxis for its
category axis.
values_ref(series)
The Excel worksheet reference to the values for series (not including the column heading).
number_format
The formatting template string, e.g. ‘#,##0.0’, that determines how X and Y values are formatted in this
chart and in the Excel spreadsheet. A number format specified on a series will override this value for that
series. Likewise, a distinct number format can be specified for a particular data point within a series.
class pptx.chart.data.Categories
A sequence of Category objects, also having certain hierarchical graph behaviors for support of multi-level
(nested) categories.
add_category(label)
Return a newly created Category object having label and appended to the end of this category sequence.
label can be a string, a number, a datetime.date, or datetime.datetime object. All category labels in a chart
must be the same type. All category labels in a chart having multi-level categories must be strings.
Creating a chart from chart data having date categories will cause the chart to have a DateAxis for its
category axis.
are_dates
Return True if the first category in this collection has a date label (as opposed to str or numeric). A date
label is one of type datetime.date or datetime.datetime. Returns False otherwise, including when this
category collection is empty. It also returns False when this category collection is hierarchical, because
hierarchical categories can only be written as string labels.
are_numeric
Return True if the first category in this collection has a numeric label (as opposed to a string label),
including if that value is a datetime.date or datetime.datetime object (as those are converted to integers
for storage in Excel). Returns False otherwise, including when this category collection is empty. It
also returns False when this category collection is hierarchical, because hierarchical categories can only
be written as string labels.
depth
The number of hierarchy levels in this category graph. Returns 0 if it contains no categories.
index(category)
The offset of category in the overall sequence of leaf categories. A non-leaf category gets the index of its
first sub-category.
leaf_count
The number of leaf-level categories in this hierarchy. The return value is the same as that of len() only
when the hierarchy is single level.
levels
A generator of (idx, label) sequences representing the category hierarchy from the bottom up. The first
level contains all leaf categories, and each subsequent is the next level up.
number_format
Read/write. Return a string representing the number format used in Excel to format these category values,
e.g. ‘0.0’ or ‘mm/dd/yyyy’. This string is only relevant when the categories are numeric or date type,
although it returns ‘General’ without error when the categories are string labels. Assigning None causes
the default number format to be used, based on the type of the category labels.
class pptx.chart.data.Category(label, parent)
A chart category, primarily having a label to be displayed on the category axis, but also able to be configured in
a hierarchy for support of multi-level category charts.
add_sub_category(label)
Return a newly created Category object having label and appended to the end of the sub-category
sequence for this category.
label
The value that appears on the axis for this category. The label can be a string, a number, or a datetime.date
or datetime.datetime object.
numeric_str_val(date_1904=False)
The string representation of the numeric (or date) label of this category, suitable for use in the XML c:pt
element for this category. The optional date_1904 parameter specifies the epoch used for calculating Excel
date numbers.
sub_categories
The sequence of child categories for this category.
class pptx.chart.data.XyChartData(number_format=’General’)
A specialized ChartData object suitable for use with an XY (aka. scatter) chart. Unlike ChartData, it has no
category sequence. Rather, each data point of each series specifies both an X and a Y value.
add_series(name, number_format=None)
Return an XySeriesData object newly created and added at the end of this sequence, identified by name
and values formatted with number_format.
number_format
The formatting template string, e.g. ‘#,##0.0’, that determines how X and Y values are formatted in this
chart and in the Excel spreadsheet. A number format specified on a series will override this value for that
series. Likewise, a distinct number format can be specified for a particular data point within a series.
class pptx.chart.data.BubbleChartData(number_format=’General’)
A specialized ChartData object suitable for use with a bubble chart. A bubble chart is essentially an XY chart
where the markers are scaled to provide a third quantitative dimension to the exhibit.
add_series(name, number_format=None)
Return a BubbleSeriesData object newly created and added at the end of this sequence, and having
series named name and values formatted with number_format.
number_format
The formatting template string, e.g. ‘#,##0.0’, that determines how X and Y values are formatted in this
chart and in the Excel spreadsheet. A number format specified on a series will override this value for that
series. Likewise, a distinct number format can be specified for a particular data point within a series.
class pptx.chart.data.XySeriesData(chart_data, name, number_format)
The data specific to a particular XY chart series. It provides access to the series label, the series data points, and
an optional number format to be applied to each data point not having a specified number format.
The sequence of data points in an XY series is significant; lines are plotted following the sequence of points,
even if that causes a line segment to “travel backward” (implying a multi-valued function). The data points are
not automatically sorted into increasing order by X value.
add_data_point(x, y, number_format=None)
Return an XyDataPoint object newly created with values x and y, and appended to this sequence.
index
Zero-based integer indicating the sequence position of this series in its chart. For example, the second of
three series would return 1.
name
The name of this series, e.g. ‘Series 1’. This name is used as the column heading for the y-values of this
series and may also appear in the chart legend and perhaps other chart locations.
number_format
The formatting template string that determines how a number in this series is formatted, both in the chart
and in the Excel spreadsheet; for example ‘#,##0.0’. If not specified for this series, it is inherited from the
parent chart data object.
x_values
A sequence containing the X value of each datapoint in this series, in data point order.
y_values
A sequence containing the Y value of each datapoint in this series, in data point order.
class pptx.chart.data.BubbleSeriesData(chart_data, name, number_format)
The data specific to a particular Bubble chart series. It provides access to the series label, the series data points,
and an optional number format to be applied to each data point not having a specified number format.
The sequence of data points in a bubble chart series is maintained throughout the chart building process because
a data point has no unique identifier and can only be retrieved by index.
add_data_point(x, y, size, number_format=None)
Append a new BubbleDataPoint object having the values x, y, and size. The optional number_format is
used to format the Y value. If not provided, the number format is inherited from the series data.
bubble_sizes
A sequence containing the bubble size for each datapoint in this series, in data point order.
data_point_offset
The integer count of data points that appear in all chart series prior to this one.
index
Zero-based integer indicating the sequence position of this series in its chart. For example, the second of
three series would return 1.
name
The name of this series, e.g. ‘Series 1’. This name is used as the column heading for the y-values of this
series and may also appear in the chart legend and perhaps other chart locations.
number_format
The formatting template string that determines how a number in this series is formatted, both in the chart
and in the Excel spreadsheet; for example ‘#,##0.0’. If not specified for this series, it is inherited from the
parent chart data object.
x_values
A sequence containing the X value of each datapoint in this series, in data point order.
y_values
A sequence containing the Y value of each datapoint in this series, in data point order.
6.7 Charts
python-pptx provides an API for adding and manipulating charts. A chart object, like a table, is not a shape. Rather
it is a graphical object contained in a GraphicFrame shape. The shape API, such as position, size, shape id, and
name, are provided by the graphic frame shape. The chart itself is accessed using the chart property on the graphic
frame shape.
The Chart object is the root of a generally hierarchical graph of component objects that together provide access to
the properties and methods required to specify and format a chart.
class pptx.chart.chart.Chart(chartSpace, chart_part)
A chart object.
category_axis
The category axis of this chart. In the case of an XY or Bubble chart, this is the X axis. Raises
ValueError if no category axis is defined (as is the case for a pie chart, for example).
chart_style
Read/write integer index of chart style used to format this chart. Range is from 1 to 48. Value is None if
no explicit style has been assigned, in which case the default chart style is used. Assigning None causes
any explicit setting to be removed. The integer index corresponds to the style’s position in the chart style
gallery in the PowerPoint UI.
chart_title
A ChartTitle object providing access to title properties.
Calling this property is destructive in the sense it adds a chart title element (c:title) to the chart XML if
one is not already present. Use has_title to test for presence of a chart title non-destructively.
chart_type
Member of XL_CHART_TYPE enumeration specifying type of this chart.
If the chart has two plots, for example, a line plot overlayed on a bar plot, the type reported is for the first
(back-most) plot. Read-only.
font
Font object controlling text format defaults for this chart.
has_legend
Read/write boolean, True if the chart has a legend. Assigning True causes a legend to be added to the
chart if it doesn’t already have one. Assigning False removes any existing legend definition along with any
existing legend settings.
has_title
Read/write boolean, specifying whether this chart has a title.
Assigning True causes a title to be added if not already present. Assigning False removes any existing
title along with its text and settings.
legend
A Legend object providing access to the properties of the legend for this chart.
plots
The sequence of plots in this chart. A plot, called a chart group in the Microsoft API, is a distinct sequence
of one or more series depicted in a particular charting type. For example, a chart having a series plotted as
a line overlaid on three series plotted as columns would have two plots; the first corresponding to the three
column series and the second to the line series. Plots are sequenced in the order drawn, i.e. back-most to
front-most. Supports len(), membership (e.g. p in plots), iteration, slicing, and indexed access (e.g.
plot = plots[i]).
replace_data(chart_data)
Use the categories and series values in the ChartData object chart_data to replace those in the XML
and Excel worksheet for this chart.
series
A SeriesCollection object containing all the series in this chart. When the chart has multiple plots,
all the series for the first plot appear before all those for the second, and so on. Series within a plot have
an explicit ordering and appear in that sequence.
value_axis
The ValueAxis object providing access to properties of the value axis of this chart. Raises
ValueError if the chart has no value axis.
class pptx.chart.chart.ChartTitle
Provides properties for manipulating a chart title.
format
ChartFormat object providing access to line and fill formatting.
Return the ChartFormat object providing shape formatting properties for this chart title, such as its line
color and fill.
has_text_frame
Read/write Boolean specifying whether this title has a text frame.
Return True if this chart title has a text frame, and False otherwise. Assigning True causes a text
frame to be added if not already present. Assigning False causes any existing text frame to be removed
along with its text and formatting.
text_frame
TextFrame instance for this chart title.
Return a TextFrame instance allowing read/write access to the text of this chart title and its text format-
ting properties. Accessing this property is destructive in the sense it adds a text frame if one is not present.
Use has_text_frame to test for the presence of a text frame non-destructively.
A legend provides a visual key relating each series of data points to their assigned meaning by mapping a color, line
type, or point shape to each series name. A legend is optional, but there can be at most one. Most aspects of a legend
are determined automatically, but aspects of its position may be specified via the API.
class pptx.chart.chart.Legend
Represents the legend in a chart. A chart can have at most one legend.
font
The Font object that provides access to the text properties for this legend, such as bold, italic, etc.
horz_offset
Adjustment of the x position of the legend from its default. Expressed as a float between -1.0 and 1.0
representing a fraction of the chart width. Negative values move the legend left, positive values move it to
the right. None if no setting is specified.
include_in_layout
True if legend should be located inside plot area.
Read/write boolean specifying whether legend should be placed inside the plot area. In many cases this
will cause it to be superimposed on the chart itself. Assigning None to this property causes any c:overlay
6.7. Charts 99
python-pptx Documentation, Release 0.6.22
element to be removed, which is interpreted the same as True. This use case should rarely be required
and assigning a boolean value is recommended.
position
Read/write XL_LEGEND_POSITION enumeration value specifying the general region of the chart in
which to place the legend.
A chart typically has two axes, a category axis and a value axis. In general, one of these is horizontal and the other is
vertical, where which is which depends on the chart type. For example, the category axis is horizontal on a column
chart, but vertical on a bar chart.
A chart where the independent variable is in a continuous (numeric) range, such as an XY/scatter chart, does not have
a category axis. Rather it has two value axes.
A category is perhaps most commonly a string label, such as 'East' or 'Revenue'; however a category can also
be a number or a date (although all categories in a chart must be the same type).
When a chart’s categories are dates, the category axis is generally, but not necessarily a DateAxis object.
A Chart may have zero to four axes. A pie chart, for example, has neither a category nor a value axis.
class pptx.chart.axis._BaseAxis
Base class for chart axis objects. All axis objects share these properties.
axis_title
An AxisTitle object providing access to title properties.
Calling this property is destructive in the sense that it adds an axis title element (c:title) to the axis XML if
one is not already present. Use has_title to test for presence of axis title non-destructively.
format
The ChartFormat object providing access to the shape formatting properties of this axis, such as its line
color and fill.
has_major_gridlines
Read/write boolean value specifying whether this axis has gridlines at its major tick mark locations. As-
signing True to this property causes major gridlines to be displayed. Assigning False causes them to
be removed.
has_minor_gridlines
Read/write boolean value specifying whether this axis has gridlines at its minor tick mark locations. As-
signing True to this property causes minor gridlines to be displayed. Assigning False causes them to
be removed.
has_title
Read/write boolean specifying whether this axis has a title.
True if this axis has a title, False otherwise. Assigning True causes an axis title to be added if not
already present. Assigning False causes any existing title to be deleted.
major_gridlines
The MajorGridlines object representing the major gridlines for this axis.
major_tick_mark
Read/write XL_TICK_MARK value specifying the type of major tick mark to display on this axis.
maximum_scale
Read/write float value specifying the upper limit of the value range for this axis, the number at the top
or right of the vertical or horizontal value scale, respectively. The value None indicates the upper limit
should be determined automatically based on the range of data point values associated with the axis.
minimum_scale
Read/write float value specifying lower limit of value range, the number at the bottom or left of the value
scale. None if no minimum scale has been set. The value None indicates the lower limit should be
determined automatically based on the range of data point values associated with the axis.
minor_tick_mark
Read/write XL_TICK_MARK value specifying the type of minor tick mark for this axis.
reverse_order
Read/write bool value specifying whether to reverse plotting order for axis.
For a category axis, this reverses the order in which the categories are displayed. This may be desired, for
example, on a (horizontal) bar-chart where by default the first category appears at the bottom. Since we
read from top-to-bottom, many viewers may find it most natural for the first category to appear on top.
For a value axis, it reverses the direction of increasing value from bottom-to-top to top-to-bottom.
tick_labels
The TickLabels instance providing access to axis tick label formatting properties. Tick labels are the
numbers appearing on a value axis or the category names appearing on a category axis.
tick_label_position
Read/write XL_TICK_LABEL_POSITION value specifying where the tick labels for this axis should ap-
pear.
visible
Read/write. True if axis is visible, False otherwise.
class pptx.chart.axis.CategoryAxis
A category axis of a chart.
category_type
A member of XL_CATEGORY_TYPE specifying the scale type of this axis. Unconditionally
CATEGORY_SCALE for a CategoryAxis object.
class pptx.chart.axis.DateAxis
A category axis with dates as its category labels.
This axis-type has some special display behaviors such as making length of equal periods equal and normalizing
month start dates despite unequal month lengths.
category_type
A member of XL_CATEGORY_TYPE specifying the scale type of this axis. Unconditionally
TIME_SCALE for a DateAxis object.
class pptx.chart.axis.AxisTitle
Provides properties for manipulating axis title.
format
ChartFormat object providing access to shape formatting.
Return the ChartFormat object providing shape formatting properties for this axis title, such as its line
color and fill.
has_text_frame
Read/write Boolean specifying presence of a text frame.
Return True if this axis title has a text frame, and False otherwise. Assigning True causes a text frame
to be added if not already present. Assigning False causes any existing text frame to be removed along
with any text contained in the text frame.
text_frame
TextFrame instance for this axis title.
Return a TextFrame instance allowing read/write access to the text of this axis title and its text formatting
properties. Accessing this property is destructive as it adds a new text frame if not already present.
Value Axes
Some axis properties are only relevant to value axes, in particular, those related to numeric values rather than text
category labels.
class pptx.chart.axis.ValueAxis
An axis having continuous (as opposed to discrete) values.
The vertical axis is generally a value axis, however both axes of an XY-type chart are value axes.
crosses
Member of XL_AXIS_CROSSES enumeration specifying the point on this axis where the other axis crosses,
such as auto/zero, minimum, or maximum. Returns XL_AXIS_CROSSES.CUSTOM when a specific nu-
meric crossing point (e.g. 1.5) is defined.
crosses_at
Numeric value on this axis at which the perpendicular axis crosses. Returns None if no crossing value is
set.
major_unit
The float number of units between major tick marks on this value axis. None corresponds to the ‘Auto’
setting in the UI, and specifies the value should be calculated by PowerPoint based on the underlying chart
data.
minor_unit
The float number of units between minor tick marks on this value axis. None corresponds to the ‘Auto’
setting in the UI, and specifies the value should be calculated by PowerPoint based on the underlying chart
data.
Gridlines are the vertical and horizontal lines that extend major tick marks of an axis across the chart to ease compari-
son of a data point with the axis divisions.
class pptx.chart.axis.MajorGridlines
Provides access to the properties of the major gridlines appearing on an axis.
format
The ChartFormat object providing access to the shape formatting properties of this data point, such as
line and fill.
Tick labels are the numbers appearing on a value axis or the category names appearing on a category axis. Certain
formatting options are available for changing how these labels are displayed.
class pptx.chart.axis.TickLabels
A service class providing access to formatting of axis tick mark labels.
font
The Font object that provides access to the text properties for these tick labels, such as bold, italic, etc.
number_format
Read/write string (e.g. “$#,##0.00”) specifying the format for the numbers on this axis. The syn-
tax for these strings is the same as it appears in the PowerPoint or Excel UI. Returns ‘General’ if no
number format has been set. Note that this format string has no effect on rendered tick labels when
number_format_is_linked() is True. Assigning a format string to this property automatically
sets number_format_is_linked() to False.
number_format_is_linked
Read/write boolean specifying whether number formatting should be taken from the source spreadsheet
rather than the value of number_format().
offset
Read/write int value in range 0-1000 specifying the spacing between the tick mark labels and the axis as a
percentange of the default value. 100 if no label offset setting is present.
A plot is a group of series all depicted using the same charting type, e.g. bar, column, line, etc. Most charts have only
a single plot; however, a chart may have multiple, as in where a line plot appears overlaid on a bar plot in the same
chart. In the Microsoft API, this concept has the name chart group. The term plot was chosen for python-pptx to avoid
the common mistake of understanding a chart group to be a group of chart objects.
Certain properties must be set at the plot level. Some of those properties are not present on plots of all chart types. For
example, gap_width is only present on a bar or column plot.
class pptx.chart.plot._BasePlot
A distinct plot that appears in the plot area of a chart. A chart may have more than one plot, in which case they
appear as superimposed layers, such as a line plot appearing on top of a bar chart.
categories
Returns a Categories sequence object containing a Category object for each of the category labels
associated with this plot. The Category class derives from str, so the returned value can be treated as
a simple sequence of strings for the common case where all you need is the labels in the order they appear
on the chart. Categories provides additional properties for dealing with hierarchical categories when
required.
chart
The Chart object containing this plot.
data_labels
DataLabels instance providing properties and methods on the collection of data labels associated with
this plot.
has_data_labels
Read/write boolean, True if the series has data labels. Assigning True causes data labels to be added to
the plot. Assigning False removes any existing data labels.
series
A sequence of Series objects representing the series in this plot, in the order they appear in the plot.
vary_by_categories
Read/write boolean value specifying whether to use a different color for each of the points in this plot.
Only effective when there is a single series; PowerPoint automatically varies color by series when more
than one series is present.
BarPlot objects
The following properties are only present on bar-type plots, which includes both bar and column charts.
class pptx.chart.plot.BarPlot
A bar chart-style plot.
gap_width
Width of gap between bar(s) of each category, as an integer percentage of the bar width. The default value
for a new bar chart is 150, representing 150% or 1.5 times the width of a single bar.
overlap
Read/write int value in range -100..100 specifying a percentage of the bar width by which to overlap
adjacent bars in a multi-series bar chart. Default is 0. A setting of -100 creates a gap of a full bar width
and a setting of 100 causes all the bars in a category to be superimposed. A stacked bar plot has overlap of
100 by default.
BubblePlot objects
Categories objects
Category plots provide access to a Categories object with their .categories property.
class pptx.chart.category.Categories
A sequence of Category objects, each representing a category label on the chart. Provides properties for
dealing with hierarchical categories.
depth
Return an integer representing the number of hierarchical levels in this category collection. Returns 1 for
non-hierarchical categories and 0 if no categories are present (generally meaning no series are present).
flattened_labels
Return a sequence of tuples, each containing the flattened hierarchy of category labels for a leaf category.
Each tuple is in parent -> child order, e.g. ('US', 'CA', 'San Francisco'), with the leaf cat-
egory appearing last. If this categories collection is non-hierarchical, each tuple will contain only a leaf
category label. If the plot has no series (and therefore no categories), an empty tuple is returned.
levels
Return a sequence of CategoryLevel objects representing the hierarchy of this category collection.
The sequence is empty when the category collection is not hierarchical, that is, contains only leaf-level
categories. The levels are ordered from the leaf level to the root level; so the first level will contain the
same categories as this category collection.
Category objects
class pptx.chart.category.Category
An extension of str that provides the category label as its string value, and additional attributes representing
CategoryLevel objects
class pptx.chart.category.CategoryLevel
A sequence of Category objects representing a single level in a hierarchical category collection. This object
is only used when the categories are hierarchical, meaning they have more than one level and higher level
categories group those at lower levels.
A data label is text that labels a particular data point, usually with its value, allowing the point to be interpreted more
clearly than just visually comparing its marker with its axis.
A DataLabels object is not a collection, such as a sequence, and it does not provide access to individual data points.
Rather, it provides properties that allow all the data labels in its scope to be formatted at once.
class pptx.chart.datalabel.DataLabels
Provides access to properties of data labels for a plot or a series.
This is not a collection and does not provide access to individual data labels. Access to individual labels is via
the Point object. The properties this object provides control formatting of all the data labels in its scope.
font
The Font object that provides access to the text properties for these data labels, such as bold, italic, etc.
number_format
Read/write string specifying the format for the numbers on this set of data labels. Returns ‘General’ if
no number format has been set. Note that this format string has no effect on rendered data labels when
number_format_is_linked() is True. Assigning a format string to this property automatically
sets number_format_is_linked() to False.
number_format_is_linked
Read/write boolean specifying whether number formatting should be taken from the source spreadsheet
rather than the value of number_format().
position
Read/write XL_DATA_LABEL_POSITION enumeration value specifying the position of the data labels
with respect to their data point, or None if no position is specified. Assigning None causes PowerPoint to
choose the default position, which varies by chart type.
show_category_name
Read/write. True when name of category should appear in label.
show_legend_key
Read/write. True when data label displays legend-color swatch.
show_percentage
Read/write. True when data label displays percentage.
This option is not operative on all chart types. Percentage appears on polar charts such as pie and donut.
show_series_name
Read/write. True when data label displays series name.
show_value
Read/write. True when label displays numeric value of datapoint.
class pptx.chart.datalabel.DataLabel
The data label associated with an individual data point.
font
The Font object providing text formatting for this data label.
This font object is used to customize the appearance of automatically inserted text, such as the data point
value. The font applies to the entire data label. More granular control of the appearance of custom data
label text is controlled by a font object on runs in the text frame.
has_text_frame
Return True if this data label has a text frame (implying it has custom data label text), and False
otherwise. Assigning True causes a text frame to be added if not already present. Assigning False
causes any existing text frame to be removed along with any text contained in the text frame.
position
Read/write XL_DATA_LABEL_POSITION member specifying the position of this data label with respect
to its data point, or None if no position is specified. Assigning None causes PowerPoint to choose the
default position, which varies by chart type.
text_frame
TextFrame instance for this data label, containing the text of the data label and providing access to its
text formatting properties.
A series is a sequence of data points that represent a coherent set of observations across each of the categories in the
chart. For example, on a chart having regional categories “West”, “East”, and “Mid-west”, a series might be “Q1
Sales” and have values 42, 120, and 34. The series in this case coheres around the first quarter time period.
In general, the type (class) of a series object depends upon the chart type. The following properties are available on
series objects of all types.
class pptx.chart.series._BaseSeries
Base class for BarSeries and other series classes.
format
The ChartFormat instance for this series, providing access to shape properties such as fill and line.
index
The zero-based integer index of this series as reported in its c:ser/c:idx element.
name
The string label given to this series, appears as the title of the column for this series in the Excel worksheet.
It also appears as the label for this series in the legend.
AreaSeries objects
These properties are available on a series belonging to an area-type plot such as AREA_STACKED.
class pptx.chart.series.AreaSeries
A data point series belonging to an area plot.
data_labels
DataLabels object controlling data labels for this series.
format
The ChartFormat instance for this series, providing access to shape properties such as fill and line.
index
The zero-based integer index of this series as reported in its c:ser/c:idx element.
name
The string label given to this series, appears as the title of the column for this series in the Excel worksheet.
It also appears as the label for this series in the legend.
points
The CategoryPoints object providing access to individual data points in this series.
values
Read-only. A sequence containing the float values for this series, in the order they appear on the chart.
BarSeries objects
These properties are available on a series belonging to a bar-type plot. Note that column charts are also bar-type charts.
class pptx.chart.series.BarSeries
A data point series belonging to a bar plot.
invert_if_negative
True if a point having a value less than zero should appear with a fill different than those with a positive
value. False if the fill should be the same regardless of the bar’s value. When True, a bar with a solid
fill appears with white fill; in a bar with gradient fill, the direction of the gradient is reversed, e.g. dark ->
light instead of light -> dark. The term “invert” here should be understood to mean “invert the direction of
the fill gradient”.
data_labels
DataLabels object controlling data labels for this series.
format
The ChartFormat instance for this series, providing access to shape properties such as fill and line.
index
The zero-based integer index of this series as reported in its c:ser/c:idx element.
name
The string label given to this series, appears as the title of the column for this series in the Excel worksheet.
It also appears as the label for this series in the legend.
points
The CategoryPoints object providing access to individual data points in this series.
values
Read-only. A sequence containing the float values for this series, in the order they appear on the chart.
BubbleSeries objects
points
The BubblePoints object providing access to individual data point objects used to discover and adjust
the formatting and data labels of a data point.
format
The ChartFormat instance for this series, providing access to shape properties such as fill and line.
index
The zero-based integer index of this series as reported in its c:ser/c:idx element.
iter_values()
Generate each float Y value in this series, in the order they appear on the chart. A value of None represents
a missing Y value (corresponding to a blank Excel cell).
marker
The Marker instance for this series, providing access to data point marker properties such as fill and
line. Setting these properties determines the appearance of markers for all points in this series that are not
overridden by settings at the point level.
name
The string label given to this series, appears as the title of the column for this series in the Excel worksheet.
It also appears as the label for this series in the legend.
values
Read-only. A sequence containing the float values for this series, in the order they appear on the chart.
LineSeries objects
Marker objects
A marker is the small shape (e.g. diamond or circle) that “marks” each individual data point connected by a series line
in a line-type plot.
class pptx.chart.marker.Marker
Represents a data point marker, such as a diamond or circle, on a line-type chart.
format
The ChartFormat instance for this marker, providing access to shape properties such as fill and line.
size
An integer between 2 and 72 inclusive indicating the size of this marker in points. A value of None
indicates no explicit value is set and the size is inherited from a higher-level setting or the PowerPoint
default (which may be 9). Assigning None removes any explicitly assigned size, causing this value to be
inherited.
element
The lxml element proxied by this object.
style
A member of the XL_MARKER_STYLE enumeration indicating the shape of this marker. Returns None if
no explicit style has been set, which corresponds to the “Automatic” option in the PowerPoint UI.
PieSeries objects
RadarSeries objects
format
The ChartFormat instance for this series, providing access to shape properties such as fill and line.
index
The zero-based integer index of this series as reported in its c:ser/c:idx element.
marker
The Marker instance for this series, providing access to data point marker properties such as fill and
line. Setting these properties determines the appearance of markers for all points in this series that are not
overridden by settings at the point level.
name
The string label given to this series, appears as the title of the column for this series in the Excel worksheet.
It also appears as the label for this series in the legend.
points
The CategoryPoints object providing access to individual data points in this series.
values
Read-only. A sequence containing the float values for this series, in the order they appear on the chart.
XySeries objects
An XY or bubble chart has a points attribute providing access to a sequence of Point objects. That sequence
supports iteration, indexed access, and len().
class pptx.chart.point.CategoryPoints
Sequence providing access to individual Point objects, each representing the visual properties of a data point
in the specified category series.
class pptx.chart.point.BubblePoints
Sequence providing access to the individual data points in a BubbleSeries object.
class pptx.chart.point.XyPoints
Sequence providing access to the individual data points in an XySeries object.
class pptx.chart.point.Point
Provides access to the properties of an individual data point in a series, such as the visual properties of its marker
and the text and font of its data label.
data_label
The DataLabel object representing the label on this data point.
format
The ChartFormat object providing access to the shape formatting properties of this data point, such as
line and fill.
marker
The Marker instance for this point, providing access to the visual properties of the data point marker,
such as fill and line. Setting these properties overrides any value set at the series level.
class pptx.text.text.TextFrame
The part of a shape that contains its text.
Not all shapes have a text frame. Corresponds to the <p:txBody> element that can appear as a child element
of <p:sp>. Not intended to be constructed directly.
add_paragraph()
Return new _Paragraph instance appended to the sequence of paragraphs contained in this text frame.
auto_size
The type of automatic resizing that should be used to fit the text of this shape within its bounding box when
the text would otherwise extend beyond the shape boundaries. May be None, MSO_AUTO_SIZE.NONE,
MSO_AUTO_SIZE.SHAPE_TO_FIT_TEXT, or MSO_AUTO_SIZE.TEXT_TO_FIT_SHAPE.
clear()
Remove all paragraphs except one empty one.
fit_text(font_family=’Calibri’, max_size=18, bold=False, italic=False, font_file=None)
Fit text-frame text entirely within bounds of its shape.
Make the text in this text frame fit entirely within the bounds of its shape by setting word wrap on
and applying the “best-fit” font size to all the text it contains. TextFrame.auto_size is set to
MSO_AUTO_SIZE.NONE. The font size will not be set larger than max_size points. If the path to a
matching TrueType font is provided as font_file, that font file will be used for the font metrics. If font_file
is None, best efforts are made to locate a font file with matchhing font_family, bold, and italic installed on
the current system (usually succeeds if the font is installed).
margin_bottom
Length value representing the inset of text from the bottom text frame border. pptx.util.Inches()
The Font object is encountered as a property of _Run, _Paragraph, and in future other presentation text objects.
class pptx.text.text.Font
Character properties object, providing font size, font name, bold, italic, etc. Corresponds to <a:rPr> child
element of a run. Also appears as <a:defRPr> and <a:endParaRPr> in paragraph and <a:defRPr> in
list style elements.
bold
Get or set boolean bold value of Font, e.g. paragraph.font.bold = True. If set to None, the
bold setting is cleared and is inherited from an enclosing shape’s setting, or a setting in a style or master.
Returns None if no bold attribute is present, meaning the effective bold value is inherited from a master or
the theme.
color
The ColorFormat instance that provides access to the color settings for this font.
fill
FillFormat instance for this font, providing access to fill properties such as fill color.
italic
Get or set boolean italic value of Font instance, with the same behaviors as bold with respect to None
values.
language_id
Get or set the language id of this Font instance. The language id is a member of the
MSO_LANGUAGE_ID enumeration. Assigning None removes any language setting, the same behavior
as assigning MSO_LANGUAGE_ID.NONE.
name
Get or set the typeface name for this Font instance, causing the text it controls to appear in the named
font, if a matching font is found. Returns None if the typeface is currently inherited from the theme.
Setting it to None removes any override of the theme typeface.
size
Read/write Length value or None, indicating the font height in English Metric Units (EMU). None
indicates the font size should be inherited from its style hierarchy, such as a placeholder or document
defaults (usually 18pt). Length is a subclass of int having properties for convenient conversion into
points or other length units. Likewise, the pptx.util.Pt class allows convenient specification of point
values:
underline
Read/write. True, False, None, or a member of the MSO_TEXT_UNDERLINE_TYPE enumeration
indicating the underline setting for this font. None is the default and indicates the underline setting should
be inherited from the style hierarchy, such as from a placeholder. True indicates single underline. False
indicates no underline. Other settings such as double and wavy underlining are indicated with members of
the MSO_TEXT_UNDERLINE_TYPE enumeration.
class pptx.text.text._Paragraph
Paragraph object. Not intended to be constructed directly.
add_line_break()
Add line break at end of this paragraph.
add_run()
Return a new run appended to the runs in this paragraph.
alignment
Horizontal alignment of this paragraph, represented by either a member of the enumeration
PP_PARAGRAPH_ALIGNMENT or None. The value None indicates the paragraph should ‘inherit’ its
effective value from its style hierarchy. Assigning None removes any explicit setting, causing its inherited
value to be used.
clear()
Remove all content from this paragraph. Paragraph properties are preserved. Content includes runs, line
breaks, and fields.
font
Font object containing default character properties for the runs in this paragraph. These character prop-
erties override default properties inherited from parent objects such as the text frame the paragraph is
contained in and they may be overridden by character properties set at the run level.
level
Read-write integer indentation level of this paragraph, having a range of 0-8 inclusive. 0 represents a top-
level paragraph and is the default value. Indentation level is most commonly encountered in a bulleted list,
as is found on a word bullet slide.
line_spacing
Numeric or Length value specifying the space between baselines in successive lines of this paragraph.
A value of None indicates no explicit value is assigned and its effective value is inherited from the para-
graph’s style hierarchy. A numeric value, e.g. 2 or 1.5, indicates spacing is applied in multiples of line
heights. A Length value such as Pt(12) indicates spacing is a fixed height. The Pt value class is a
convenient way to apply line spacing in units of points.
runs
Immutable sequence of _Run objects corresponding to the runs in this paragraph.
space_after
Length value specifying the spacing to appear between this paragraph and the subsequent paragraph. A
value of None indicates no explicit value is assigned and its effective value is inherited from the para-
graph’s style hierarchy. Length objects provide convenience properties, such as .pt and .inches, that
allow easy conversion to various length units.
space_before
Length value specifying the spacing to appear between this paragraph and the prior paragraph. A value
of None indicates no explicit value is assigned and its effective value is inherited from the paragraph’s
style hierarchy. Length objects provide convenience properties, such as .pt and .cm, that allow easy
conversion to various length units.
text
str (unicode) representation of paragraph contents.
Read/write. This value is formed by concatenating the text in each run and field making up the para-
graph, adding a vertical-tab character ("\v") for each line-break element (<a:br>, soft carriage-return)
encountered.
While the encoding of line-breaks as a vertical tab might be surprising at first, doing so is consistent
with PowerPoint’s clipboard copy behavior and allows a line-break to be distinguished from a paragraph
boundary within the str return value.
Assignment causes all content in the paragraph to be replaced. Each vertical-tab character ("\v") in the
assigned str is translated to a line-break, as is each line-feed character ("\n"). Contrast behavior of line-
feed character in TextFrame.text setter. If line-feed characters are intended to produce new paragraphs, use
TextFrame.text instead. Any other control characters in the assigned string are escaped as a hex represen-
tation like “_x001B_” (for ESC (ASCII 27) in this example).
The assigned value can be a 7-bit ASCII byte string (Python 2 str), a UTF-8 encoded 8-bit byte string
(Python 2 str), or unicode. Bytes values are converted to unicode assuming UTF-8 encoding.
class pptx.text.text._Run
Text run object. Corresponds to <a:r> child element in a paragraph.
font
Font instance containing run-level character properties for the text in this run. Character properties can
be and perhaps most often are inherited from parent objects such as the paragraph and slide layout the run
is contained in. Only those specifically overridden at the run level are contained in the font object.
hyperlink
_Hyperlink instance acting as proxy for any <a:hlinkClick> element under the run properties
element. Created on demand, the hyperlink object is available whether an <a:hlinkClick> element is
present or not, and creates or deletes that element as appropriate in response to actions on its methods and
attributes.
text
Read/write. A unicode string containing the text in this run.
Assignment replaces all text in the run. The assigned value can be a 7-bit ASCII string, a UTF-8 encoded
8-bit string, or unicode. String values are converted to unicode assuming UTF-8 encoding.
Any other control characters in the assigned string other than tab or newline are escaped as a hex represen-
tation. For example, ESC (ASCII 27) is escaped as “_x001B_”. Contrast the behavior of TextFrame.text
and _Paragraph.text with respect to line-feed and vertical-tab characters.
The following classes represent click and hover mouse actions, typically a hyperlink. Other actions such as navigating
to another slide in the presentation or running a macro are also possible.
class pptx.action.ActionSetting
Properties specifying how a shape or run reacts to mouse actions.
action
Member of PP_ACTION_TYPE enumeration, such as PP_ACTION.HYPERLINK.
The returned member indicates the type of action that will result when the specified shape or text is clicked
or the mouse pointer is positioned over the shape during a slide show.
If there is no click-action or the click-action value is not recognized (is not one of the official MsoPpAction
values) then PP_ACTION.NONE is returned.
hyperlink
A Hyperlink object representing the hyperlink action defined on this click or hover mouse event. A
Hyperlink object is always returned, even if no hyperlink or other click action is defined.
part
The package part containing this object
target_slide
A reference to the slide in this presentation that is the target of the slide jump action in this shape. Slide
jump actions include PP_ACTION.FIRST_SLIDE, LAST_SLIDE, NEXT_SLIDE, PREVIOUS_SLIDE, and
NAMED_SLIDE. Returns None for all other actions. In particular, the LAST_SLIDE_VIEWED action and
the PLAY (start other presentation) actions are not supported.
A slide object may be assigned to this property, which makes the shape an “internal hyperlink” to the
assigened slide:
Assigning None removes any slide jump action. Note that this is accomplished by removing any action
present (such as a hyperlink), without first checking that it is a slide jump action.
class pptx.action.Hyperlink
Represents a hyperlink action on a shape or text run.
address
Read/write. The URL of the hyperlink. URL can be on http, https, mailto, or file scheme; others may
work. Returns None if no hyperlink is defined, including when another action such as RUN_MACRO is
defined on the object. Assigning None removes any action defined on the object, whether it is a hyperlink
action or not.
part
The package part containing this object
Low-level drawing elements like fill and color that appear repeatedly in various aspects of shapes.
class pptx.dml.chtfmt.ChartFormat(element)
The ChartFormat object provides access to visual shape properties for chart elements like Axis, Series,
and MajorGridlines. It has two properties, fill and line, which return a FillFormat and
LineFormat object respectively. The ChartFormat object is provided by the format property on the
target axis, series, etc.
fill
FillFormat instance for this object, providing access to fill properties such as fill color.
line
The LineFormat object providing access to the visual properties of this object, such as line color and
line style.
background()
Sets the fill type to noFill, i.e. transparent.
fore_color
Return a ColorFormat instance representing the foreground color of this fill.
gradient()
Sets the fill type to gradient.
If the fill is not already a gradient, a default gradient is added. The default gradient corresponds to the
default in the built-in PowerPoint “White” template. This gradient is linear at angle 90-degrees (upward),
with two stops. The first stop is Accent-1 with tint 100%, shade 100%, and satMod 130%. The second
stop is Accent-1 with tint 50%, shade 100%, and satMod 350%.
gradient_angle
Angle in float degrees of line of a linear gradient.
Read/Write. May be None, indicating the angle should be inherited from the style hierarchy. An angle of
0.0 corresponds to a left-to-right gradient. Increasing angles represent counter-clockwise rotation of the
line, for example 90.0 represents a bottom-to-top gradient. Raises TypeError when the fill type is not
MSO_FILL_TYPE.GRADIENT. Raises ValueError for a non-linear gradient (e.g. a radial gradient).
gradient_stops
GradientStops object providing access to stops of this gradient.
Raises TypeError when fill is not gradient (call fill.gradient() first). Each stop represents a color between
which the gradient smoothly transitions.
pattern
Return member of MSO_PATTERN_TYPE indicating fill pattern.
Raises TypeError when fill is not patterned (call fill.patterned() first). Returns None if no pattern
has been set; PowerPoint may display the default PERCENT_5 pattern in this case. Assigning None
will remove any explicit pattern setting, although relying on the default behavior is discouraged and may
produce rendering differences across client applications.
patterned()
Selects the pattern fill type.
Note that calling this method does not by itself set a foreground or background color of the pattern. Rather
it enables subsequent assignments to properties like fore_color to set the pattern and colors.
solid()
Sets the fill type to solid, i.e. a solid color. Note that calling this method does not set a color or by itself
cause the shape to appear with a solid color fill; rather it enables subsequent assignments to properties like
fore_color to set the color.
type
Return a value from the MSO_FILL_TYPE enumeration corresponding to the type of this fill.
class pptx.dml.line.LineFormat(parent)
Provides access to line properties such as color, style, and width.
A LineFormat object is typically accessed via the .line property of a shape such as Shape or Picture.
color
The ColorFormat instance that provides access to the color settings for this line. Essentially a shortcut
for line.fill.fore_color. As a side-effect, accessing this property causes the line fill type to
be set to MSO_FILL.SOLID. If this sounds risky for your use case, use line.fill.type to non-
destructively discover the existing fill type.
dash_style
Return value indicating line style.
Returns a member of MSO_LINE_DASH_STYLE indicating line style, or None if no explicit value has
been set. When no explicit value has been set, the line dash style is inherited from the style hierarchy.
Assigning None removes any existing explicitly-defined dash style.
fill
FillFormat instance for this line, providing access to fill properties such as foreground color.
width
The width of the line expressed as an integer number of English Metric Units. The returned value is an
instance of Length, a value class having properties such as .inches, .cm, and .pt for converting the value
into convenient units.
class pptx.dml.color.RGBColor
Immutable value object defining a particular RGB color.
classmethod from_string(rgb_hex_str)
Return a new instance from an RGB color hex string like '3C2F80'.
class pptx.dml.effect.ShadowFormat(spPr)
Provides access to shadow effect on a shape.
inherit
True if shape inherits shadow settings.
Read/write. An explicitly-defined shadow setting on a shape causes this property to return False. A
shape with no explicitly-defined shadow setting inherits its shadow settings from the style hierarchy (and
so returns True).
Assigning True causes any explicitly-defined shadow setting to be removed and inheritance is restored.
Note this has the side-effect of removing all explicitly-defined effects, such as glow and reflection, and
restoring inheritance for all effects on the shape. Assigning False causes the inheritance link to be
broken and no effects to appear on the shape.
6.11 Image
An image depicted in a Picture shape can be accessed using its image property. The Image object provides
access to detailed properties of the image itself, including the bytes of the image file itself.
6.12 Exceptions
exception pptx.exc.PythonPptxError
Generic error class.
exception pptx.exc.PackageNotFoundError
Raised when a package cannot be found at the specified path.
exception pptx.exc.InvalidXmlError
Raised when a value is encountered in the XML that is not valid according to the schema.
class pptx.util.Pt
Bases: pptx.util.Length
Convenience value class for specifying a length in points
6.14 Enumerations
Documentation for the various enumerations used for python-pptx property settings can be found here:
6.14.1 MSO_AUTO_SHAPE_TYPE
BEVEL Bevel
BLOCK_ARC Block arc
CAN Can
CHART_PLUS Chart Plus
CHART_STAR Chart Star
CHART_X Chart X
CHEVRON Chevron
CHORD Geometric chord shape
CIRCULAR_ARROW Block arrow that follows a curved 180-degree angle
CLOUD Cloud
CLOUD_CALLOUT Cloud callout
CORNER Corner
CORNER_TABS Corner Tabs
CROSS Cross
CUBE Cube
CURVED_DOWN_ARROW Block arrow that curves down
CURVED_DOWN_RIBBON Ribbon banner that curves down
CURVED_LEFT_ARROW Block arrow that curves left
CURVED_RIGHT_ARROW Block arrow that curves right
CURVED_UP_ARROW Block arrow that curves up
CURVED_UP_RIBBON Ribbon banner that curves up
DECAGON Decagon
DIAGONAL_STRIPE Diagonal Stripe
DIAMOND Diamond
DODECAGON Dodecagon
DONUT Donut
DOUBLE_BRACE Double brace
DOUBLE_BRACKET Double bracket
DOUBLE_WAVE Double wave
DOWN_ARROW Block arrow that points down
DOWN_ARROW_CALLOUT Callout with arrow that points down
DOWN_RIBBON Ribbon banner with center area below ribbon ends
EXPLOSION1 Explosion
EXPLOSION2 Explosion
FLOWCHART_ALTERNATE_PROCESS Alternate process flowchart symbol
FLOWCHART_CARD Card flowchart symbol
6.14.2 MSO_AUTO_SIZE
shape.text_frame.auto_size = MSO_AUTO_SIZE.TEXT_TO_FIT_SHAPE
The word-wrap setting of the text frame interacts with the auto-size setting to determine the specific auto-sizing
behavior.
Note that TextFrame.auto_size can also be set to None, which removes the auto size setting altogether. This
causes the setting to be inherited, either from the layout placeholder, in the case of a placeholder shape, or from the
theme.
NONE No automatic sizing of the shape or text will be done. Text can freely extend beyond the horizontal and
vertical edges of the shape bounding box.
SHAPE_TO_FIT_TEXT The shape height and possibly width are adjusted to fit the text. Note this setting interacts
with the TextFrame.word_wrap property setting. If word wrap is turned on, only the height of the shape will be
adjusted; soft line breaks will be used to fit the text horizontally.
TEXT_TO_FIT_SHAPE The font size is reduced as necessary to fit the text within the shape.
MIXED Return value only; indicates a combination of automatic sizing schemes are used.
6.14.3 MSO_COLOR_TYPE
6.14.4 MSO_CONNECTOR_TYPE
shapes = prs.slides[0].shapes
connector = shapes.add_connector(
MSO_CONNECTOR.STRAIGHT, Cm(2), Cm(2), Cm(10), Cm(10)
)
assert connector.left.cm == 2
6.14.5 MSO_FILL_TYPE
BACKGROUND The shape is transparent, such that whatever is behind the shape shows through. Often this is the
slide background, but if a visible shape is behind, that will show through.
GRADIENT Shape is filled with a gradient
GROUP Shape is part of a group and should inherit the fill properties of the group.
PATTERNED Shape is filled with a pattern
PICTURE Shape is filled with a bitmapped image
SOLID Shape is filled with a solid color
TEXTURED Shape is filled with a texture
6.14.6 MSO_LANGUAGE_ID
font.language_id = MSO_LANGUAGE_ID.POLISH
6.14.7 MSO_LINE_DASH_STYLE
shape.line.dash_style = MSO_LINE.DASH_DOT_DOT
6.14.8 MSO_PATTERN_TYPE
fill = shape.fill
fill.patterned()
fill.pattern == MSO_PATTERN.WAVE
CROSS Cross
DARK_DOWNWARD_DIAGONAL Dark Downward Diagonal
DARK_HORIZONTAL Dark Horizontal
DARK_UPWARD_DIAGONAL Dark Upward Diagonal
DARK_VERTICAL Dark Vertical
DASHED_DOWNWARD_DIAGONAL Dashed Downward Diagonal
DASHED_HORIZONTAL Dashed Horizontal
DASHED_UPWARD_DIAGONAL Dashed Upward Diagonal
DASHED_VERTICAL Dashed Vertical
DIAGONAL_BRICK Diagonal Brick
DIAGONAL_CROSS Diagonal Cross
DIVOT Pattern Divot
DOTTED_DIAMOND Dotted Diamond
DOTTED_GRID Dotted Grid
DOWNWARD_DIAGONAL Downward Diagonal
HORIZONTAL Horizontal
HORIZONTAL_BRICK Horizontal Brick
LARGE_CHECKER_BOARD Large Checker Board
LARGE_CONFETTI Large Confetti
LARGE_GRID Large Grid
LIGHT_DOWNWARD_DIAGONAL Light Downward Diagonal
6.14.9 MSO_SHAPE_TYPE
AUTO_SHAPE AutoShape
CALLOUT Callout shape
CANVAS Drawing canvas
CHART Chart, e.g. pie chart, bar chart
COMMENT Comment
DIAGRAM Diagram
EMBEDDED_OLE_OBJECT Embedded OLE object
FORM_CONTROL Form control
FREEFORM Freeform
GROUP Group shape
IGX_GRAPHIC SmartArt graphic
INK Ink
INK_COMMENT Ink Comment
LINE Line
LINKED_OLE_OBJECT Linked OLE object
LINKED_PICTURE Linked picture
MEDIA Media
OLE_CONTROL_OBJECT OLE control object
PICTURE Picture
PLACEHOLDER Placeholder
SCRIPT_ANCHOR Script anchor
TABLE Table
TEXT_BOX Text box
TEXT_EFFECT Text effect
WEB_VIDEO Web video
MIXED Mixed shape types
6.14.10 MSO_TEXT_UNDERLINE_TYPE
Indicates the type of underline for text. Used with Font.underline to specify the style of text underlining.
Alias: MSO_UNDERLINE
Example:
run.font.underline = MSO_UNDERLINE.DOUBLE_LINE
6.14.11 MSO_THEME_COLOR_INDEX
Indicates the Office theme color, one of those shown in the color gallery on the formatting ribbon.
Alias: MSO_THEME_COLOR
Example:
shape.fill.solid()
shape.fill.fore_color.theme_color == MSO_THEME_COLOR.ACCENT_1
6.14.12 MSO_VERTICAL_ANCHOR
Specifies the vertical alignment of text in a text frame. Used with the .vertical_anchor property of the
TextFrame object. Note that the vertical_anchor property can also have the value None, indicating there
is no directly specified vertical anchor setting and its effective value is inherited from its placeholder if it has one or
from the theme. None may also be assigned to remove an explicitly specified vertical anchor setting.
Alias: MSO_ANCHOR
Example:
TOP Aligns text to top of text frame and inherits its value from its layout placeholder or theme.
MIDDLE Centers text vertically
BOTTOM Aligns text to bottom of text frame
MIXED Return value only; indicates a combination of the other states.
6.14.13 PP_ACTION_TYPE
6.14.14 PP_MEDIA_TYPE
movie = slide.shapes[0]
assert movie.media_type == PP_MEDIA_TYPE.MOVIE
6.14.15 PP_PARAGRAPH_ALIGNMENT
shape.paragraphs[0].alignment = PP_ALIGN.CENTER
6.14.16 PP_PLACEHOLDER_TYPE
placeholder = slide.placeholders[0]
assert placeholder.type == PP_PLACEHOLDER.TITLE
BITMAP Bitmap
BODY Body
CENTER_TITLE Center Title
CHART Chart
DATE Date
FOOTER Footer
HEADER Header
MEDIA_CLIP Media Clip
OBJECT Object
ORG_CHART Organization Chart
PICTURE Picture
SLIDE_NUMBER Slide Number
SUBTITLE Subtitle
TABLE Table
TITLE Title
VERTICAL_BODY Vertical Body
VERTICAL_OBJECT Vertical Object
VERTICAL_TITLE Vertical Title
MIXED Return value only; multiple placeholders of differing types.
6.14.17 XL_AXIS_CROSSES
Specifies the point on the specified axis where the other axis crosses.
Example:
value_axis.crosses = XL_AXIS_CROSSES.MAXIMUM
6.14.18 XL_CATEGORY_TYPE
date_axis = chart.category_axis
assert date_axis.category_type == XL_CATEGORY_TYPE.TIME_SCALE
6.14.19 XL_CHART_TYPE
THREE_D_AREA 3D Area.
THREE_D_AREA_STACKED 3D Stacked Area.
THREE_D_AREA_STACKED_100 100% Stacked Area.
THREE_D_BAR_CLUSTERED 3D Clustered Bar.
THREE_D_BAR_STACKED 3D Stacked Bar.
THREE_D_BAR_STACKED_100 3D 100% Stacked Bar.
THREE_D_COLUMN 3D Column.
THREE_D_COLUMN_CLUSTERED 3D Clustered Column.
THREE_D_COLUMN_STACKED 3D Stacked Column.
THREE_D_COLUMN_STACKED_100 3D 100% Stacked Column.
THREE_D_LINE 3D Line.
THREE_D_PIE 3D Pie.
THREE_D_PIE_EXPLODED Exploded 3D Pie.
AREA Area
AREA_STACKED Stacked Area.
AREA_STACKED_100 100% Stacked Area.
BAR_CLUSTERED Clustered Bar.
BAR_OF_PIE Bar of Pie.
BAR_STACKED Stacked Bar.
BAR_STACKED_100 100% Stacked Bar.
BUBBLE Bubble.
BUBBLE_THREE_D_EFFECT Bubble with 3D effects.
COLUMN_CLUSTERED Clustered Column.
COLUMN_STACKED Stacked Column.
COLUMN_STACKED_100 100% Stacked Column.
CONE_BAR_CLUSTERED Clustered Cone Bar.
CONE_BAR_STACKED Stacked Cone Bar.
CONE_BAR_STACKED_100 100% Stacked Cone Bar.
CONE_COL 3D Cone Column.
6.14.20 XL_DATA_LABEL_POSITION
data_labels = chart.plots[0].data_labels
data_labels.position = XL_LABEL_POSITION.OUTSIDE_END
6.14.21 XL_LEGEND_POSITION
chart.has_legend = True
chart.legend.position = XL_LEGEND_POSITION.BOTTOM
6.14.22 XL_MARKER_STYLE
Specifies the marker style for a point or series in a line chart, scatter chart, or radar chart.
Example:
series.marker.style = XL_MARKER_STYLE.CIRCLE
6.14.23 XL_TICK_LABEL_POSITION
category_axis = chart.category_axis
category_axis.tick_label_position = XL_TICK_LABEL_POSITION.LOW
6.14.24 XL_TICK_MARK
chart.value_axis.minor_tick_mark = XL_TICK_MARK.INSIDE
The following integer values correspond to built-in Excel number formats. While they cannot be used directly in
python-pptx, this reference can be used to determine the format strings that can be substituted in ChartData.
add_series() to specify a numeric display format for series values.
Further information on string number format codes (such as ‘#,##0’) can be found on this web page.
Contributor Guide
python-pptx has a robust test suite, comprising over 600 tests at the time of writing, both at the acceptance test and unit
test levels. pytest is used for unit tests, with help from the excellent mock library. behave is used for acceptance
tests.
You can run the tests from the source working directory using the following commands:
$ py.test
============================ test session starts ============================
platform darwin -- Python 2.7.5 -- pytest-2.4.2
plugins: cov
collected 301 items
tests/test_oxml.py .........................................
tests/test_presentation.py ...................
tests/test_spec.py ........
tests/test_text.py ..........................
tests/test_util.py ...............
tests/opc/test_packaging.py .....................................................
tests/opc/test_rels.py ..............
tests/parts/test_coreprops.py .
tests/parts/test_image.py ...........
tests/parts/test_part.py ........
tests/parts/test_slides.py ..................
tests/shapes/test_autoshape.py ....................
tests/shapes/test_picture.py .
tests/shapes/test_placeholder.py .
tests/shapes/test_shape.py ...........
tests/shapes/test_shapetree.py ..............
tests/shapes/test_table.py ........................................
149
python-pptx Documentation, Release 0.6.22
$ behave
Feature: Add a text box to a slide
In order to accommodate a requirement for free-form text on a slide
As a presentation developer
I need the ability to place a text box on a slide
xmlchemy is an object-XML mapping layer somewhat reminiscent of SQLAlchemy, hence the name. Mapping XML
elements to objects is not nearly as challenging as mapping to a relational database, so this layer is substantially more
modest. Nevertheless, it provides a powerful and very useful abstraction layer around lxml, particularly well-suited
to providing access to the broad schema of XML elements involved in the Open XML standard.
7.2.3 Example
class CT_Foobar(BaseOxmlElement):
"""
Custom element class corresponding to ``CT_Foobar`` complex type
definition in pml.xsd or other Open XML schema.
"""
hlink = ZeroOrOne('a:hlink', successors=('a:rtl', 'a:extLst'))
eg_fillProperties = ZeroOrOneChoice(
(Choice('a:noFill'), Choice('a:solidFill'), Choice('a:gradFill'),
Choice('a:blipFill'), Choice('a:pattFill')),
successors=(
'a:effectLst', 'a:effectDag', 'a:highlight', 'a:uLnTx',
'a:uLn', 'a:uFillTx' 'a:extLst'
)
)
sz = OptionalAttribute(
'sz', ST_SimpleType, default=ST_SimpleType.OPTION
)
anchor = OptionalAttribute('i', XsdBoolean)
rId = RequiredAttribute('r:id', XsdString)
7.2.4 Protocol
>>> foobar.eg_fillProperties
None
>>> foobar.solidFill
None
>>> solidFill = foobar.get_or_change_to_solidFill()
>>> solidFill
<pptx.oxml.xyz.CT_SolidFill object at 0x10ab4b2d0>
>>> assert foobar.eg_fillProperties is solidFill
>>> assert foobar.solidFill is solidFill
>>> foobar.remove_eg_fillProperties()
>>> foobar.eg_fillProperties
None
>>> foobar.solidFill
None
The OneAndOnlyOne callable generates the API for a required child element:
childElement = OneAndOnlyOne('ns:localTagName')
Unlike the other element declarations, the call does not include a successors argument. Since no API for inserting
a new element is generated, a successors list is not required.
Generated API
childElement property (read-only) Holds a reference to the child element object. Raises InvalidXmlError
on access if the required child element is not present.
Protocol
>>> foobar.childElement
<pptx.oxml.xyz.CT_ChildElement object at 0x10ab4b2d0>
Generated API
childElement property (read/write) Referencing the property returns the type-converted value of the attribute
as determined by the from_xml() method of the simple type class appearing in the declaration (e.g.
ST_SimpleType above). Assignments to the property are validated by the validate() method of the simple
type class, potentially raising TypeError or ValueError. Values are assigned in their natural Python type
and are encoded to the appropriate string value by the to_xml() method of the simple type class.
childElement = ZeroOrOne(
'ns:localTagName', successors=('ns:abc', 'ns:def')
)
Generated API
childElement property (read-only) Holds a reference to the child element object, or None if the element is not
present.
get_or_add_childElement() method Returns the child element object, newly added if not present.
_add_childElement() empty element adder method Returns a newly added empty child element having the
declared tag name. Adding is unconditional and assumes the element is not already present. This method
is called by the get_or_add_childElement() method as needed and may be called by a hand-coded
add_childElement() method as needed. May be overridden to produce customized behavior.
_new_childElement() empty element creator method Returns a new “loose” child element of the declared tag
name. Called by _add_childElement() to obtain a new child element, it may be overridden to customize
the element creation process.
Outside-in layers
Installation
Tutorial
behave Resources
7.4 Vision
A robust, full-featured, and well-documented general-purpose library for manipulating Open XML PowerPoint files.
• robust - High reliability driven by a comprehensive test suite.
• full-featured - Anything that the file format will allow can be accomplished via the API. (Note that visions
often take some time to fulfill completely :).
• well-documented - I don’t know about you, but I find it hard to remember what I was thinking yesterday if I
don’t write it down. That’s not a problem for most of my thinking, but when it comes to how I set up an object
hierarchy to interact, it can be a big time-waster. So I like it when things are nicely laid out in black-and-white.
Other folks seem to like that too :).
• general-purpose - Applicability to all conceivable purposes is valued over being especially well-suited to any
particular purpose. Particular purposes can always be accomplished by building a wrapper library of your own.
Serving general purposes from a particularized library is not so easy.
• create AND manipulate - While this library will perhaps most commonly be used for writing .pptx files, it will
also be suitable for reading .pptx files and inspecting and manipulating their contents. I could see that coming
in handy for full-text indexing, removing speaker notes, changing out templates, adding dynamically generated
slides to static boilerplate, that sort of thing.
7.5 Analysis
Slides
Slide Background
A slide inherits its background from its layout or master (and possibly theme), in that order. Each slide can also
override its inherited background settings.
A background is essentially a container for a fill.
Protocol
Access slide background. Slide.background is the Background object for the slide. Its presence is unconditional and
the same Background object is provided on each access for a particular Slide instance. Its presence does not imply an
explicitly applied slide background:
Detect explicitly-applied slide background. A slide inherits its background unless an explicitly-defined background
has been applied to the slide. The presence of an “override” background is determined by interrogating the .fol-
low_master_background property on each slide:
>>> slide.follow_master_background
True
Note that this step is not necessary to override inheritance. Merely specifying a background fill will also interrupt
inheritance. This approach might be the easiest way though, if all you want is to interrupt inheritance and don’t want
to apply a particular fill.
Restore inheritance of slide background. Any explicitly-applied slide background can be removed by assigning
True to .follow_master_background:
Access background fill. The FillFormat object for a slide background is accessed using the background’s .fill property.
Note that merely accessing this property will suppress inheritance of background for this slide. This shouldn’t normally
be a problem as there would be little reason to access the property without intention to change it:
>>> background.fill
<pptx.dml.fill.FillFormat object at 0x0...>
Apply solid color background. A background color is specified in the same way as fill is specified for a shape. Note
that the FillFormat object also supports applying theme colors and patterns:
>>> fill = background.fill
>>> fill.solid()
>>> fill.fore_color.rgb = RGBColor(255, 0, 0)
Minimal p:bg?:
<p:cSld>
<p:bg>
<p:bgPr>
<a:noFill/>
<a:effectLst/>
</p:bgPr>
</p:bg>
...
</p:cSld>
Schema excerpt
<xsd:complexType name="CT_CommonSlideData">
<xsd:sequence>
<xsd:element name="bg" type="CT_Background" minOccurs="0"/>
<xsd:element name="spTree" type="CT_GroupShape"/>
<xsd:element name="custDataLst" type="CT_CustomerDataList" minOccurs="0"/>
<xsd:element name="controls" type="CT_ControlList" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
(continues on next page)
<xsd:complexType name="CT_Background">
<xsd:choice> <!-- EG_Background - one and only one -->
<xsd:element name="bgPr" type="CT_BackgroundProperties"/>
<xsd:element name="bgRef" type="a:CT_StyleMatrixReference"/>
</xsd:choice>
<xsd:attribute name="bwMode" type="a:ST_BlackWhiteMode" use="optional" default=
˓→"white"/>
</xsd:complexType>
<xsd:complexType name="CT_BackgroundProperties">
<xsd:sequence>
<xsd:group ref="a:EG_FillProperties"/>
<xsd:group ref="a:EG_EffectProperties" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="shadeToTitle" type="xsd:boolean" use="optional" default="false
˓→"/>
</xsd:complexType>
<xsd:group name="EG_FillProperties">
<xsd:choice>
<xsd:element name="noFill" type="CT_NoFillProperties"/>
<xsd:element name="solidFill" type="CT_SolidColorFillProperties"/>
<xsd:element name="gradFill" type="CT_GradientFillProperties"/>
<xsd:element name="blipFill" type="CT_BlipFillProperties"/>
<xsd:element name="pattFill" type="CT_PatternFillProperties"/>
<xsd:element name="grpFill" type="CT_GroupFillProperties"/>
</xsd:choice>
</xsd:group>
<xsd:group name="EG_EffectProperties">
<xsd:choice>
<xsd:element name="effectLst" type="CT_EffectList"/>
<xsd:element name="effectDag" type="CT_EffectContainer"/>
</xsd:choice>
</xsd:group>
<xsd:simpleType name="ST_SlideId">
<xsd:restriction base="xsd:unsignedInt">
<xsd:minInclusive value="256"/>
<xsd:maxExclusive value="2147483648"/>
</xsd:restriction>
</xsd:simpleType>
Notes Slide
A slide may have an associated notes page. The notes it contains are displayed under the slide in the PowerPoint UI
when in edit mode. The slide notes are also shown in presenter mode, are displayed in Notes Pages view, and are
printed on those notes pages.
Internally, a notes page is referred to as a notes slide. This is sensible because it is actually a specialized instance of
a slide. It contains shapes, many of which are placeholders, and allows inserting of new shapes such as auto shapes,
tables, and charts (although it is probably not common). Much of the functionality for a notes slide is inherited from
existing base classes.
A notes slide is created using the notes master as a template. A presentation has no notes master when created from
a template in PowerPoint. One is created according to a PowerPoint-internal preset default the first time it is needed,
which is generally when a notes slide is created. It’s possible one can also be created by entering the Notes Master
view and almost certainly is created by editing the master found there (haven’t tried it though). A presentation can
have at most one notes master.
On creation, certain placeholders (slide image, notes, slide number) are copied from the notes master onto the new
notes slide (if they have not been removed from the master). These “cloned” placeholders inherit position, size, and
formatting from their corresponding notes master placeholder. If the position, size, or formatting of a notes slide
placeholder is changed, the changed property is no long inherited (unchanged properties, however, continue to be
inherited).
The remaining three placeholders that can appear on the notes master (date, header text, footer text) can optionally be
made to appear on an individual notes slide using the Header and Footer. . . dialog. This dialog also has a button allow-
ing all notes slides to be updated with the selected options. There appears to be some heuristic logic that automatically
propagates these settings to notes for new slides as they are created.
A notes slide is not automatically created for each slide. Rather it is created the first time it is needed, perhaps most
commonly when notes text is typed into the notes area under the slide in the UI.
Candidate Protocol
A notes slide is created on first access if one doesn’t exist. Consequently, Slide.has_notes_slide is provided to detect
the presence of an existing notes slide, avoiding creation of unwanted notes slide objects:
>>> slide.has_notes_slide
False
Because a notes slide is created on first access, Slide.notes_slide unconditionally returns a NotesSlide object. Once
created, the same instance is returned on each call:
Like any slide (slide, slide layout, slide master, etc.), a notes slide has shapes and placeholders, as well as other
standard properties:
>>> notes_slide.shapes
<pptx.shapes.shapetree.NotesSlideShapes object at 0x10698c1e0>
>>> notes_slide.placeholders
<pptx.shapes.shapetree.NotesSlidePlaceholders object at 0x10698f622>
The distinctive characteristic of a notes slide is the notes it contains. These notes are contained in the text frame of the
notes placeholder and are manipulated using the same properties and methods as any shape textframe:
PowerPoint behavior
• Notes page has its own view (View > Notes Page)
– Notes can be edited from there too
– It has a hide background graphics option and the other background settings
– Notes have richer edit capabilities (such as ruler for tabs and indents) in the Notes view.
• A notes slide, once created, doesn’t disappear when its notes content is deleted.
• NotesSlide placeholders inherit properties from the NotesMaster placeholder of the same type.
• For some reason PowerPoint adds a second theme for the NotesMaster, not sure what that’s all about. I’ll just add
the default theme2.xml, then folks can avoid that if they encounter problems just by pre-loading a notesMaster
of their own in their template.
Example XML
<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
˓→">
<p:cSld>
<p:spTree>
<p:nvGrpSpPr>
<p:cNvPr id="1" name=""/>
<p:cNvGrpSpPr/>
<p:nvPr/>
</p:nvGrpSpPr>
<p:grpSpPr>
<a:xfrm>
<a:off x="0" y="0"/>
<a:ext cx="0" cy="0"/>
<a:chOff x="0" y="0"/>
<a:chExt cx="0" cy="0"/>
</a:xfrm>
</p:grpSpPr>
</p:spTree>
</p:cSld>
<p:clrMapOvr>
<a:masterClrMapping/>
</p:clrMapOvr>
</p:notes>
<p:notes
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
(continues on next page)
</p:ext>
</p:extLst>
</p:cSld>
<p:clrMapOvr>
<a:masterClrMapping/>
</p:clrMapOvr>
</p:notes>
<xsd:complexType name="CT_CommonSlideData">
<xsd:sequence>
<xsd:element name="bg" type="CT_Background" minOccurs="0"/>
<xsd:element name="spTree" type="CT_GroupShape"/>
<xsd:element name="custDataLst" type="CT_CustomerDataList" minOccurs="0"/>
<xsd:element name="controls" type="CT_ControlList" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
(continues on next page)
Notes Master
A presentation may have a notes master part (zero or one). The notes master determines the background elements and
default layout of a notes page.
In the PowerPoint UI, a notes item is called a “notes page”; internally however, it is referred to as a “notes slide”, is
based on the Slide object, and shares many behaviors with it such as containing shapes and inheriting from a master.
A notes slide is created on-first use, perhaps most frequently by typing text into the notes pane. When a new notes
slide is created, it is based on the notes master. If no notes master is yet present, a new one is created from an internal
PowerPoint-preset default and added to the package.
When a notes slide is created from the notes master, certain placeholders are partially “cloned” from the master. All
other placeholders and shapes remain only on the master. The cloning process only creates placeholder shapes on the
notes slide, but does not copy position or size information or other formatting. By default, position, size, and other
formatting is inherited from the corresponding master placeholder. This achieves consistency through a presentation.
If position, size, etc. is changed on a NotesSlide, the new position overrides that on the master. This override is
property-by-property.
A notes slide maintains a relationship with the master it was created from. This relationship is traversed to access the
master placeholder properties for inheritance purposes.
A master can contain at most one each of six different placeholders: slide image, notes (textbox), header, footer, date,
and slide number. The header, footer, and date placeholders are not copied to the notes slide by default. These three
placeholders can be individually shown or hidden (copied to or deleted from the notes slide actually) using the Insert
> Header and Footer. . . menu option/dialog. This dialog is also available from the Page Setup dialog.
All other items on the notes master, such as background color/texture/image and any additional text boxes or other
shapes such as a logo, constitute “background graphics” and are shown by default. The may be hidden or re-shown on
a notes slide-by-slide basis using the Format Background. . . (context or menu bar) menu item.
Candidate Protocol
It provides access to its placeholders and its shapes (which include placeholders):
>>> notes_master.shapes
<pptx.shapes.shapetree.MasterShapes object at 0x10698d140>
>>> notes_master.placeholders
<pptx.shapes.shapetree.MasterPlaceholders object at 0x1069902f0>
Call stacks:
• _BaseSlide.placeholders
=> BasePlaceholders() => _BaseShapes + _is_member_elm() override
• NotesMaster.placeholders
=> _BaseMaster.placeholders
=> MasterPlaceholders()
=> BasePlaceholders() + get() + _shape_factory() override => _BaseShapes +
_is_member_elm() override
PowerPoint behavior
• A NotesSlide placeholder inherits properties from the NotesMaster placeholder of the same type (there can be
at most one).
• For some reason PowerPoint adds a second theme for the NotesMaster, not sure what that’s all about. I’ll just
add the default theme2.xml, then folks can avoid that if there are problems just by pre-loading a notesMaster of
their own in their template.
<xsd:complexType name="CT_NotesMaster">
<xsd:sequence>
<xsd:element name="cSld" type="CT_CommonSlideData"/>
<xsd:element name="clrMap" type="a:CT_ColorMapping"/>
<xsd:element name="hf" type="CT_HeaderFooter" minOccurs="0"/>
<xsd:element name="notesStyle" type="a:CT_TextListStyle" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_CommonSlideData">
<xsd:sequence>
<xsd:element name="bg" type="CT_Background" minOccurs="0"/>
<xsd:element name="spTree" type="CT_GroupShape"/>
<xsd:element name="custDataLst" type="CT_CustomerDataList" minOccurs="0"/>
<xsd:element name="controls" type="CT_ControlList" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="optional" default=""/>
</xsd:complexType>
<xsd:complexType name="CT_OfficeStyleSheet">
<xsd:sequence>
<xsd:element name="themeElements" type="CT_BaseStyles"/>
<xsd:element name="objectDefaults" type="CT_ObjectStyleDefaults" minOccurs=
˓→"0"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" default=""/>
</xsd:complexType>
Base Slide
A slide is the fundamental visual content container in a presentation, that content taking the form of shape objects.
The SlideMaster and SlideLayout objects are also slides and the three share common behaviors. They each also have
distinctive behaviors. The focus of this page is the common slide characteristics.
Name
For the moment, the only shared attribute is name, stored in the p:sld/p:cSld/@name attribute.
While this attribute is populated by PowerPoint in slide layouts, it is commonly unpopulated in slides and slide masters.
When a slide has no explicit name, PowerPoint uses the default name ‘Slide {n}’, where n is the sequence number of
the slide in the current presentation. This name is not written to the p:cSlide/@name attribute. In the outline pane,
PowerPoint uses the slide title if there is one.
Slide names may come into things when doing animations. Otherwise they don’t show up in the commonly-used parts
of the UI.
XML specimens
Schema excerpt
<xsd:complexType name="CT_SlideLayout">
<xsd:sequence>
<xsd:element name="cSld" type="CT_CommonSlideData"/>
<xsd:element name="clrMapOvr" type="a:CT_ColorMappingOverride" minOccurs="0"/>
<xsd:element name="transition" type="CT_SlideTransition" minOccurs="0"/>
<xsd:element name="timing" type="CT_SlideTiming" minOccurs="0"/>
<xsd:element name="hf" type="CT_HeaderFooter" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="showMasterSp" type="xsd:boolean" default="true"/>
<xsd:attribute name="showMasterPhAnim" type="xsd:boolean" default="true"/>
<xsd:attribute name="matchingName" type="xsd:string" default=""/>
<xsd:attribute name="type" type="ST_SlideLayoutType" default="cust"/>
<xsd:attribute name="preserve" type="xsd:boolean" default="false"/>
<xsd:attribute name="userDrawn" type="xsd:boolean" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_CommonSlideData">
(continues on next page)
<xsd:complexType name="CT_ColorMappingOverride">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="masterClrMapping" type="CT_EmptyElement"/>
<xsd:element name="overrideClrMapping" type="CT_ColorMapping"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_ColorMapping">
<xsd:sequence>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="bg1" type="ST_ColorSchemeIndex" use="required"/>
<xsd:attribute name="tx1" type="ST_ColorSchemeIndex" use="required"/>
<xsd:attribute name="bg2" type="ST_ColorSchemeIndex" use="required"/>
<xsd:attribute name="tx2" type="ST_ColorSchemeIndex" use="required"/>
<xsd:attribute name="accent1" type="ST_ColorSchemeIndex" use="required"/>
<xsd:attribute name="accent2" type="ST_ColorSchemeIndex" use="required"/>
<xsd:attribute name="accent3" type="ST_ColorSchemeIndex" use="required"/>
<xsd:attribute name="accent4" type="ST_ColorSchemeIndex" use="required"/>
<xsd:attribute name="accent5" type="ST_ColorSchemeIndex" use="required"/>
<xsd:attribute name="accent6" type="ST_ColorSchemeIndex" use="required"/>
<xsd:attribute name="hlink" type="ST_ColorSchemeIndex" use="required"/>
<xsd:attribute name="folHlink" type="ST_ColorSchemeIndex" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_EmptyElement"/>
Slide
A slide is the fundamental visual content container in a presentation, that content taking the form of shape objects.
The slides in a presentation are owned by the presentation object. In particular, the unique identifier of a slide, the
slide id, is assigned and managed by the presentation part, and is not recorded in the slide XML.
A slide master and slide layout are both closely related to slide and the three share the majority of their properties and
behaviors.
Slide ID
PowerPoint assigns a unique integer identifier to a slide when it is created. Note that this identifier is only present in
the presentation part, and maps to a relationship ID; it is not recorded in the XML of the slide itself. Therefore the
identifier is only unique within a presentation. The ID takes the form of an integer starting at 256 and incrementing
by one for each new slide. Changing the ordering of the slides does not change the id. The id of a deleted slide is
not reused, although I’m not sure whether it’s clever enough not to reuse the id of the last added slide when it’s been
deleted as there doesn’t seem to be any record in the XML of the max value assigned.
XML specimens
<p:sldIdLst>
<p:sldId r:id="rId7" id="256"/>
</p:sldIdLst>
Schema excerpt
<xsd:complexType name="CT_Presentation">
<!-- ... -->
<xsd:element name="sldIdLst" type="CT_SlideIdList" minOccurs="0"/>
<!-- ... -->
</xsd:complexType>
<xsd:complexType name="CT_SlideIdList">
<xsd:sequence>
<xsd:element name="sldId" type="CT_SlideIdListEntry" minOccurs="0" maxOccurs=
˓→"unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_SlideIdListEntry">
<xsd:sequence>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="id" type="ST_SlideId" use="required"/>
<xsd:attribute ref="r:id" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_CommonSlideData">
<xsd:sequence>
<xsd:element name="bg" type="CT_Background" minOccurs="0"/>
<xsd:element name="spTree" type="CT_GroupShape"/>
<xsd:element name="custDataLst" type="CT_CustomerDataList" minOccurs="0"/>
<xsd:element name="controls" type="CT_ControlList" minOccurs="0"/>
(continues on next page)
<xsd:complexType name="CT_Background">
<xsd:choice>
<xsd:element name="bgPr" type="CT_BackgroundProperties"/>
<xsd:element name="bgRef" type="a:CT_StyleMatrixReference"/>
</xsd:choice>
<xsd:attribute name="bwMode" type="a:ST_BlackWhiteMode" use="optional" default=
˓→"white"/>
</xsd:complexType>
<xsd:complexType name="CT_BackgroundProperties">
<xsd:sequence>
<xsd:group ref="a:EG_FillProperties"/>
<xsd:group ref="a:EG_EffectProperties" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="shadeToTitle" type="xsd:boolean" use="optional" default="false
˓→"/>
</xsd:complexType>
<xsd:simpleType name="ST_SlideId">
<xsd:restriction base="xsd:unsignedInt">
<xsd:minInclusive value="256"/>
<xsd:maxExclusive value="2147483648"/>
</xsd:restriction>
</xsd:simpleType>
Slide Master
A slide master acts as a “parent” for zero or more slide layouts, providing an inheritance base for placeholders and
other slide and shape properties.
Schema excerpt
<xsd:complexType name="CT_ColorMapping">
<xsd:sequence>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"
˓→maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="bg1" type="ST_ColorSchemeIndex" use="required"/>
<xsd:attribute name="tx1" type="ST_ColorSchemeIndex" use="required"/>
<xsd:attribute name="bg2" type="ST_ColorSchemeIndex" use="required"/>
<xsd:attribute name="tx2" type="ST_ColorSchemeIndex" use="required"/>
<xsd:attribute name="accent1" type="ST_ColorSchemeIndex" use="required"/>
<xsd:attribute name="accent2" type="ST_ColorSchemeIndex" use="required"/>
<xsd:attribute name="accent3" type="ST_ColorSchemeIndex" use="required"/>
<xsd:attribute name="accent4" type="ST_ColorSchemeIndex" use="required"/>
<xsd:attribute name="accent5" type="ST_ColorSchemeIndex" use="required"/>
<xsd:attribute name="accent6" type="ST_ColorSchemeIndex" use="required"/>
<xsd:attribute name="hlink" type="ST_ColorSchemeIndex" use="required"/>
<xsd:attribute name="folHlink" type="ST_ColorSchemeIndex" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_SlideLayoutIdList">
<xsd:sequence>
<xsd:element name="sldLayoutId" type="CT_SlideLayoutIdListEntry" minOccurs="0"
˓→maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_SlideLayoutIdListEntry">
<xsd:sequence>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="id" type="ST_SlideLayoutId"/>
<xsd:attribute ref="r:id" type="ST_RelationshipId" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_RelationshipId">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
Slide Layout
A slide layout acts as an property inheritance base for zero or more slides. This provides a certain amount of separation
between formatting and content and contributes to visual consistency across the slides of a presentation.
Remove Layout
Preliminary notes
• Images on a removed slide layout appear to disappear automatically (without explicitly dropping their relation-
ship from the slide layout before removing it).
• A “used” layout cannot be removed. Being “used” in this context means the presentation contains one or more
slides based on that layout. The layout provides inherited placeholders, styling, and perhaps other background
objects and will cause a repair error if missing.
Protocol
The default slide layout collection (the one belonging to the first slide master) is accessible directly from the presenta-
tion object:
>>> slide_layouts.remove(slide_layouts[3])
Specimen XML
Each slide master contains a list of its slide layouts. Each layout is uniquely identified by a slide-layout id (although
this is the only place it appears) and is accessed by traversing the relationship-id (rId) in the r:id attribute:
<p:sldMaster>
<!-- ... -->
<p:sldLayoutIdLst>
<p:sldLayoutId id="2147483649" r:id="rId1"/>
<p:sldLayoutId id="2147483650" r:id="rId2"/>
<p:sldLayoutId id="2147483651" r:id="rId3"/>
<p:sldLayoutId id="2147483652" r:id="rId4"/>
<p:sldLayoutId id="2147483653" r:id="rId5"/>
<p:sldLayoutId id="2147483654" r:id="rId6"/>
<p:sldLayoutId id="2147483655" r:id="rId7"/>
<p:sldLayoutId id="2147483656" r:id="rId8"/>
<p:sldLayoutId id="2147483657" r:id="rId9"/>
<p:sldLayoutId id="2147483658" r:id="rId10"/>
<p:sldLayoutId id="2147483659" r:id="rId11"/>
</p:sldLayoutIdLst>
<!-- ... -->
</p:sldMaster>
The layout used by a slide is specified (only) in the .rels file for that slide:
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship
Id="rId1"
Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/
˓→slideLayout"
Target="../slideLayouts/slideLayout1.xml"/>
</Relationships>
Schema excerpt
<xsd:complexType name="CT_SlideLayout">
<xsd:sequence>
<xsd:element name="cSld" type="CT_CommonSlideData"/>
<xsd:element name="clrMapOvr" type="a:CT_ColorMappingOverride" minOccurs="0"/>
<xsd:element name="transition" type="CT_SlideTransition" minOccurs="0"/>
<xsd:element name="timing" type="CT_SlideTiming" minOccurs="0"/>
<xsd:element name="hf" type="CT_HeaderFooter" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="showMasterSp" type="xsd:boolean" default="true"/>
<xsd:attribute name="showMasterPhAnim" type="xsd:boolean" default="true"/>
<xsd:attribute name="matchingName" type="xsd:string" default=""/>
<xsd:attribute name="type" type="ST_SlideLayoutType" default="cust"/>
<xsd:attribute name="preserve" type="xsd:boolean" default="false"/>
<xsd:attribute name="userDrawn" type="xsd:boolean" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_CommonSlideData">
<xsd:sequence>
<xsd:element name="bg" type="CT_Background" minOccurs="0"/>
<xsd:element name="spTree" type="CT_GroupShape"/>
<xsd:element name="custDataLst" type="CT_CustomerDataList" minOccurs="0"/>
<xsd:element name="controls" type="CT_ControlList" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="optional" default=""/>
</xsd:complexType>
Chart
Chart.font
By default, a new chart appears with an 18-point font that is applied to its axes, the legend, tick labels, etc. The size,
color, etc. can be specified for the chart as a whole by settings attributes on /c:chartSpace/c:txPr/a:p/a:pPr/a:defRPr.
XML Specimens
<c:chartSpace>
<!-- ... -->
<c:txPr>
<a:bodyPr/>
<a:lstStyle/>
(continues on next page)
<xsd:complexType name="CT_RelId">
<xsd:attribute ref="r:id" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_ChartSpace">
<xsd:sequence>
<xsd:element name="date1904" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="lang" type="CT_TextLanguageID" minOccurs="0"/>
<xsd:element name="roundedCorners" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="style" type="CT_Style" minOccurs="0"/>
<xsd:element name="clrMapOvr" type="a:CT_ColorMapping" minOccurs="0"/>
<xsd:element name="pivotSource" type="CT_PivotSource" minOccurs="0"/>
<xsd:element name="protection" type="CT_Protection" minOccurs="0"/>
<xsd:element name="chart" type="CT_Chart"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0"/>
<xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0"/>
<xsd:element name="externalData" type="CT_ExternalData" minOccurs="0"/>
<xsd:element name="printSettings" type="CT_PrintSettings" minOccurs="0"/>
<xsd:element name="userShapes" type="CT_RelId" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Chart">
<xsd:sequence>
<xsd:element name="title" type="CT_Title" minOccurs="0"/>
<xsd:element name="autoTitleDeleted" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="pivotFmts" type="CT_PivotFmts" minOccurs="0"/>
<xsd:element name="view3D" type="CT_View3D" minOccurs="0"/>
<xsd:element name="floor" type="CT_Surface" minOccurs="0"/>
<xsd:element name="sideWall" type="CT_Surface" minOccurs="0"/>
<xsd:element name="backWall" type="CT_Surface" minOccurs="0"/>
<xsd:element name="plotArea" type="CT_PlotArea"/>
(continues on next page)
<xsd:complexType name="CT_Style">
<xsd:attribute name="val" type="ST_Style" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_Style">
<xsd:restriction base="xsd:unsignedByte">
<xsd:minInclusive value="1"/>
<xsd:maxInclusive value="48"/>
</xsd:restriction>
</xsd:simpleType>
A chart can have a title. The title is a rich text container, and can contain arbitrary text with arbitrary formatting (font,
size, color, etc.). There is little but one thing to distinquish a chart title from an independent text box; its position is
automatically adjusted by the chart to account for resizing and movement.
A title is visible whenever present. The only way to “hide” it is to delete it, along with its contents.
Although it will not yet be supported, the chart title can be specified in the XML as a cell reference in the Excel
worksheet. In general, any constructive operations on the title will remove this.
Proposed Scope
• Chart.has_title
• Chart.chart_title
• ChartTitle.has_text_frame
• ChartTitle.text_frame
• ChartTitle.format
Candidate protocol
The presence of a chart title is reported by Chart.has_title. Reading this property is non-destructive. Starting
with a newly-created chart, which has no title:
Assigning True to .has_title causes an empty title element to be added along with its text frame elements (when
not already present). This assignment is idempotent, such that assigning True when a chart title is present leaves the
chart unchanged:
Assigning False to .has_title removes the title element from the XML along with its contents. This assignment
is also idempotent:
Access to the chart title is provided by Chart.chart_title. This property always provides a ChartTitle
object; a new one is created if not present. This behavior produces cleaner code for the common “get or add” case;
Chart.has_title is provided to avoid this potentially destructive behavior when required:
ChartTitle.text_frame
The ChartTitle object can contain either a text frame or an Excel cell reference (<c:strRef>). However, the
only operation on the c:strRef element the library will support (for now anyway) is to delete it when adding a text
frame.
ChartTitle.has_text_frame is used to determine whether a text frame is present. Assigning True to .
has_text_frame causes any Excel reference to be removed and an empty text frame to be inserted. If a text frame
is already present, no changes are made:
>>> chart_title.has_text_frame
False
>>> chart_title.has_text_frame = True
>>> chart_title.has_text_frame
True
Assigning False to .has_text_frame removes the text frame element from the XML along with its contents.
This assignment is also idempotent:
The text frame can be accessed using ChartTitle.text_frame. This property always provides a TextFrame
object; one is added if not present and any c:strRef element is removed:
>>> chart.has_text_frame
False
>>> chart_title.text_frame
<pptx.text.text.TextFrame object at 0x65432fe>
>>> chart.has_text_frame
True
XML semantics
• c:autoTitleDeleted set True has no effect on the visibility of a default chart title (no actual text, ‘place-
holder’ display: ‘Chart Title’. It also seems to have no effect on an actual title, having a text frame and actual
text.
XML specimens
Default when clicking Chart Title > Title Above Chart from ribbon (before changing the text of the title):
<c:chart>
<c:title>
<c:layout/>
<c:overlay val="0"/>
</c:title>
<c:autoTitleDeleted val="0"/>
<c:plotArea>
...
</c:plotArea>
</c:chart>
Text ‘Foobar’ typed into chart title just after adding it from ribbon:
<c:title>
<c:tx>
<c:rich>
<a:bodyPr/>
<a:lstStyle/>
<a:p>
<a:pPr>
<a:defRPr/>
</a:pPr>
<a:r>
<a:rPr lang="en-US" dirty="0" smtClean="0"/>
<a:t>Foobar</a:t>
</a:r>
<a:endParaRPr lang="en-US" dirty="0"/>
(continues on next page)
<xsd:complexType name="CT_Chart">
<xsd:sequence>
<xsd:element name="title" type="CT_Title" minOccurs="0"/>
<xsd:element name="autoTitleDeleted" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="pivotFmts" type="CT_PivotFmts" minOccurs="0"/>
<xsd:element name="view3D" type="CT_View3D" minOccurs="0"/>
<xsd:element name="floor" type="CT_Surface" minOccurs="0"/>
<xsd:element name="sideWall" type="CT_Surface" minOccurs="0"/>
<xsd:element name="backWall" type="CT_Surface" minOccurs="0"/>
<xsd:element name="plotArea" type="CT_PlotArea"/>
<xsd:element name="legend" type="CT_Legend" minOccurs="0"/>
<xsd:element name="plotVisOnly" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="dispBlanksAs" type="CT_DispBlanksAs" minOccurs="0"/>
<xsd:element name="showDLblsOverMax" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Title">
<xsd:sequence>
<xsd:element name="tx" type="CT_Tx" minOccurs="0"/>
<xsd:element name="layout" type="CT_Layout" minOccurs="0"/>
<xsd:element name="overlay" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0"/>
<xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Tx">
<xsd:sequence>
<xsd:choice>
<xsd:element name="strRef" type="CT_StrRef"/>
<xsd:element name="rich" type="a:CT_TextBody"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Layout">
<xsd:sequence>
<xsd:element name="manualLayout" type="CT_ManualLayout" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
Axis Title
A chart axis can have a title. Theoretically, the title text can be drawn from a cell in the spreadsheet behind the chart;
however, there is no mechanism for specifying this from the PowerPoint 2011 UI (Mac) and there’s no mention of
such a procedure I could find on search. So only the “manually applied” axis title text will be discussed here, other
than how to remove any elements associated with “linked” text, however they may have gotten there.
The title is a rich text container, and can contain arbitrary text with arbitrary formatting (font, size, color, etc.). There
is little but one thing to distinquish an axis title from an independent text box; its position is automatically adjusted by
the chart to account for resizing and movement.
An axis title is visible whenever present. The only way to “hide” it is to delete it, along with its contents.
Although it will not be supported, it appears that axis title text can be specified in the XML as a cell reference in the
Excel worksheet. This is a so-called “linked” title, and in general, any constructive operations on the axis title will
remove any linked title present.
Proposed Scope
Completed
• Axis.has_title
• Axis.axis_title
• AxisTitle.has_text_frame
• AxisTitle.text_frame
• AxisTitle.format
Pending
Candidate protocol
Typical usage
I expect the most typical use is simply to set the text of the axis title:
Axis.has_axis_title is used to non-destructively test for the presence of an axis title and may also be used to
add an axis title.
An axis on a newly created chart has no axis title:
Assigning True to .has_title causes an empty axis title element to be added along with its text frame elements
(when not already present):
Axis.axis_title is used to access the AxisTitle object for an axis. It will always return an AxisTitle
object, but it may be destructive in the sense that it adds an axis title if there is none:
Assigning False to .has_title removes the title element from the XML along with its contents:
Assigning None to Axis.axis_title has the same effect (not sure we’ll actually implement this as a priority):
>>> axis.has_title
True
>>> axis.axis_title = None
>>> axis.has_title
False
AxisTitle.text_frame
According to the schema and the MS API, the AxisTitle object can contain either a text frame or an Excel cell
reference (<c:strRef>). However, the only operation on the c:strRef element the library will support (for now
anyway) is to delete it when adding a text frame.
A newly added axis title will already have a text frame, but for the sake of completeness, AxisTitle.
has_text_frame will allow the client to test for, add, and remove an axis title text frame. Assigning True to
.has_text_frame causes any Excel reference (<c:strRef>) element to be removed and an empty text frame to
be inserted. If a text frame is already present, no changes are made:
>>> axis_title.has_text_frame
False
>>> axis_title.has_text_frame = True
>>> axis_title.has_text_frame
True
The text frame can be accessed using AxisTitle.text_frame. This call always returns a text frame object,
newly created if not already present:
>>> axis_title.has_text_frame
False
>>> axis_title.text_frame
<pptx.text.text.TextFrame object at 0x65432fe>
>>> axis_title.has_text_frame
True
AxisTitle.orientation
By default, the PowerPoint UI adds an axis title for a vertical axis at 90° counterclockwise rotation. The MS API pro-
vides for rotation to be specified as an integer number of degrees between -90 and 90. Positive angles are interpreted
as counterclockwise from the horizontal. Orientation can also be specified as one of the members of the XlOrienta-
tion enumeration. The enumeration includes values for horizontal, 90° (upward), -90° (downward), and (vertically)
stacked:
MS API
Axis object
AxisTitle object
AxisTitle.Text Returns or sets the axis title text. Setting removes any existing directly-applied formatting, but not
title-level formatting.
AxisTitle.VerticalAlignment Perhaps not terrifically useful since the textbox is automatically positioned and sized,
so no difference is visible in the typical cases.
PowerPoint UI Behaviors
XlOrientation Enumeration
https://msdn.microsoft.com/en-us/library/office/ff746480.aspx
xlDownward (-4170) Text runs downward.
xlHorizontal (-4128) Text runs horizontally.
xlUpward (-4171) Text runs upward.
xlVertical (-4166) Text runs downward and is centered in the cell.
Specimen XML
<c:valAx>
<!-- ... -->
<c:majorGridlines/>
<c:title>
<c:layout/>
<c:overlay val="0"/>
<c:txPr>
<a:bodyPr rot="-5400000" vert="horz"/>
<a:lstStyle/>
<a:p>
<a:pPr>
<a:defRPr/>
</a:pPr>
<a:endParaRPr lang="en-US"/>
</a:p>
</c:txPr>
</c:title>
Edit text directly in UI. Note that c:txPr element is removed when text is added:
<c:title>
<c:tx>
<c:rich>
<a:bodyPr rot="-5400000" vert="horz"/>
<a:lstStyle/>
<a:p>
<a:pPr>
<a:defRPr/>
</a:pPr>
<a:r>
<a:rPr lang="en-US" dirty="0" smtClean="0"/>
<a:t>Foobar</a:t>
</a:r>
<a:endParaRPr lang="en-US" dirty="0"/>
</a:p>
</c:rich>
</c:tx>
<c:layout/>
<c:overlay val="0"/>
</c:title>
<xsd:group name="EG_AxShared">
<xsd:sequence>
<xsd:element name="axId" type="CT_UnsignedInt"/>
<xsd:element name="scaling" type="CT_Scaling"/>
<xsd:element name="delete" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="axPos" type="CT_AxPos"/>
<xsd:element name="majorGridlines" type="CT_ChartLines" minOccurs="0"/>
<xsd:element name="minorGridlines" type="CT_ChartLines" minOccurs="0"/>
<xsd:element name="title" type="CT_Title" minOccurs="0"/>
<xsd:element name="numFmt" type="CT_NumFmt" minOccurs="0"/>
<xsd:element name="majorTickMark" type="CT_TickMark" minOccurs="0"/>
<xsd:element name="minorTickMark" type="CT_TickMark" minOccurs="0"/>
<xsd:element name="tickLblPos" type="CT_TickLblPos" minOccurs="0"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0"/>
<xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0"/>
<xsd:element name="crossAx" type="CT_UnsignedInt"/>
<xsd:choice minOccurs="0" maxOccurs="1">
<xsd:element name="crosses" type="CT_Crosses"/>
<xsd:element name="crossesAt" type="CT_Double"/>
</xsd:choice>
</xsd:sequence>
</xsd:group>
<xsd:complexType name="CT_Title">
<xsd:sequence>
<xsd:element name="tx" type="CT_Tx" minOccurs="0"/>
<xsd:element name="layout" type="CT_Layout" minOccurs="0"/>
<xsd:element name="overlay" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0"/>
<xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
(continues on next page)
<xsd:complexType name="CT_Tx">
<xsd:sequence>
<xsd:choice>
<xsd:element name="strRef" type="CT_StrRef"/>
<xsd:element name="rich" type="a:CT_TextBody"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Layout">
<xsd:sequence>
<xsd:element name="manualLayout" type="CT_ManualLayout" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_ShapeProperties">
<xsd:sequence>
<xsd:element name="xfrm" type="CT_Transform2D"
˓→minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="bwMode" type="ST_BlackWhiteMode"/>
</xsd:complexType>
<xsd:complexType name="CT_TextListStyle">
<xsd:sequence>
<xsd:element name="defPPr" type="CT_TextParagraphProperties" minOccurs="0"/>
<xsd:element name="lvl1pPr" type="CT_TextParagraphProperties" minOccurs="0"/>
<xsd:element name="lvl2pPr" type="CT_TextParagraphProperties" minOccurs="0"/>
<xsd:element name="lvl3pPr" type="CT_TextParagraphProperties" minOccurs="0"/>
<xsd:element name="lvl4pPr" type="CT_TextParagraphProperties" minOccurs="0"/>
<xsd:element name="lvl5pPr" type="CT_TextParagraphProperties" minOccurs="0"/>
<xsd:element name="lvl6pPr" type="CT_TextParagraphProperties" minOccurs="0"/>
<xsd:element name="lvl7pPr" type="CT_TextParagraphProperties" minOccurs="0"/>
<xsd:element name="lvl8pPr" type="CT_TextParagraphProperties" minOccurs="0"/>
<xsd:element name="lvl9pPr" type="CT_TextParagraphProperties" minOccurs="0"/>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name="ST_TextVerticalType">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="horz"/>
<xsd:enumeration value="vert"/>
<xsd:enumeration value="vert270"/>
<xsd:enumeration value="wordArtVert"/>
<xsd:enumeration value="eaVert"/>
<xsd:enumeration value="mongolianVert"/>
<xsd:enumeration value="wordArtVertRtl"/>
</xsd:restriction>
</xsd:simpleType>
On a PowerPoint chart, data points may be labeled as an aid to readers. Typically, the label is the value of the data
point, but a data label may have any combination of its series name, category name, and value. A number format may
also be applied to the value displayed.
Object access
The DataLabels object is not a collection of DataLabel objects. DataLabels controls the formatting of the data labels
for a whole series, so “global” settings in a way of thinking. An individual DataLabel object is accessed using it’s
associated Point object:
data_label = chart.plot[0].series[0].points[0].data_label
DataLabel.font
Proposed protocol:
Position
There are nine choices for where a data label may be positioned relative to its data point marker, although the available
options depend on the chart type. The options are specified using the XL_DATA_LABEL_POSITION enumeration.
XML Semantics. The default position when no <c:dLblPos> element is present (common) depends on the chart
type:
http://msdn.microsoft.com/en-us/library/ff535061(v=office.12).aspx
Proposed protocol:
MS API
The following properties from the MS API DataLabel object are of most interest:
Delete() Deletes the DataLabel object, which might be useful for “undoing” data label overrides and restoring inher-
ited behaviors.
AutoText True if the object automatically generates appropriate text based on context. Read/write Boolean.
Caption Returns or sets the data label text. Read/write String.
Format Returns the line, fill, and effect formatting for the object. Read-only ChartFormat.
NumberFormat Returns or sets the format code for the object. Read/write String.
NumberFormatLinked True if the number format is linked to the cells (so that the number format changes in the
labels when it changes in the cells). Read/write Boolean.
Orientation Returns or sets the text orientation. Read/write Long in range -90 to 90 (degrees).
Position Returns or sets the position of the data label. Read/write XlDataLabelPosition.
Separator Returns or sets the separator used for the data labels on a chart. Used when more than one value is shown,
like category+value. Read/write Variant.
Shadow Returns or sets a value that indicates whether the object has a shadow. Read/write Boolean.
ShowBubbleSize True to show the bubble size for the data labels on a chart. False to hide the bubble size. Read/write
Boolean.
ShowCategoryName True to display the category name for the data labels on a chart. False to hide the category
name. Read/write Boolean.
ShowLegendKey True if the data label legend key is visible. This is a small square of the series color shown in the
legend, and appears adjacent to the data label. Read/write Boolean.
ShowPercentage True to display the percentage value for the data labels on a chart. False to hide the value. This
might only be relevant for pie charts and similar. Read/write Boolean.
ShowSeriesName True to show the series name for the data labels on a chart. False to hide the series name.
Read/write Boolean.
ShowValue True to display a specified chart’s data label values. False to hide the values. Read/write Boolean.
Text Returns or sets the text for the specified object. Read/write String.
VerticalAlignment Returns or sets the vertical alignment of the specified object. Read/write Variant.
PowerPoint behavior
• A default PowerPoint bar chart does not display data labels, but it does have a <c:dLbls> child element on
its <c:barChart> element.
• Data labels are added to a chart in the UI by selecting the Data Labels drop-down menu in the Chart Layout
ribbon. The options include setting the contents of the data label, its position relative to the point, and bringing
up the Format Data Labels dialog.
• The default number format, when no <c:numFmt> child element appears, is equivalent to <c:numFmt
formatCode="General" sourceLinked="1"/>
XML Semantics
• A <c:dLbls> element at the plot level (e.g. <c:barChart>) is overridden completely by a <c:dLbls>
element at the series level. Unless overridden, a <c:dLbls> element at the plot level determines the content
and formatting for data labels on all the plot’s series.
• A <c:dLbl> element appears as a child of <c:dLbls> only when the data label for its associated data point
has overrides.
XML specimens
The <c:dLbls> element is available on a plot (e.g. <c:barChart>), a series (<c:ser>), and perhaps elsewhere.
Default <c:dLbls> element added by PowerPoint when selecting Data Labels > Value from the Chart Layout ribbon:
<c:dLbls>
<c:showLegendKey val="0"/>
<c:showVal val="1"/>
<c:showCatName val="0"/>
<c:showSerName val="0"/>
<c:showPercent val="0"/>
<c:showBubbleSize val="0"/>
</c:dLbls>
A <c:dLbls> element specifying the labels should appear in 10pt Bold Italic Arial Narrow, color Accent 6, 25%
Darker:
<c:dLbls>
<c:txPr>
<a:bodyPr/>
<a:lstStyle/>
<a:p>
<a:pPr>
<a:defRPr sz="1000" b="1" i="1">
<a:solidFill>
<a:schemeClr val="accent6">
<a:lumMod val="75000"/>
</a:schemeClr>
</a:solidFill>
<a:latin typeface="Arial Narrow"/>
</a:defRPr>
</a:pPr>
<a:endParaRPr lang="en-US"/>
</a:p>
</c:txPr>
<c:showLegendKey val="0"/>
<c:showVal val="1"/>
<c:showCatName val="0"/>
<c:showSerName val="0"/>
(continues on next page)
A <c:dLbls> element having an individual point override for font color and outline box:
<c:dLbls>
<c:dLbl>
<c:idx val="0"/>
<c:spPr>
<!-- ouline color (Red) -->
<a:ln>
<a:solidFill>
<a:srgbClr val="FF0000"/>
</a:solidFill>
</a:ln>
</c:spPr>
<c:txPr>
<a:bodyPr/>
<a:lstStyle/>
<a:p>
<a:pPr>
<!-- font color (Green) -->
<a:defRPr>
<a:solidFill>
<a:srgbClr val="00FF00"/>
</a:solidFill>
</a:defRPr>
</a:pPr>
<a:endParaRPr lang="en-US"/>
</a:p>
</c:txPr>
<c:showLegendKey val="0"/>
<c:showCatName val="0"/>
<c:showSerName val="0"/>
</c:dLbl>
<c:spPr/>
<!-- ... -->
</c:dLbls>
<xsd:complexType name="CT_DLbls">
<xsd:sequence>
<xsd:element name="dLbl" type="CT_DLbl" minOccurs="0" maxOccurs="unbounded"/>
<xsd:choice>
<xsd:element name="delete" type="CT_Boolean"/>
<xsd:group ref="Group_DLbls"/>
</xsd:choice>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_DLbl">
<xsd:sequence>
<xsd:element name="idx" type="CT_UnsignedInt"/>
<xsd:choice>
<xsd:element name="delete" type="CT_Boolean"/>
<xsd:group ref="Group_DLbl"/>
</xsd:choice>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_DLblPos">
<xsd:attribute name="val" type="ST_DLblPos" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_NumFmt">
<xsd:attribute name="formatCode" type="xsd:string" use="required"/>
<xsd:attribute name="sourceLinked" type="xsd:boolean"/>
</xsd:complexType>
<xsd:complexType name="CT_TextBody">
<xsd:sequence>
(continues on next page)
<xsd:complexType name="CT_Tx">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="strRef" type="CT_StrRef"/>
<xsd:element name="rich" type="a:CT_TextBody"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name="ST_DLblPos">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="bestFit"/>
<xsd:enumeration value="b"/>
<xsd:enumeration value="ctr"/>
<xsd:enumeration value="inBase"/>
<xsd:enumeration value="inEnd"/>
<xsd:enumeration value="l"/>
<xsd:enumeration value="outEnd"/>
<xsd:enumeration value="r"/>
<xsd:enumeration value="t"/>
</xsd:restriction>
</xsd:simpleType>
A date axis maintains a linear relationship between axis distance and elapsed time in days, months, or years, even if
the data items do not include values for each base time unit. This is in contrast to a category axis, which uses the
independent axis values themselves to determine the discrete set of categories.
The date axis does this by essentially creating a “logical category” for each base time unit in a range, whether the data
contains a value for that time unit or not.
Variations in the number of days in a month (or year) is also taken care of automatically. This would otherwise cause
month starts to appear at days not the first of the month.
This does not make the category axis continuous, however the “grain” of the discrete units can be quite small in
comparison to the axis length. The individual base unit divisions can but are not typically represented graphically. The
granularity of major and minor divisions is specified as a property on the date axis.
MS API
• Axis.CategoryType = XL_CATEGORY_TYPE.TIME
• Axis.BaseUnit = XL_TIME_UNIT.DAYS
Enumerations
XL_CATEGORY_TYPE
• .AUTOMATIC (-4105)
• .CATEGORY (2)
• .TIME (3)
XL_TIME_UNIT https://msdn.microsoft.com/en-us/library/office/ff746136.aspx * .DAYS (0) * .MONTHS (1) *
.YEARS (2)
XML Semantics
In the MS API, DateAxis.CategoryType is used to discover the category type, but is also used to change an axis from
a date axis to a category axis and back. Note the corresponding property in python-pptx is read-only for now.
Changing from a category to date axis leaves the base, major, and minor unit elements in place. They apply again
(instead of the defaults) if the axis is changed back:
<c:baseTimeUnit val="days"/>
<c:majorUnit val="1.0"/>
<c:majorTimeUnit val="months"/>
<c:minorUnit val="1.0"/>
PowerPoint automatically uses a c:dateAx element if the category labels in Excel are dates (numbers with date format-
ting).
python-pptx uses a c:dateAx element if the category labels in the chart data object are datetime.date or date-
time.datetime objects.
Note that python-pptx does not change the category axis type when using Chart.replace_data().
A date axis is only available on an area, bar (including column), or line chart.
The c:auto element under c:catAx or c:dateAx controls whether the category axis changes automatically between
category and date types.
Specimen XML
<c:ser>
<c:idx val="0"/>
<c:order val="0"/>
<c:tx>
<c:strRef>
<c:f>Sheet1!$B$1</c:f>
<c:strCache>
<c:ptCount val="1"/>
<c:pt idx="0">
<c:v>Buzz</c:v>
</c:pt>
</c:strCache>
</c:strRef>
</c:tx>
<c:marker>
<c:symbol val="none"/>
</c:marker>
<c:cat>
<c:numRef>
<c:f>Sheet1!$A$2:$A$520</c:f>
<c:numCache>
<c:formatCode>mm\-dd\-yyyy</c:formatCode>
<c:ptCount val="3"/>
<c:pt idx="0">
<c:v>42156.0</c:v>
</c:pt>
<c:pt idx="1">
<c:v>42157.0</c:v>
</c:pt>
<c:pt idx="2">
<c:v>42158.0</c:v>
</c:pt>
</c:numCache>
</c:numRef>
</c:cat>
<c:val>
<c:numRef>
<c:f>Sheet1!$B$2:$B$520</c:f>
<c:numCache>
<c:formatCode>0.0</c:formatCode>
<c:ptCount val="3"/>
<c:pt idx="0">
<c:v>19.65943065775559</c:v>
</c:pt>
<c:pt idx="1">
<c:v>20.13705095574664</c:v>
</c:pt>
<c:pt idx="2">
<c:v>19.48264757927654</c:v>
</c:pt>
</c:numCache>
</c:numRef>
</c:val>
<c:plotArea>
(continues on next page)
References
<xsd:complexType name="CT_PlotArea">
<xsd:sequence>
<!-- 17 others -->
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="valAx" type="CT_ValAx"/>
<xsd:element name="catAx" type="CT_CatAx"/>
<xsd:element name="dateAx" type="CT_DateAx"/>
<xsd:element name="serAx" type="CT_SerAx"/>
</xsd:choice>
<xsd:element name="dTable" type="CT_DTable" minOccurs="0"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
(continues on next page)
<xsd:complexType name="CT_SerAx">
<xsd:sequence>
<xsd:group ref="EG_AxShared"/>
<xsd:element name="tickLblSkip" type="CT_Skip" minOccurs="0"/>
<xsd:element name="tickMarkSkip" type="CT_Skip" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:group name="EG_AxShared">
<xsd:sequence>
<xsd:element name="axId" type="CT_UnsignedInt"/>
<xsd:element name="scaling" type="CT_Scaling"/>
<xsd:element name="delete" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="axPos" type="CT_AxPos"/>
<xsd:element name="majorGridlines" type="CT_ChartLines" minOccurs="0"/>
<xsd:element name="minorGridlines" type="CT_ChartLines" minOccurs="0"/>
<xsd:element name="title" type="CT_Title" minOccurs="0"/>
<xsd:element name="numFmt" type="CT_NumFmt" minOccurs="0"/>
<xsd:element name="majorTickMark" type="CT_TickMark" minOccurs="0"/>
<xsd:element name="minorTickMark" type="CT_TickMark" minOccurs="0"/>
<xsd:element name="tickLblPos" type="CT_TickLblPos" minOccurs="0"/>
(continues on next page)
<xsd:complexType name="CT_AxisUnit">
<xsd:attribute name="val" type="ST_AxisUnit" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_ChartLines">
<xsd:sequence>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Crosses">
<xsd:attribute name="val" type="ST_Crosses" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_Scaling">
<xsd:sequence>
<xsd:element name="logBase" type="CT_LogBase" minOccurs="0"/>
<xsd:element name="orientation" type="CT_Orientation" minOccurs="0"/>
<xsd:element name="max" type="CT_Double" minOccurs="0"/>
<xsd:element name="min" type="CT_Double" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_NumFmt">
<xsd:attribute name="formatCode" type="xsd:string" use="required"/>
<xsd:attribute name="sourceLinked" type="xsd:boolean"/>
</xsd:complexType>
<xsd:complexType name="CT_TickLblPos">
<xsd:attribute name="val" type="ST_TickLblPos" default="nextTo"/>
</xsd:complexType>
<xsd:complexType name="CT_TickMark">
<xsd:attribute name="val" type="ST_TickMark" default="cross"/>
</xsd:complexType>
<xsd:complexType name="CT_TimeUnit">
<xsd:attribute name="val" type="ST_TimeUnit" default="days"/>
</xsd:complexType>
<xsd:complexType name="CT_Boolean">
<xsd:attribute name="val" type="xsd:boolean" default="true"/>
</xsd:complexType>
<xsd:complexType name="CT_Double">
<xsd:attribute name="val" type="xsd:double" use="required"/>
(continues on next page)
<xsd:simpleType name="ST_AxisUnit">
<xsd:restriction base="xsd:double">
<xsd:minExclusive value="0"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_Crosses">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="autoZero"/>
<xsd:enumeration value="max"/>
<xsd:enumeration value="min"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_TickLblPos">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="high"/>
<xsd:enumeration value="low"/>
<xsd:enumeration value="nextTo"/>
<xsd:enumeration value="none"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_TickMark">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="cross"/>
<xsd:enumeration value="in"/>
<xsd:enumeration value="none"/>
<xsd:enumeration value="out"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_TimeUnit">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="days"/>
<xsd:enumeration value="months"/>
<xsd:enumeration value="years"/>
</xsd:restriction>
</xsd:simpleType>
Chart - Categories
• A category can be None, meaning the category exists, but there is no label for it.
– The string value of it can be ‘’, since it needs to be a string. But the .label value will be None.
Caveats
• Categories are read from the first series in the plot. In all normal situations I’ve ever encountered, all series have
exactly the same set of categories.
I’m not sure why the category labels are redundantly applied to each series, but the fact that they are leads me to
believe I must be missing something; I don’t believe they would repeat them like that if there wasn’t a situation
in which they could be different between two series in the same plot.
Consequently, there might be some edge cases where this won’t work quite as expected. At the same time, I
expect it will work exactly as expected for 99.9% of the cases, maybe 99.99%.
• Categories are not enforced to be strictly hierarchical. So if a higher-level category “breaks” (gets a new value)
without also a new value at the next level, the results might be a little weird. Like changing from USA to Canada,
but leaving NY as the state (by leaving that cell blank).
Basically, the meaning of a structure like this is ambiguous. PowerPoint interprets it without error and python-
pptx interprets it without error, but the results might not exactly match up. PowerPoint seems to take the senior
category break and show the intermediate category as blank or ‘None’. But I suppose it could be interpreted as
the senior category just splits a subordinate one; it’s open to some question.
Multilevel Categories
A category chart can have more than one level of categories, where each individual category is nested in a higher-level
category.
https://www.youtube.com/watch?v=KbyQpzA7fLo
Acceptance Tests
cht-plot-props.feature:
cht-categories.feature:
Scenario: Categories.__len__()
Given a Categories object having 3 categories
Then len(categories) is 3
Scenario: Categories.__getitem__()
Given a Categories object having 3 categories
Then categories[2] is a Category object
Scenario: Categories.__iter__()
Given a Categories object having 3 categories
Then iterating categories produces 3 Category objects
Scenario: Categories.depth
Given a Categories object having 3 levels of categories
Then categories.depth is 3
Scenario: Categories.flattened
Given a Categories object having 3 levels of categories
Then categories.flattened is tuple of 3-tuples
cht-category.feature:
XML semantics
XML specimens
<c:cat>
<c:strRef>
<c:f>Sheet1!$A$2:$A$5</c:f>
<c:strCache>
<c:ptCount val="4"/>
<c:pt idx="0">
<c:v>Category 1</c:v>
</c:pt>
<c:pt idx="1">
<c:v>Category 2</c:v>
</c:pt>
<c:pt idx="2">
<c:v>Category 3</c:v>
</c:pt>
<c:pt idx="3">
<c:v>Category 4</c:v>
</c:pt>
</c:strCache>
</c:strRef>
</c:cat>
Multi-level categories:
<c:cat>
<c:multiLvlStrRef>
<c:f>Sheet1!$C$1:$J$3</c:f>
<c:multiLvlStrCache>
<c:ptCount val="8"/>
<c:lvl>
<c:pt idx="0">
<c:v>county one</c:v>
</c:pt>
<c:pt idx="1">
<c:v>county two</c:v>
(continues on next page)
<c:catAx>
...
<c:noMultiLvlLbl val="0"/>
</c:catAx>
A <c:cat> element is a child of a <c:ser> (series) element and is of the CT_AxDataSource type:
<xsd:complexType name="CT_AxDataSource">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="multiLvlStrRef" type="CT_MultiLvlStrRef"/>
<xsd:element name="numRef" type="CT_NumRef"/>
<xsd:element name="numLit" type="CT_NumData"/>
<xsd:element name="strRef" type="CT_StrRef"/>
<xsd:element name="strLit" type="CT_StrData"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_MultiLvlStrRef">
<xsd:sequence>
<xsd:element name="f" type="xsd:string"/>
<xsd:element name="multiLvlStrCache" type="CT_MultiLvlStrData" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_MultiLvlStrData">
<xsd:sequence>
<xsd:element name="ptCount" type="CT_UnsignedInt" minOccurs="0"/>
<xsd:element name="lvl" type="CT_Lvl" minOccurs="0" maxOccurs=
˓→"unbounded"/>
<xsd:complexType name="CT_Lvl">
<xsd:sequence>
<xsd:element name="pt" type="CT_StrVal" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_StrVal">
<xsd:sequence>
<xsd:element name="v" type="s:ST_Xstring"/>
</xsd:sequence>
<xsd:attribute name="idx" type="xsd:unsignedInt" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_Xstring">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
Chart - Markers
A marker is a small geometric shape that explicitly indicates a data point position on a line-oriented chart. Line, XY,
and Radar are the line-oriented charts. Other chart types do not have markers.
PowerPoint behavior
• Marker Fill
– Solid
– Gradient
– Picture or Texture
– Pattern
• Marker Line
– Solid
XL_MARKER_STYLE enumeration
https://msdn.microsoft.com/en-us/library/bb241374(v=office.12).aspx
XML specimens
Marker properties set at the series level, all markers for the series:
<c:ser>
<!-- ... -->
<c:marker>
<c:spPr>
<a:solidFill>
<a:schemeClr val="accent4">
<a:lumMod val="60000"/>
<a:lumOff val="40000"/>
</a:schemeClr>
(continues on next page)
<a:schemeClr val="accent6">
<a:lumMod val="75000"/>
<a:alpha val="43000"/>
</a:schemeClr>
</a:outerShdw>
</a:effectLst>
</c:spPr>
</c:marker>
<c:bubble3D val="0"/>
(continues on next page)
<a:schemeClr val="accent6">
<a:lumMod val="75000"/>
<a:alpha val="43000"/>
</a:schemeClr>
</a:outerShdw>
</a:effectLst>
</c:spPr>
</c:dPt>
<!-- ... -->
</c:ser>
<xsd:complexType name="CT_DPt">
<xsd:sequence>
<xsd:element name="idx" type="CT_UnsignedInt"/>
<xsd:element name="invertIfNegative" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="marker" type="CT_Marker" minOccurs="0"/>
<xsd:element name="bubble3D" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="explosion" type="CT_UnsignedInt" minOccurs="0"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0"/>
<xsd:element name="pictureOptions" type="CT_PictureOptions" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Marker">
<xsd:sequence>
<xsd:element name="symbol" type="CT_MarkerStyle" minOccurs="0"/>
<xsd:element name="size" type="CT_MarkerSize" minOccurs="0"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_MarkerStyle">
<xsd:attribute name="val" type="ST_MarkerStyle" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_MarkerSize">
<xsd:attribute name="val" type="ST_MarkerSize" default="5"/>
</xsd:complexType>
<xsd:simpleType name="ST_MarkerSize">
<xsd:restriction base="xsd:unsignedByte">
<xsd:minInclusive value="2"/>
<xsd:maxInclusive value="72"/>
</xsd:restriction>
</xsd:simpleType>
Charts - Overview
1. Analysis - add chart type page with schema for each new chart element and see if there’s anything distinctive
about the chart type series
2. feature/sld-add-chart .. add new chart types, steps/chart.py
3. pptx/chart/xmlwriter.py add new type to ChartXmlWriter
4. pptx/chart/xmlwriter.py add _AreaChartXmlWriter, one per new element type
5. pptx/chart/series.py add AreaSeries, one per new element type
There are 73 different possible chart types, but only 16 distinct XML chart-type elements. The implementation effort
is largely proportional to the number of new XML chart-type elements.
Here is an accounting of the implementation status of the 73 chart types:
areaChart
• AREA
• AREA_STACKED
• AREA_STACKED_100
barChart
• BAR_CLUSTERED
• BAR_STACKED
• BAR_STACKED_100
• COLUMN_CLUSTERED
• COLUMN_STACKED
• COLUMN_STACKED_100
bubbleChart
• BUBBLE
• BUBBLE_THREE_D_EFFECT
doughnutChart
• DOUGHNUT
• DOUGHNUT_EXPLODED
lineChart
• LINE
• LINE_MARKERS
• LINE_MARKERS_STACKED
• LINE_MARKERS_STACKED_100
• LINE_STACKED
• LINE_STACKED_100
pieChart
• PIE
• PIE_EXPLODED
radarChart
• RADAR
• RADAR_FILLED
• RADAR_MARKERS
scatterChart
• XY_SCATTER
• XY_SCATTER_LINES
• XY_SCATTER_LINES_NO_MARKERS
• XY_SCATTER_SMOOTH
• XY_SCATTER_SMOOTH_NO_MARKERS
44 remaining:
area3DChart
• THREE_D_AREA
• THREE_D_AREA_STACKED
• THREE_D_AREA_STACKED_100
• THREE_D_BAR_CLUSTERED
• THREE_D_BAR_STACKED
• THREE_D_BAR_STACKED_100
• THREE_D_COLUMN
• THREE_D_COLUMN_CLUSTERED
• THREE_D_COLUMN_STACKED
• THREE_D_COLUMN_STACKED_100
• CONE_BAR_CLUSTERED
• CONE_BAR_STACKED
• CONE_BAR_STACKED_100
• CONE_COL
• CONE_COL_CLUSTERED
• CONE_COL_STACKED
• CONE_COL_STACKED_100
• CYLINDER_BAR_CLUSTERED
• CYLINDER_BAR_STACKED
• CYLINDER_BAR_STACKED_100
• CYLINDER_COL
• CYLINDER_COL_CLUSTERED
• CYLINDER_COL_STACKED
• CYLINDER_COL_STACKED_100
• PYRAMID_BAR_CLUSTERED
• PYRAMID_BAR_STACKED
• PYRAMID_BAR_STACKED_100
• PYRAMID_COL
• PYRAMID_COL_CLUSTERED
• PYRAMID_COL_STACKED
• PYRAMID_COL_STACKED_100
line3DChart
• THREE_D_LINE
pie3DChart
• THREE_D_PIE
• THREE_D_PIE_EXPLODED
ofPieChart
• BAR_OF_PIE
• PIE_OF_PIE
stockChart
• STOCK_HLC
• STOCK_OHLC
• STOCK_VHLC
• STOCK_VOHLC
surfaceChart
• SURFACE
• SURFACE_WIREFRAME
surface3DChart
• SURFACE_TOP_VIEW
• SURFACE_TOP_VIEW_WIREFRAME
data point (point) An individual numeric value, represented by a bar, point, column, or pie slice.
data series (series) A group of related data points. For example, the columns of a series will all be the same color.
category axis (X axis) The horizontal axis of a two-dimensional or three-dimensional chart.
value axis (Y axis) The vertical axis of a two-dimensional or three-dimensional chart.
depth axis (Z axis) The front-to-back axis of a three-dimensional chart.
grid lines Horizontal or vertical lines that may be added to an axis to aid comparison of a data point to an axis value.
legend A key that explains which data series each color or pattern represents.
floor The bottom of a three-dimensional chart.
walls The background of a chart. Three-dimensional charts have a back wall and a side wall, which can be formatted
separately.
data labels Numeric labels on each data point. A data label can represent the actual value or a percentage.
axis title Explanatory text label associated with an axis
data table A optional tabular display within the plot area of the values on which the chart is based. Not to be confused
with the Excel worksheet holding the chart values.
chart title A label explaining the overall purpose of the chart.
chart area Overall chart object, containing the chart and all its auxiliary pieces such as legends and titles.
plot area Region of the chart area that contains the actual plots, bounded by but not including the axes. May contain
more than one plot, each with its own distinct set of series. A plot is known as a chart group in the MS API.
axis . . . may be either a category axis or a value axis . . . on a two-dimensional chart, either the horizontal (x) axis
or the vertical (y) axis. A 3-dimensional chart also has a depth (z) axis. Pie, doughnut, and radar charts have a
radial axis.
How many axes do each of the different chart types have?
series categories . . .
series values . . .
Chart types
• column
– 2-D column
* clustered column
* stacked column
* 100% stacked column
– 3-D column
• pie
– 2-D pie
– 3-D pie
• bar
– 2-D bar
– 3-D bar
– cylinder
– cone
– pyramid
• area
• scatter
• other
– stock (e.g. open-high-low-close)
– surface
– doughnut
– bubble
– radar
<xsd:complexType name="CT_RelId">
<xsd:attribute ref="r:id" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_ChartSpace">
<xsd:sequence>
<xsd:element name="date1904" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="lang" type="CT_TextLanguageID" minOccurs="0"/>
<xsd:element name="roundedCorners" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="style" type="CT_Style" minOccurs="0"/>
<xsd:element name="clrMapOvr" type="a:CT_ColorMapping" minOccurs="0"/>
<xsd:element name="pivotSource" type="CT_PivotSource" minOccurs="0"/>
<xsd:element name="protection" type="CT_Protection" minOccurs="0"/>
<xsd:element name="chart" type="CT_Chart"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0"/>
<xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0"/>
<xsd:element name="externalData" type="CT_ExternalData" minOccurs="0"/>
(continues on next page)
<xsd:complexType name="CT_Chart">
<xsd:sequence>
<xsd:element name="title" type="CT_Title" minOccurs="0"/>
<xsd:element name="autoTitleDeleted" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="pivotFmts" type="CT_PivotFmts" minOccurs="0"/>
<xsd:element name="view3D" type="CT_View3D" minOccurs="0"/>
<xsd:element name="floor" type="CT_Surface" minOccurs="0"/>
<xsd:element name="sideWall" type="CT_Surface" minOccurs="0"/>
<xsd:element name="backWall" type="CT_Surface" minOccurs="0"/>
<xsd:element name="plotArea" type="CT_PlotArea"/>
<xsd:element name="legend" type="CT_Legend" minOccurs="0"/>
<xsd:element name="plotVisOnly" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="dispBlanksAs" type="CT_DispBlanksAs" minOccurs="0"/>
<xsd:element name="showDLblsOverMax" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_PlotArea">
<xsd:sequence>
<xsd:element name="layout" type="CT_Layout" minOccurs="0" maxOccurs="1"/>
<xsd:choice minOccurs="1" maxOccurs="unbounded">
<xsd:element name="areaChart" type="CT_AreaChart"/>
<xsd:element name="area3DChart" type="CT_Area3DChart"/>
<xsd:element name="lineChart" type="CT_LineChart"/>
<xsd:element name="line3DChart" type="CT_Line3DChart"/>
<xsd:element name="stockChart" type="CT_StockChart"/>
<xsd:element name="radarChart" type="CT_RadarChart"/>
<xsd:element name="scatterChart" type="CT_ScatterChart"/>
<xsd:element name="pieChart" type="CT_PieChart"/>
<xsd:element name="pie3DChart" type="CT_Pie3DChart"/>
<xsd:element name="doughnutChart" type="CT_DoughnutChart"/>
<xsd:element name="barChart" type="CT_BarChart"/>
<xsd:element name="bar3DChart" type="CT_Bar3DChart"/>
<xsd:element name="ofPieChart" type="CT_OfPieChart"/>
<xsd:element name="surfaceChart" type="CT_SurfaceChart"/>
<xsd:element name="surface3DChart" type="CT_Surface3DChart"/>
<xsd:element name="bubbleChart" type="CT_BubbleChart"/>
</xsd:choice>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="valAx" type="CT_ValAx"/>
<xsd:element name="catAx" type="CT_CatAx"/>
<xsd:element name="dateAx" type="CT_DateAx"/>
<xsd:element name="serAx" type="CT_SerAx"/>
</xsd:choice>
<xsd:element name="dTable" type="CT_DTable" minOccurs="0"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Boolean">
<xsd:attribute name="val" type="xsd:boolean" use="optional" default="true"/>
</xsd:complexType>
<xsd:complexType name="CT_Double">
<xsd:attribute name="val" type="xsd:double" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_Scaling">
<xsd:sequence>
<xsd:element name="logBase" type="CT_LogBase" minOccurs="0"/>
<xsd:element name="orientation" type="CT_Orientation" minOccurs="0"/>
<xsd:element name="max" type="CT_Double" minOccurs="0"/>
<xsd:element name="min" type="CT_Double" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_NumFmt">
<xsd:attribute name="formatCode" type="s:ST_Xstring" use="required"/>
<xsd:attribute name="sourceLinked" type="xsd:boolean"/>
</xsd:complexType>
<xsd:complexType name="CT_TickMark">
<xsd:attribute name="val" type="ST_TickMark" default="cross"/>
</xsd:complexType>
<xsd:simpleType name="ST_TickMark">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="cross"/>
<xsd:enumeration value="in"/>
<xsd:enumeration value="none"/>
<xsd:enumeration value="out"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_DLbls">
<xsd:sequence>
<xsd:element name="dLbl" type="CT_DLbl" minOccurs="0" maxOccurs="unbounded"/>
<xsd:choice>
<xsd:element name="delete" type="CT_Boolean"/>
<xsd:group ref="Group_DLbls"/>
</xsd:choice>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_DLbl">
<xsd:sequence>
<xsd:element name="idx" type="CT_UnsignedInt"/>
<xsd:choice>
<xsd:element name="delete" type="CT_Boolean"/>
<xsd:group ref="Group_DLbl"/>
</xsd:choice>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
(continues on next page)
<xsd:complexType name="CT_Style">
<xsd:attribute name="val" type="ST_Style" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_Style">
<xsd:restriction base="xsd:unsignedByte">
<xsd:minInclusive value="1"/>
<xsd:maxInclusive value="48"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_Legend">
<xsd:sequence>
<xsd:element name="legendPos" type="CT_LegendPos" minOccurs="0"/>
<xsd:element name="legendEntry" type="CT_LegendEntry" minOccurs="0"
˓→maxOccurs="unbounded"/>
<xsd:complexType name="CT_LegendPos">
<xsd:attribute name="val" type="ST_LegendPos" default="r"/>
</xsd:complexType>
<xsd:simpleType name="ST_LegendPos">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="b"/>
<xsd:enumeration value="tr"/>
<xsd:enumeration value="l"/>
<xsd:enumeration value="r"/>
<xsd:enumeration value="t"/>
</xsd:restriction>
</xsd:simpleType>
(continues on next page)
<xsd:complexType name="CT_DLblPos">
<xsd:attribute name="val" type="ST_DLblPos" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_DLblPos">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="bestFit"/>
<xsd:enumeration value="b"/>
<xsd:enumeration value="ctr"/>
<xsd:enumeration value="inBase"/>
<xsd:enumeration value="inEnd"/>
<xsd:enumeration value="l"/>
<xsd:enumeration value="outEnd"/>
<xsd:enumeration value="r"/>
<xsd:enumeration value="t"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_LblOffset">
<xsd:attribute name="val" type="ST_LblOffset" default="100%"/>
</xsd:complexType>
<xsd:simpleType name="ST_LblOffset">
<xsd:union memberTypes="ST_LblOffsetPercent ST_LblOffsetUShort"/>
</xsd:simpleType>
<xsd:simpleType name="ST_LblOffsetUShort">
<xsd:restriction base="xsd:unsignedShort">
<xsd:minInclusive value="0"/>
<xsd:maxInclusive value="1000"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_LblOffsetPercent">
<xsd:restriction base="xsd:string">
<xsd:pattern value="0*(([0-9])|([1-9][0-9])|([1-9][0-9][0-9])|1000)%"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_Overlap">
<xsd:attribute name="val" type="ST_Overlap" default="0%"/>
</xsd:complexType>
<xsd:simpleType name="ST_Overlap">
<xsd:union memberTypes="ST_OverlapPercent ST_OverlapByte"/>
</xsd:simpleType>
<xsd:simpleType name="ST_OverlapPercent">
<xsd:restriction base="xsd:string">
<xsd:pattern value="(-?0*(([0-9])|([1-9][0-9])|100))%"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_OverlapByte">
<xsd:restriction base="xsd:byte">
<xsd:minInclusive value="-100"/>
(continues on next page)
<xsd:complexType name="CT_Layout">
<xsd:sequence>
<xsd:element name="manualLayout" type="CT_ManualLayout" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_ManualLayout">
<xsd:sequence>
<xsd:element name="layoutTarget" type="CT_LayoutTarget" minOccurs="0"/>
<xsd:element name="xMode" type="CT_LayoutMode" minOccurs="0"/>
<xsd:element name="yMode" type="CT_LayoutMode" minOccurs="0"/>
<xsd:element name="wMode" type="CT_LayoutMode" minOccurs="0"/>
<xsd:element name="hMode" type="CT_LayoutMode" minOccurs="0"/>
<xsd:element name="x" type="CT_Double" minOccurs="0"/>
<xsd:element name="y" type="CT_Double" minOccurs="0"/>
<xsd:element name="w" type="CT_Double" minOccurs="0"/>
<xsd:element name="h" type="CT_Double" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_LayoutMode">
<xsd:attribute name="val" type="ST_LayoutMode" default="factor"/>
</xsd:complexType>
<xsd:simpleType name="ST_LayoutMode">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="edge"/>
<xsd:enumeration value="factor"/>
</xsd:restriction>
</xsd:simpleType>
Area Chart
The area chart is similar to a stacked line chart where the area between the lines is filled in.
XML specimens
<mc:Choice xmlns:c14="http://schemas.microsoft.com/office/drawing/2007/8/2/chart"
˓→Requires="c14">
<c14:style val="118"/>
</mc:Choice>
<mc:Fallback>
<c:style val="18"/>
</mc:Fallback>
</mc:AlternateContent>
<c:chart>
<c:autoTitleDeleted val="0"/>
<c:plotArea>
<c:layout/>
<c:areaChart>
<c:grouping val="standard"/>
<c:varyColors val="0"/>
<c:ser>
<c:idx val="0"/>
<c:order val="0"/>
<c:tx>
<c:strRef>
<c:f>Sheet1!$B$1</c:f>
<c:strCache>
<c:ptCount val="1"/>
<c:pt idx="0">
<c:v>Series 1</c:v>
</c:pt>
</c:strCache>
</c:strRef>
</c:tx>
<c:cat>
<c:numRef>
<c:f>Sheet1!$A$2:$A$6</c:f>
<c:numCache>
<c:formatCode>m/d/yy</c:formatCode>
<c:ptCount val="5"/>
<c:pt idx="0">
<c:v>37261.0</c:v>
</c:pt>
<c:pt idx="1">
<c:v>37262.0</c:v>
</c:pt>
<c:pt idx="2">
<c:v>37263.0</c:v>
</c:pt>
<c:pt idx="3">
<c:v>37264.0</c:v>
</c:pt>
<c:pt idx="4">
<c:v>37265.0</c:v>
</c:pt>
</c:numCache>
</c:numRef>
</c:cat>
<c:val>
(continues on next page)
<xsd:complexType name="CT_Grouping">
<xsd:attribute name="val" type="ST_Grouping" default="standard"/>
</xsd:complexType>
<xsd:simpleType name="ST_Grouping">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="percentStacked"/>
<xsd:enumeration value="standard"/>
<xsd:enumeration value="stacked"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_ChartLines">
<xsd:sequence>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
Doughnut Chart
A doughnut chart is similar in many ways to a pie chart, except there is a “hole” in the middle. It can accept multiple
series, which appear as concentric “rings”.
XML specimens
<mc:Choice xmlns:c14="http://schemas.microsoft.com/office/drawing/2007/8/2/chart"
˓→Requires="c14">
<c14:style val="118"/>
</mc:Choice>
<mc:Fallback>
<c:style val="18"/>
</mc:Fallback>
</mc:AlternateContent>
<c:chart>
<c:autoTitleDeleted val="0"/>
<c:plotArea>
<c:layout/>
<c:doughnutChart>
<c:varyColors val="1"/>
<c:ser>
<c:idx val="0"/>
<c:order val="0"/>
<c:tx>
<c:strRef>
<c:f>Sheet1!$B$1</c:f>
<c:strCache>
<c:ptCount val="1"/>
<c:pt idx="0">
<c:v>Sales</c:v>
</c:pt>
</c:strCache>
</c:strRef>
</c:tx>
<c:cat>
<c:strRef>
<c:f>Sheet1!$A$2:$A$5</c:f>
<c:strCache>
<c:ptCount val="4"/>
<c:pt idx="0">
<c:v>1st Qtr</c:v>
</c:pt>
<c:pt idx="1">
<c:v>2nd Qtr</c:v>
</c:pt>
<c:pt idx="2">
<c:v>3rd Qtr</c:v>
</c:pt>
<c:pt idx="3">
<c:v>4th Qtr</c:v>
</c:pt>
</c:strCache>
</c:strRef>
</c:cat>
(continues on next page)
Chart - Points
A chart may be understood as a graph of a function, formed by rendering a finite number of ordered pairs (e.g. (x, y))
in one of several graphical formats such as bar, pie, or bubble.
A functon can be expressed as:
y = f(x)
where x is the input to the function and y is the output. x is known more formally as the function’s argument, and y as
its value. The set of possible input (x) values is the domain of the function. The set of possible output (y) values is the
function’s range.
In PowerPoint, the function is perhaps rarely mathematical; perhaps more commonly, the x and y values are correlated
observations, facts to be communicated graphically as a set. Still these terms borrowed from mathematics provide
convenient language for describing aspects of PowerPoint charts.
PowerPoint charts can be divided broadly into category types, which take a discrete argument, and XY (aka. scatter)
types which take a continuous argument. For category types, the argument is one of a discrete set of categories,
expressed as a label, such as “Blue”, “Red”, and “Green”. The argument for an XY type is a real number. In both
cases, the value of each data point is a real number.
The argument is commonly associated with the horizontal axis of the chart and the value with the vertical axis; these
would be the X and Y axis respectively on an XY chart. However the 2D orientation of the axes is reversed in some
char types (bar charts in particular) and takes other forms in chart types such as radar and doughnut. In the MS API,
the axis associated with the argument is known as the category axis and the other is the value axis. This terminology
is used across all chart types (including XY) as a matter of convention.
Series
A chart can have one or more series. A series is a set of ordered pairs that are related in some way and meant to be
distinguished graphically on the chart, often so they can be compared. For example, one series could represent Q1
financial results, depicted as a blue line, and a second series represent Q2 financial results with a red line.
In a standard chart, all series share the same domain (e.g. the same X axis). In a category chart, all series also share
the same set of categories. In an XY chart, the domain values are continuous; so in general, each data point in each
XY series will in have a distinct argument (x value).
In the MS API, there are multiple members on Series related to data points:
• Values
• XValues
• Points
Note that Categories is not in this set. CategoryCollection is a member of ChartGroup (named Plot in
python-pptx) in the MS API.
Values is the Excel range address at which the series values are stored. A set of constant values can be assigned in the
MS API but this is not supported in python-pptx.
XValues is the Excel range address at which the series arguments are stored when the chart is one of the XY types. X
values replace categories for an XY chart.
Points is a sequence of Point objects, each of which provides access to the formatting of the graphical representation
of the data point. Notably, it does not allow changing the category, x or y value, or size (for a bubble chart).
Every chart type supported by MS Office charts has the concept of data points.
Informally, a data point is an atomic element of the content depicted by the chart.
MS Office charts do not have a firm distinction for data points.
In all cases, points belong to a series.
There is some distinction between a data point for a category chart and one for an XY (scatter) chart.
The API
Functions
data_point_count = min(
xVal.ptCount_val, yVal.ptCount_val, bubbleSize.ptCount_val
)
@property
def pt_v(self, parent, idx):
pts = parent.xpath('.//c:pt[@val=%s]' % idx)
if pts is None:
return None
pt = pts[0]
(continues on next page)
• Visual alignment is not significant. A range may be anywhere in relation to the other data point ranges.
• Sequence is low row/col to high row/col in the Excel range, regardless of the “direction” in which the cells
are selected. This seems to be enforced by a validation “correction” of the range string in the UI ‘Select Data’
dialog.
• The number (count) of x, y, or size values is the number of cells in the range. This corresponds directly to
ptCount/@val for that data source sequence.
• The number of points in the series is the minimum of the x, y, and size value counts (ptCount).
• The ordered set of values for a point is formed by simple indexing within each value sequence. For example:
When any value sequence in the set runs out of elements, no further points are formed.
All values of each data source sequence are written to the XML; values are not truncated because they lack a
counter part in one of the other sequences. Consequently, the ptCount values will not necessarily match.
Experiment (IronPython):
• Create a chart with three X-values and four Y-values. .XValues has three and .Values has four members. How
many points are in Series.Points?
Observations:
• 4 X, 4 Y, 4 size – 4 points
• 3 X, 4 Y, 4 size – 3 points
• 4 X, 3 Y, 4 size – 3 points
• 4 X, 4 Y, 3 size – 3 points
Points with blank (y) values still count as a point. Points with blank (y) values still count as a point.
Explain how . . .
Hypothesis: An x, y, or size value index always starts at zero, at the beginning of the range, and increments to ptCount-
1.
Hypothesis: ptCount is always based on the number of cells in the Excel range, including blank cells at the start and
end.
ptCount and pt behavior on range including blank cell at end.
xVal//ptCount can be different than yVal//ptCount
<xsd:complexType name="CT_ScatterStyle">
<xsd:attribute name="val" type="ST_ScatterStyle" default="marker"/>
</xsd:complexType>
<xsd:complexType name="CT_AxDataSource">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="multiLvlStrRef" type="CT_MultiLvlStrRef"/>
<xsd:element name="numRef" type="CT_NumRef"/>
<xsd:element name="numLit" type="CT_NumData"/>
<xsd:element name="strRef" type="CT_StrRef"/>
<xsd:element name="strLit" type="CT_StrData"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_DPt">
<xsd:sequence>
<xsd:element name="idx" type="CT_UnsignedInt"/>
<xsd:element name="invertIfNegative" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="marker" type="CT_Marker" minOccurs="0"/>
<xsd:element name="bubble3D" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="explosion" type="CT_UnsignedInt" minOccurs="0"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0"/>
<xsd:element name="pictureOptions" type="CT_PictureOptions" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Marker">
<xsd:sequence>
<xsd:element name="symbol" type="CT_MarkerStyle" minOccurs="0"/>
<xsd:element name="size" type="CT_MarkerSize" minOccurs="0"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_MarkerStyle">
<xsd:attribute name="val" type="ST_MarkerStyle" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_MarkerSize">
<xsd:attribute name="val" type="ST_MarkerSize" default="5"/>
</xsd:complexType>
<xsd:complexType name="CT_NumData">
<xsd:sequence>
(continues on next page)
<xsd:complexType name="CT_NumDataSource">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="numRef" type="CT_NumRef"/>
<xsd:element name="numLit" type="CT_NumData"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_NumRef">
<xsd:sequence>
<xsd:element name="f" type="xsd:string"/>
<xsd:element name="numCache" type="CT_NumData" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name="ST_MarkerSize">
<xsd:restriction base="xsd:unsignedByte">
<xsd:minInclusive value="2"/>
<xsd:maxInclusive value="72"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_MarkerStyle">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="circle"/>
<xsd:enumeration value="dash"/>
<xsd:enumeration value="diamond"/>
<xsd:enumeration value="dot"/>
<xsd:enumeration value="none"/>
<xsd:enumeration value="picture"/>
<xsd:enumeration value="plus"/>
<xsd:enumeration value="square"/>
<xsd:enumeration value="star"/>
<xsd:enumeration value="triangle"/>
<xsd:enumeration value="x"/>
<xsd:enumeration value="auto"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ScatterStyle">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="none"/>
<xsd:enumeration value="line"/>
<xsd:enumeration value="lineMarker"/>
<xsd:enumeration value="marker"/>
<xsd:enumeration value="smooth"/>
<xsd:enumeration value="smoothMarker"/>
(continues on next page)
Radar Chart
PowerPoint UI
XML semantics
• There is one c:ser element for each series. Each c:ser element contains both the categories and the values (even
though that is often redundant).
• ? What happens if the category items in a radar chart don’t match? Inside are c:xVal, c:yVal, and c:bubbleSize,
each containing the set of points for that “series”.
XML specimen
MS API Protocol
<xsd:complexType name="CT_RadarChart">
<xsd:sequence>
<xsd:element name="radarStyle" type="CT_RadarStyle"/>
<xsd:element name="varyColors" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="ser" type="CT_RadarSer" minOccurs="0" maxOccurs=
˓→"unbounded"/>
<xsd:complexType name="CT_RadarStyle">
<xsd:attribute name="val" type="ST_RadarStyle" default="standard"/>
</xsd:complexType>
<xsd:complexType name="CT_SerTx">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="strRef" type="CT_StrRef"/>
<xsd:element name="v" type="s:ST_Xstring"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Marker">
<xsd:sequence>
<xsd:element name="symbol" type="CT_MarkerStyle" minOccurs="0"/>
<xsd:element name="size" type="CT_MarkerSize" minOccurs="0"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_DPt">
<xsd:sequence>
(continues on next page)
<xsd:simpleType name="ST_RadarStyle">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="standard"/>
<xsd:enumeration value="marker"/>
<xsd:enumeration value="filled"/>
</xsd:restriction>
</xsd:simpleType>
Bubble Chart
A bubble chart is an extension of an X-Y or scatter chart. Containing an extra (third) series, the size of the bubble is
proportional to the value in the third series.
The bubble is proportioned to its value by one of two methods selected by the client:
• Bubble width is proportional to value (linear)
• Bubble area is proportional to value (quadratic)
By default, the scale of the bubbles is determined by setting the largest bubble equal to a “default bubble size” equal
to roughly 25% of the height or width of the chart area, whichever is less. The default bubble size can be scaled using
a property setting to obtain proportionally larger or smaller bubbles.
PowerPoint UI
XML semantics
• I think this is going to get into blank cells if multiple series are required. Might be worth checking out how
using NA() possibly differs as to how it appears in the XML.
• There is a single c:ser element. Inside are c:xVal, c:yVal, and c:bubbleSize, each containing the set of points for
that “series”.
XML specimen
MS API Protocol
bubbleChart.chart.SetElement (msoElementPrimaryCategoryAxisTitleAdjacentToAxis)
bubbleChart.chart.Axes(xlCategory, xlPrimary).AxisTitle.Text = "=" & selection.
˓→Cells(1, 2).Address(External:=True)
bubbleChart.chart.SetElement (msoElementPrimaryValueAxisTitleRotated)
bubbleChart.chart.Axes(xlValue, xlPrimary).AxisTitle.Text = "=" & selection.Cells(1,
˓→3).Address(External:=True)
bubbleChart.chart.SetElement (msoElementPrimaryCategoryGridLinesMajor)
bubbleChart.chart.Axes(xlCategory).MinimumScale = 0
<xsd:complexType name="CT_AxDataSource">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="multiLvlStrRef" type="CT_MultiLvlStrRef"/>
<xsd:element name="numRef" type="CT_NumRef"/>
<xsd:element name="numLit" type="CT_NumData"/>
<xsd:element name="strRef" type="CT_StrRef"/>
<xsd:element name="strLit" type="CT_StrData"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_BubbleScale">
<xsd:attribute name="val" type="ST_BubbleScale" default="100%"/>
</xsd:complexType>
<xsd:complexType name="CT_NumData">
<xsd:sequence>
<xsd:element name="formatCode" type="s:ST_Xstring" minOccurs="0"/>
<xsd:element name="ptCount" type="CT_UnsignedInt" minOccurs="0"/>
<xsd:element name="pt" type="CT_NumVal" minOccurs="0" maxOccurs=
˓→"unbounded"/>
<xsd:complexType name="CT_NumDataSource">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="numRef" type="CT_NumRef"/>
<xsd:element name="numLit" type="CT_NumData"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_NumRef">
<xsd:sequence>
<xsd:element name="f" type="xsd:string"/>
<xsd:element name="numCache" type="CT_NumData" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_SizeRepresents">
<xsd:attribute name="val" type="ST_SizeRepresents" default="area"/>
</xsd:complexType>
<xsd:complexType name="CT_Trendline">
<xsd:sequence>
<xsd:element name="name" type="xsd:string" minOccurs="0"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0"/>
<xsd:element name="trendlineType" type="CT_TrendlineType"/>
<xsd:element name="order" type="CT_Order" minOccurs="0"/>
<xsd:element name="period" type="CT_Period" minOccurs="0"/>
(continues on next page)
<xsd:simpleType name="ST_BubbleScale">
<xsd:union memberTypes="ST_BubbleScalePercent ST_BubbleScaleUInt"/>
</xsd:simpleType>
<xsd:simpleType name="ST_BubbleScalePercent">
<xsd:restriction base="xsd:string">
<xsd:pattern value="0*(([0-9])|([1-9][0-9])|([1-2][0-9][0-9])|300)%"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_BubbleScaleUInt">
<xsd:restriction base="xsd:unsignedInt">
<xsd:minInclusive value="0"/>
<xsd:maxInclusive value="300"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_SizeRepresents">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="area"/>
<xsd:enumeration value="w"/>
</xsd:restriction>
</xsd:simpleType>
References
• https://blogs.msdn.microsoft.com/tomholl/2011/03/27/creating-multi-series-bubble-charts-in-excel/
• http://peltiertech.com/Excel/ChartsHowTo/HowToBubble.html
• http://peltiertech.com/Excel/Charts/ControlBubbleSizes.html
X-Y Chart
An X-Y chart, also known as a scatter chart, depending on the version of PowerPoint, is distinguished by having two
value axes rather than one category axis and one value axis.
XML specimen
<xsd:complexType name="CT_ScatterChart">
<xsd:sequence>
<xsd:element name="scatterStyle" type="CT_ScatterStyle"/>
<xsd:element name="varyColors" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="ser" type="CT_ScatterSer" minOccurs="0" maxOccurs=
˓→"unbounded"/>
<xsd:complexType name="CT_ScatterStyle">
<xsd:attribute name="val" type="ST_ScatterStyle" default="marker"/>
</xsd:complexType>
<xsd:complexType name="CT_AxDataSource">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="multiLvlStrRef" type="CT_MultiLvlStrRef"/>
<xsd:element name="numRef" type="CT_NumRef"/>
<xsd:element name="numLit" type="CT_NumData"/>
<xsd:element name="strRef" type="CT_StrRef"/>
<xsd:element name="strLit" type="CT_StrData"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Marker">
<xsd:sequence>
<xsd:element name="symbol" type="CT_MarkerStyle" minOccurs="0"/>
<xsd:element name="size" type="CT_MarkerSize" minOccurs="0"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_MarkerStyle">
<xsd:attribute name="val" type="ST_MarkerStyle" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_MarkerSize">
<xsd:attribute name="val" type="ST_MarkerSize" default="5"/>
</xsd:complexType>
<xsd:complexType name="CT_NumData">
<xsd:sequence>
<xsd:element name="formatCode" type="s:ST_Xstring" minOccurs="0"/>
<xsd:element name="ptCount" type="CT_UnsignedInt" minOccurs="0"/>
<xsd:element name="pt" type="CT_NumVal" minOccurs="0" maxOccurs=
˓→"unbounded"/>
<xsd:complexType name="CT_NumDataSource">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="numRef" type="CT_NumRef"/>
<xsd:element name="numLit" type="CT_NumData"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_NumRef">
<xsd:sequence>
<xsd:element name="f" type="xsd:string"/>
<xsd:element name="numCache" type="CT_NumData" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
(continues on next page)
<xsd:simpleType name="ST_MarkerSize">
<xsd:restriction base="xsd:unsignedByte">
<xsd:minInclusive value="2"/>
<xsd:maxInclusive value="72"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_MarkerStyle">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="circle"/>
<xsd:enumeration value="dash"/>
<xsd:enumeration value="diamond"/>
<xsd:enumeration value="dot"/>
<xsd:enumeration value="none"/>
<xsd:enumeration value="picture"/>
<xsd:enumeration value="plus"/>
<xsd:enumeration value="square"/>
<xsd:enumeration value="star"/>
<xsd:enumeration value="triangle"/>
<xsd:enumeration value="x"/>
<xsd:enumeration value="auto"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_ScatterStyle">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="none"/>
<xsd:enumeration value="line"/>
<xsd:enumeration value="lineMarker"/>
<xsd:enumeration value="marker"/>
<xsd:enumeration value="smooth"/>
<xsd:enumeration value="smoothMarker"/>
</xsd:restriction>
</xsd:simpleType>
Line Chart
XML Semantics
• c:lineChart/c:marker{val=0|1} doesn’t seem to have any effect one way or the other. Default line charts inserted
using PowerPoint always have it set to 1 (True). But even if it’s set to 0 or removed, markers still appear.
Hypothesis is that c:lineChart/c:ser/c:marker/c:symbol{val=none} and the like are the operative settings.
XML specimens
Minimal working XML for a line plot. Note this does not reference values in a spreadsheet.:
<c:chart>
<c:plotArea>
<c:lineChart>
<c:grouping val="standard"/>
<c:ser>
<c:idx val="0"/>
<c:order val="0"/>
<c:tx>
<c:v>Series 1</c:v>
</c:tx>
<c:marker>
<c:symbol val="none"/>
</c:marker>
<c:cat>
<c:strLit>
<c:ptCount val="2"/>
<c:pt idx="0">
<c:v>Category 1</c:v>
</c:pt>
<c:pt idx="1">
<c:v>Category 2</c:v>
</c:pt>
</c:strLit>
</c:cat>
<c:val>
<c:numLit>
<c:ptCount val="2"/>
<c:pt idx="0">
<c:v>4.3</c:v>
</c:pt>
<c:pt idx="1">
<c:v>2.5</c:v>
</c:pt>
</c:numLit>
</c:val>
<c:smooth val="0"/>
</c:ser>
<c:axId val="-2044963928"/>
<c:axId val="-2071826904"/>
</c:lineChart>
<c:catAx>
<c:axId val="-2044963928"/>
<c:scaling/>
<c:delete val="0"/>
<c:axPos val="b"/>
<c:crossAx val="-2071826904"/>
</c:catAx>
<c:valAx>
<c:axId val="-2071826904"/>
<c:scaling/>
<c:delete val="0"/>
<c:axPos val="l"/>
(continues on next page)
<xsd:complexType name="CT_Grouping">
<xsd:attribute name="val" type="ST_Grouping" default="standard"/>
</xsd:complexType>
<xsd:simpleType name="ST_Grouping">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="percentStacked"/>
<xsd:enumeration value="standard"/>
<xsd:enumeration value="stacked"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_Marker">
<xsd:sequence>
<xsd:element name="symbol" type="CT_MarkerStyle" minOccurs="0"/>
<xsd:element name="size" type="CT_MarkerSize" minOccurs="0"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
Pie Chart
XML specimens
Minimal working XML for a pie plot. Note this does not reference values in a spreadsheet.:
<xsd:complexType name="CT_PieSer">
<xsd:sequence>
<xsd:element name="idx" type="CT_UnsignedInt"/>
<xsd:element name="order" type="CT_UnsignedInt"/>
<xsd:element name="tx" type="CT_SerTx" minOccurs="0"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0"/>
<xsd:element name="explosion" type="CT_UnsignedInt" minOccurs="0"/>
<xsd:element name="dPt" type="CT_DPt" minOccurs="0" maxOccurs=
˓→"unbounded"/>
<xsd:complexType name="CT_SerTx">
(continues on next page)
<xsd:complexType name="CT_AxDataSource">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="multiLvlStrRef" type="CT_MultiLvlStrRef"/>
<xsd:element name="numRef" type="CT_NumRef"/>
<xsd:element name="numLit" type="CT_NumData"/>
<xsd:element name="strRef" type="CT_StrRef"/>
<xsd:element name="strLit" type="CT_StrData"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_NumDataSource">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="numRef" type="CT_NumRef"/>
<xsd:element name="numLit" type="CT_NumData"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_NumRef">
<xsd:sequence>
<xsd:element name="f" type="xsd:string"/>
<xsd:element name="numCache" type="CT_NumData" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_NumData">
<xsd:sequence>
<xsd:element name="formatCode" type="s:ST_Xstring" minOccurs="0"/>
<xsd:element name="ptCount" type="CT_UnsignedInt" minOccurs="0"/>
<xsd:element name="pt" type="CT_NumVal" minOccurs="0" maxOccurs=
˓→"unbounded"/>
<xsd:complexType name="CT_StrRef">
<xsd:sequence>
<xsd:element name="f" type="xsd:string"/>
<xsd:element name="strCache" type="CT_StrData" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_StrData">
<xsd:sequence>
(continues on next page)
<xsd:simpleType name="ST_Xstring">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
<xsd:complexType name="CT_NumVal">
<xsd:sequence>
<xsd:element name="v" type="s:ST_Xstring"/>
</xsd:sequence>
<xsd:attribute name="idx" type="xsd:unsignedInt" use="required"/>
<xsd:attribute name="formatCode" type="s:ST_Xstring"/>
</xsd:complexType>
Bar Chart
The bar chart is a fundamental plot type, used for both column and bar charts by specifying the bar direction. It is also
used for the clustered, stacked, and stacked 100% varieties by specifying grouping and overlap.
Gap Width
A gap appears between the bar or clustered bars for each category on a bar chart. The default width for this gap is
150% of the bar width. It can be set between 0 and 500% of the bar width. In the MS API this is set using the property
ChartGroup.GapWidth.
Proposed protocol:
Overlap
In a bar chart having two or more series, the bars for each category are clustered together for ready comparison. By
default, these bars are directly adjacent to each other, visually “touching”.
The bars can be made to overlap each other or have a space between them using the overlap property. Its values range
between -100 and 100, representing the percentage of the bar width by which to overlap adjacent bars. A setting of
-100 creates a gap of a full bar width and a setting of 100 causes all the bars in a category to be superimposed. The
default value is 0.
Proposed protocol:
XML specimens
Minimal working XML for a single-series column plot. Note this does not reference values in a spreadsheet.:
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<c:chartSpace xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart"
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/
˓→relationships">
<c:chart>
<c:plotArea>
<c:barChart>
<c:barDir val="col"/>
<c:grouping val="clustered"/>
<c:ser>
<c:idx val="0"/>
<c:order val="0"/>
<c:cat>
<c:strLit>
<c:ptCount val="1"/>
<c:pt idx="0">
<c:v>Foo</c:v>
</c:pt>
</c:strLit>
</c:cat>
<c:val>
<c:numLit>
<c:ptCount val="1"/>
<c:pt idx="0">
<c:v>4.3</c:v>
</c:pt>
</c:numLit>
</c:val>
</c:ser>
<c:dLbls>
<c:showLegendKey val="0"/>
<c:showVal val="0"/>
<c:showCatName val="0"/>
<c:showSerName val="0"/>
<c:showPercent val="0"/>
<c:showBubbleSize val="0"/>
</c:dLbls>
<c:gapWidth val="300"/>
<c:overlap val="-20"/>
<c:axId val="-2068027336"/>
<c:axId val="-2113994440"/>
(continues on next page)
<xsd:complexType name="CT_GapAmount">
<xsd:attribute name="val" type="ST_GapAmount" default="150%"/>
</xsd:complexType>
<xsd:simpleType name="ST_GapAmount">
<xsd:union memberTypes="ST_GapAmountPercent ST_GapAmountUShort"/>
</xsd:simpleType>
<xsd:simpleType name="ST_GapAmountPercent">
<xsd:restriction base="xsd:string">
<xsd:pattern value="0*(([0-9])|([1-9][0-9])|([1-4][0-9][0-9])|500)%"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_GapAmountUShort">
<xsd:restriction base="xsd:unsignedShort">
<xsd:minInclusive value="0"/>
<xsd:maxInclusive value="500"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_Overlap">
<xsd:attribute name="val" type="ST_Overlap" default="0%"/>
</xsd:complexType>
<xsd:simpleType name="ST_Overlap">
<xsd:union memberTypes="ST_OverlapPercent ST_OverlapByte"/>
</xsd:simpleType>
<xsd:simpleType name="ST_OverlapPercent">
<xsd:restriction base="xsd:string">
<xsd:pattern value="(-?0*(([0-9])|([1-9][0-9])|100))%"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_OverlapByte">
<xsd:restriction base="xsd:byte">
<xsd:minInclusive value="-100"/>
<xsd:maxInclusive value="100"/>
</xsd:restriction>
</xsd:simpleType>
Chart - Plots
Within the c:chartSpace/c:chart/c:plotArea element may occur 0..n xChart elements, each containing
0..n series.
xChart here is a placeholder name for the various plot elements, each of which ends with Chart:
• <c:barChart>
• <c:lineChart>
• <c:pieChart>
• <c:areaChart>
• etc. . . .
In the Microsoft API, the term chart group is used for the concept these elements represent. Rather than a group of
charts, their role is perhaps better described as a series group. The terminology is a bit vexed when it comes down to
details. The term plot was chosen for the purposes of this library.
The reason the concept of a plot is required is that more than one type of plotting may appear on a single chart. For
example, a line chart can appear on top of a column chart. To be more precise, one or more series can be plotted as
lines superimposed on one or more series plotted as columns.
The two sets of series both belong to a single chart, and there is only a single data source to define all the series in the
chart. The Excel workbook that provides the chart data uses only a single worksheet.
Individual series can be assigned a different chart type using the PowerPoint UI; this operation causes them to be placed
in a distinct xChart element of the corresponding type. During this operation, PowerPoint adds xChart elements in
an order that seems to correspond to logical viewing order, without respect to the sequence of the series chosen. It
appears area plots are placed in back, bar next, and line in front. This prevents plots of one type from obscuring the
others.
Note that not all combinations of chart types are possible. I’ve seen area overlaid with column overlaid with line. Bar
cannot be combined with line, which seems sensible because their axes locations differ (switched horizontal/vertical).
Feature Summary
Most plot-level properties are particular to a chart type. One so far is shared by plots of almost all chart types.
• Plot.vary_by_categories – Read/write boolean determining whether point markers for each category have a
different color. A point marker here means a bar for a bar chart, a pie section, etc. This setting is only operative
when the plot has a single series. A plot with multiple series uses varying colors to distinguish series rather than
categories.
Candidate protocol
Plot.vary_by_categories:
XML Semantics
• The value of c:xChart/c:varyColors defaults to True when the element is not present or when the
element is present but its val attribute is not.
<xsd:complexType name="CT_AreaChart">
<xsd:sequence>
<xsd:group ref="EG_AreaChartShared"/>
<xsd:element name="axId" type="CT_UnsignedInt" minOccurs="2" maxOccurs="2"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Area3DChart">
<xsd:sequence>
<xsd:group ref="EG_AreaChartShared"/>
<xsd:element name="gapDepth" type="CT_GapAmount" minOccurs="0"/>
<xsd:element name="axId" type="CT_UnsignedInt" minOccurs="2" maxOccurs="3"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:group name="EG_AreaChartShared">
<xsd:sequence>
<xsd:element name="grouping" type="CT_Grouping" minOccurs="0"/>
<xsd:element name="varyColors" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="ser" type="CT_AreaSer" minOccurs="0" maxOccurs=
˓→"unbounded"/>
<xsd:complexType name="CT_Grouping">
<xsd:attribute name="val" type="ST_Grouping" default="standard"/>
</xsd:complexType>
<xsd:simpleType name="ST_Grouping">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="percentStacked"/>
<xsd:enumeration value="standard"/>
<xsd:enumeration value="stacked"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_BarChart">
<xsd:sequence>
<xsd:group ref="EG_BarChartShared"/>
<xsd:element name="gapWidth" type="CT_GapAmount" minOccurs="0"/>
<xsd:element name="overlap" type="CT_Overlap" minOccurs="0"/>
<xsd:element name="serLines" type="CT_ChartLines" minOccurs="0" maxOccurs=
˓→"unbounded"/>
<xsd:complexType name="CT_Bar3DChart">
<xsd:sequence>
<xsd:group ref="EG_BarChartShared"/>
<xsd:element name="gapWidth" type="CT_GapAmount" minOccurs="0"/>
<xsd:element name="gapDepth" type="CT_GapAmount" minOccurs="0"/>
<xsd:element name="shape" type="CT_Shape" minOccurs="0"/>
<xsd:element name="axId" type="CT_UnsignedInt" minOccurs="2" maxOccurs="3"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:group name="EG_BarChartShared">
<xsd:sequence>
<xsd:element name="barDir" type="CT_BarDir"/>
<xsd:element name="grouping" type="CT_BarGrouping" minOccurs="0"/>
<xsd:element name="varyColors" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="ser" type="CT_BarSer" minOccurs="0" maxOccurs=
˓→"unbounded"/>
<xsd:complexType name="CT_BarDir">
<xsd:attribute name="val" type="ST_BarDir" default="col"/>
</xsd:complexType>
<xsd:simpleType name="ST_BarDir">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="bar"/>
<xsd:enumeration value="col"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_BarGrouping">
<xsd:attribute name="val" type="ST_BarGrouping" default="clustered"/>
</xsd:complexType>
<xsd:simpleType name="ST_BarGrouping">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="percentStacked"/>
<xsd:enumeration value="clustered"/>
<xsd:enumeration value="standard"/>
<xsd:enumeration value="stacked"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_Shape">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="cone"/>
<xsd:enumeration value="coneToMax"/>
<xsd:enumeration value="box"/>
<xsd:enumeration value="cylinder"/>
<xsd:enumeration value="pyramid"/>
<xsd:enumeration value="pyramidToMax"/>
(continues on next page)
<xsd:complexType name="CT_LineChart">
<xsd:sequence>
<xsd:group ref="EG_LineChartShared" minOccurs="1" maxOccurs="1"/>
<xsd:element name="hiLowLines" type="CT_ChartLines" minOccurs="0"/>
<xsd:element name="upDownBars" type="CT_UpDownBars" minOccurs="0"/>
<xsd:element name="marker" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="smooth" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="axId" type="CT_UnsignedInt" minOccurs="2" maxOccurs="2
˓→"/>
<xsd:group name="EG_LineChartShared">
<xsd:sequence>
<xsd:element name="grouping" type="CT_Grouping"/>
<xsd:element name="varyColors" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="ser" type="CT_LineSer" minOccurs="0" maxOccurs=
˓→"unbounded"/>
<xsd:complexType name="CT_PieChart">
<xsd:sequence>
<xsd:group ref="EG_PieChartShared"/>
<xsd:element name="firstSliceAng" type="CT_FirstSliceAng" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:group name="EG_PieChartShared">
<xsd:sequence>
<xsd:element name="varyColors" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="ser" type="CT_PieSer" minOccurs="0" maxOccurs=
˓→"unbounded"/>
<xsd:complexType name="CT_PieSer">
<xsd:sequence>
<xsd:group ref="EG_SerShared"/>
<xsd:element name="explosion" type="CT_UnsignedInt" minOccurs="0"/>
<xsd:element name="dPt" type="CT_DPt" minOccurs="0" maxOccurs=
˓→"unbounded"/>
<xsd:complexType name="CT_RadarChart">
<xsd:sequence>
<xsd:element name="radarStyle" type="CT_RadarStyle"/>
<xsd:element name="varyColors" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="ser" type="CT_RadarSer" minOccurs="0" maxOccurs=
˓→"unbounded"/>
<xsd:complexType name="CT_RadarStyle">
<xsd:attribute name="val" type="ST_RadarStyle" default="standard"/>
</xsd:complexType>
<xsd:simpleType name="ST_RadarStyle">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="standard"/>
<xsd:enumeration value="marker"/>
<xsd:enumeration value="filled"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_ScatterChart">
<xsd:sequence>
<xsd:element name="scatterStyle" type="CT_ScatterStyle"/>
<xsd:element name="varyColors" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="ser" type="CT_ScatterSer" minOccurs="0" maxOccurs=
˓→"unbounded"/>
<xsd:complexType name="CT_ScatterStyle">
<xsd:attribute name="val" type="ST_ScatterStyle" default="marker"/>
</xsd:complexType>
<xsd:simpleType name="ST_ScatterStyle">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="none"/>
<xsd:enumeration value="line"/>
<xsd:enumeration value="lineMarker"/>
<xsd:enumeration value="marker"/>
(continues on next page)
<xsd:complexType name="CT_StockChart">
<xsd:sequence>
<xsd:element name="ser" type="CT_LineSer" minOccurs="3" maxOccurs="4
˓→"/>
<xsd:complexType name="CT_SurfaceChart">
<xsd:sequence>
<xsd:group ref="EG_SurfaceChartShared"/>
<xsd:element name="axId" type="CT_UnsignedInt" minOccurs="2" maxOccurs="3"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Surface3DChart">
<xsd:sequence>
<xsd:group ref="EG_SurfaceChartShared"/>
<xsd:element name="axId" type="CT_UnsignedInt" minOccurs="3" maxOccurs="3"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:group name="EG_SurfaceChartShared">
<xsd:sequence>
<xsd:element name="wireframe" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="ser" type="CT_SurfaceSer" minOccurs="0" maxOccurs=
˓→"unbounded"/>
Chart - Legend
A chart may have a legend. The legend may be placed within the plot area or alongside it. The legend has a fill and
font and may be positioned on the top, right, bottom, left, in the upper-right corner, or in a custom position. Individual
legend entries may be custom specified, but that is not yet in scope.
Candidate protocol
>>> chart.has_legend
False
>>> chart.has_legend = True
>>> chart.has_legend
True
>>> legend = chart.legend
>>> legend
<pptx.chart.chart.Legend object at 0xdeadbeef1>
>>> legend.font
<pptx.text.Font object at 0xdeadbeef2>
>>> legend.horz_offset
0.0
>>> legend.horz_offset = 0.2
>>> legend.horz_offset
0.2
>>> legend.include_in_layout
True
>>> legend.include_in_layout = False
>>> legend.include_in_layout
False
>>> legend.position
XL_LEGEND_POSITION.RIGHT (-4152)
>>> legend.position = XL_LEGEND_POSITION.BOTTOM
>>> legend.position
XL_LEGEND_POSITION.BOTTOM (-4107)
Feature Summary
Enumerations
• XL_LEGEND_POSITION
Microsoft API
Legend.IncludeInLayout True if a legend will occupy the chart layout space when a chart layout is being determined.
The default is True. Read/write Boolean.
Legend.Position Returns or sets the position of the legend on the chart. Read/write XlLegendPosition.
XML specimens
<c:legend>
<c:legendPos val="t"/>
<c:layout>
<c:manualLayout>
<c:xMode val="edge"/>
<c:yMode val="edge"/>
<c:x val="0.321245570866142"/>
<c:y val="0.025"/>
<c:w val="0.532508858267717"/>
<c:h val="0.0854055118110236"/>
</c:manualLayout>
</c:layout>
<c:overlay val="1"/>
<c:spPr>
<a:solidFill>
<a:schemeClr val="accent6">
<a:lumMod val="20000"/>
<a:lumOff val="80000"/>
</a:schemeClr>
</a:solidFill>
</c:spPr>
<c:txPr>
<a:bodyPr/>
<a:lstStyle/>
<a:p>
<a:pPr>
<a:defRPr sz="1600" b="0" i="1" baseline="0"/>
</a:pPr>
<a:endParaRPr lang="en-US"/>
</a:p>
</c:txPr>
</c:legend>
<c:legend>
<c:legendPos val="r"/>
<c:layout>
<c:manualLayout>
<c:xMode val="factor"/>
<c:yMode val="factor"/>
<c:x val="0.42"/>
</c:manualLayout>
</c:layout>
<c:overlay val="0"/>
</c:legend>
<xsd:complexType name="CT_Legend">
<xsd:sequence>
<xsd:element name="legendPos" type="CT_LegendPos" minOccurs="0"/>
<xsd:element name="legendEntry" type="CT_LegendEntry" minOccurs="0"
˓→maxOccurs="unbounded"/>
<xsd:complexType name="CT_LegendPos">
<xsd:attribute name="val" type="ST_LegendPos" default="r"/>
</xsd:complexType>
<xsd:simpleType name="ST_LegendPos">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="b"/>
<xsd:enumeration value="tr"/>
<xsd:enumeration value="l"/>
<xsd:enumeration value="r"/>
<xsd:enumeration value="t"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_LegendEntry">
<xsd:sequence>
<xsd:element name="idx" type="CT_UnsignedInt"/>
<xsd:choice>
<xsd:element name="delete" type="CT_Boolean"/>
<xsd:group ref="EG_LegendEntryData"/>
</xsd:choice>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Layout">
<xsd:sequence>
<xsd:element name="manualLayout" type="CT_ManualLayout" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_LayoutTarget">
<xsd:attribute name="val" type="ST_LayoutTarget" default="outer"/>
</xsd:complexType>
<xsd:simpleType name="ST_LayoutTarget">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="inner"/>
<xsd:enumeration value="outer"/>
</xsd:restriction>
</xsd:simpleType>
(continues on next page)
<xsd:complexType name="CT_LayoutMode">
<xsd:attribute name="val" type="ST_LayoutMode" default="factor"/>
</xsd:complexType>
<xsd:simpleType name="ST_LayoutMode">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="edge"/>
<xsd:enumeration value="factor"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_ManualLayout">
<xsd:sequence>
<xsd:element name="layoutTarget" type="CT_LayoutTarget" minOccurs="0"/>
<xsd:element name="xMode" type="CT_LayoutMode" minOccurs="0"/>
<xsd:element name="yMode" type="CT_LayoutMode" minOccurs="0"/>
<xsd:element name="wMode" type="CT_LayoutMode" minOccurs="0"/>
<xsd:element name="hMode" type="CT_LayoutMode" minOccurs="0"/>
<xsd:element name="x" type="CT_Double" minOccurs="0"/>
<xsd:element name="y" type="CT_Double" minOccurs="0"/>
<xsd:element name="w" type="CT_Double" minOccurs="0"/>
<xsd:element name="h" type="CT_Double" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
SlideShapes.add_chart()
A chart is added to a slide similarly to adding any other shape. Note that a chart is not itself a shape; the item returned
by .add_shape() is a GraphicFrame shape which contains a Chart object. The actual chart object is accessed
using the chart attribute on the graphic frame that contains it.
Adding a chart requires three items, a chart type, the position and size desired, and a ChartData object specifying
the categories and series values for the new chart.
Protocol
Specimen XML
<p:graphicFrame>
<p:nvGraphicFramePr>
<p:cNvPr id="2" name="Chart 1"/>
<p:cNvGraphicFramePr/>
<p:nvPr>
<p:extLst>
<p:ext uri="{D42A27DB-BD31-4B8C-83A1-F6EECF244321}">
<p14:modId xmlns:p14="http://schemas.microsoft.com/office/powerpoint/2010/
˓→main"
val="11227583"/>
</p:ext>
</p:extLst>
</p:nvPr>
</p:nvGraphicFramePr>
<p:xfrm>
<a:off x="1524000" y="1397000"/>
<a:ext cx="6096000" cy="4064000"/>
</p:xfrm>
<a:graphic>
<a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/chart">
<c:chart xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/
˓→relationships"
r:id="rId2"/>
</a:graphicData>
</a:graphic>
</p:graphicFrame>
<xsd:complexType name="CT_GroupShape">
<xsd:sequence>
<xsd:element name="nvGrpSpPr" type="CT_GroupShapeNonVisual"/>
<xsd:element name="grpSpPr" type="a:CT_GroupShapeProperties"/>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="sp" type="CT_Shape"/>
<xsd:element name="grpSp" type="CT_GroupShape"/>
<xsd:element name="graphicFrame" type="CT_GraphicalObjectFrame"/>
<xsd:element name="cxnSp" type="CT_Connector"/>
<xsd:element name="pic" type="CT_Picture"/>
<xsd:element name="contentPart" type="CT_Rel"/>
</xsd:choice>
<xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_GraphicalObjectFrame">
<xsd:sequence>
<xsd:element name="nvGraphicFramePr" type="CT_GraphicalObjectFrameNonVisual"/>
<xsd:element name="xfrm" type="a:CT_Transform2D"/>
<xsd:element ref="a:graphic"/> <!-- type="CT_GraphicalObject" -->
<xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="bwMode" type="a:ST_BlackWhiteMode"/>
</xsd:complexType>
<xsd:complexType name="CT_GraphicalObjectFrameNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps"/>
<xsd:element name="cNvGraphicFramePr" type="a:CT_NonVisualGraphicFrameProperties"/
˓→>
<xsd:complexType name="CT_GraphicalObject">
<xsd:sequence>
<xsd:element name="graphicData" type="CT_GraphicalObjectData"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_GraphicalObjectData">
<xsd:sequence>
<xsd:any minOccurs="0" maxOccurs="unbounded" processContents="strict"/>
</xsd:sequence>
<xsd:attribute name="uri" type="xsd:token" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_NonVisualDrawingProps">
<xsd:sequence>
<xsd:element name="hlinkClick" type="CT_Hyperlink" minOccurs="0"/>
<xsd:element name="hlinkHover" type="CT_Hyperlink" minOccurs="0"/>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="id" type="ST_DrawingElementId" use="required"/>
<xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="descr" type="xsd:string" default=""/>
<xsd:attribute name="hidden" type="xsd:boolean" default="false"/>
<xsd:attribute name="title" type="xsd:string" default=""/>
</xsd:complexType>
<xsd:complexType name="CT_NonVisualGraphicFrameProperties">
<xsd:sequence>
<xsd:element name="graphicFrameLocks" type="CT_GraphicalObjectFrameLocking"
˓→minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_GraphicalObjectFrameLocking">
<xsd:sequence>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
(continues on next page)
<xsd:complexType name="CT_ApplicationNonVisualDrawingProps">
<xsd:sequence>
<xsd:element name="ph" type="CT_Placeholder" minOccurs="0"/>
<xsd:group ref="a:EG_Media" minOccurs="0"/>
<xsd:element name="custDataLst" type="CT_CustomerDataList" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="isPhoto" type="xsd:boolean" default="false"/>
<xsd:attribute name="userDrawn" type="xsd:boolean" default="false"/>
</xsd:complexType>
<xsd:group name="EG_Media">
<xsd:choice>
<xsd:element name="audioCd" type="CT_AudioCD"/>
<xsd:element name="wavAudioFile" type="CT_EmbeddedWAVAudioFile"/>
<xsd:element name="audioFile" type="CT_AudioFile"/>
<xsd:element name="videoFile" type="CT_VideoFile"/>
<xsd:element name="quickTimeFile" type="CT_QuickTimeFile"/>
</xsd:choice>
</xsd:group>
Chart Data
The data behind a chart–its category labels and its series names and values–turns out to be a pivotal object in both the
construction of a new chart and updating the data behind an existing chart.
The first role of ChartData is to act as a data transfer object, allowing the data for a chart to be accumulated over
multiple calls such as .add_series(). This avoids the need to assemble and send a complex nested structure of primitives
to method calls.
In addition to this, ChartData also takes on the role of broker to ChartXmlWriter and WorkbookWriter
which know how to assemble the <c:chartSpace> XML and Excel workbook for a chart, respectively. This is
sensible because neither of these objects can operate without a chart data instance to provide the data they need and
doing so concentrates the coupling to the latter two objects into one place.
Protocol
A ChartData object is constructed directly as needed, and used for either creating a new chart or for replacing the
data behind an existing one.
Creating a new chart:
>>> chart_data = ChartData()
>>> chart_data.categories = 'Foo', 'Bar'
>>> chart_data.add_series('Series 1', (1.2, 2.3))
(continues on next page)
>>> chart.replace_data(chart_data)
Note that the dimensions of the replacement data can differ from that of the existing chart.
The vertical and horizontal divisions of a chart axis may be labeled with tick labels, text that describes the division,
most commonly its category name or value. A tick labels object is not a collection. There is no object that represents
in individual tick label.
Tick label text for a category axis comes from the name of each category. The default tick label text for a category axis
is the number that indicates the position of the category relative to the low end of this axis. To change the number of
unlabeled tick marks between tick-mark labels, you must change the TickLabelSpacing property for the category axis.
Tick label text for the value axis is calculated based on the major_unit, minimum_scale, and maximum_scale properties
of the value axis. To change the tick label text for the value axis, you must change the values of these properties.
Candidate protocol
>>> tick_labels.font
<pptx.text.Font object at 0xdeadbeef1>
>>> tick_labels.number_format
'General'
>>> tick_labels.number_format = '0"%"'
>>> tick_labels.number_format
'0"%"'
>>> tick_labels.number_format_is_linked
True
>>> tick_labels.number_format_is_linked = False
>>> tick_labels.number_format_is_linked
False
Feature Summary
Microsoft API
XML specimens
<xsd:complexType name="CT_CatAx">
<xsd:sequence>
<xsd:group ref="EG_AxShared"/>
<xsd:element name="auto" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="lblAlgn" type="CT_LblAlgn" minOccurs="0"/>
<xsd:element name="lblOffset" type="CT_LblOffset" minOccurs="0"/>
<xsd:element name="tickLblSkip" type="CT_Skip" minOccurs="0"/>
<xsd:element name="tickMarkSkip" type="CT_Skip" minOccurs="0"/>
<xsd:element name="noMultiLvlLbl" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_ValAx">
<xsd:sequence>
<xsd:group ref="EG_AxShared"/>
<xsd:element name="crossBetween" type="CT_CrossBetween" minOccurs="0"/>
<xsd:element name="majorUnit" type="CT_AxisUnit" minOccurs="0"/>
<xsd:element name="minorUnit" type="CT_AxisUnit" minOccurs="0"/>
<xsd:element name="dispUnits" type="CT_DispUnits" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_DateAx">
<xsd:sequence>
<xsd:group ref="EG_AxShared"/>
<xsd:element name="auto" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="lblOffset" type="CT_LblOffset" minOccurs="0"/>
<xsd:element name="baseTimeUnit" type="CT_TimeUnit" minOccurs="0"/>
<xsd:element name="majorUnit" type="CT_AxisUnit" minOccurs="0"/>
<xsd:element name="majorTimeUnit" type="CT_TimeUnit" minOccurs="0"/>
<xsd:element name="minorUnit" type="CT_AxisUnit" minOccurs="0"/>
<xsd:element name="minorTimeUnit" type="CT_TimeUnit" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_SerAx">
<xsd:sequence>
<xsd:group ref="EG_AxShared"/>
<xsd:element name="tickLblSkip" type="CT_Skip" minOccurs="0"/>
<xsd:element name="tickMarkSkip" type="CT_Skip" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:group name="EG_AxShared">
<xsd:sequence>
(continues on next page)
<xsd:complexType name="CT_LblOffset">
<xsd:attribute name="val" type="ST_LblOffset" default="100%"/>
</xsd:complexType>
<xsd:simpleType name="ST_LblOffset">
<xsd:union memberTypes="ST_LblOffsetPercent ST_LblOffsetUShort"/>
</xsd:simpleType>
<xsd:simpleType name="ST_LblOffsetPercent">
<xsd:restriction base="xsd:string">
<xsd:pattern value="0*(([0-9])|([1-9][0-9])|([1-9][0-9][0-9])|1000)%"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_LblOffsetUShort">
<xsd:restriction base="xsd:unsignedShort">
<xsd:minInclusive value="0"/>
<xsd:maxInclusive value="1000"/>
</xsd:restriction>
</xsd:simpleType>
The values and categories of each plot is specified by a data set. In the typical case, that data is composed of a sequence
of categories and a sequence of series, where each series has a numeric value corresponding to each of the categories.
Candidate protocol
Feature Summary
Microsoft API
ChartGroup.CategoryCollection Returns all the visible categories in the chart group, or the specified visible cate-
gory.
ChartGroup.SeriesCollection Returns all the series in the chart group.
Series.Values Returns or sets a collection of all the values in the series. Read/write Variant. Returns an array of float;
accepts a spreadsheet formula or an array of numeric values.
Series.Formula Returns or sets the object’s formula in A1-style notation. Read/write String.
XML specimens
<c:ser>
<!-- ... -->
<c:cat>
<c:strRef>
<c:f>Sheet1!$A$2:$A$4</c:f>
<c:strCache>
<c:ptCount val="3"/>
<c:pt idx="0">
<c:v>Foo</c:v>
</c:pt>
<c:pt idx="1">
<c:v>Bar</c:v>
</c:pt>
<c:pt idx="2">
<c:v>Baz</c:v>
</c:pt>
</c:strCache>
</c:strRef>
</c:cat>
<c:val>
<c:numRef>
<c:f>Sheet1!$B$2:$B$4</c:f>
(continues on next page)
<xsd:complexType name="CT_AxDataSource">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="multiLvlStrRef" type="CT_MultiLvlStrRef"/>
<xsd:element name="numRef" type="CT_NumRef"/>
<xsd:element name="numLit" type="CT_NumData"/>
<xsd:element name="strRef" type="CT_StrRef"/>
<xsd:element name="strLit" type="CT_StrData"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_NumDataSource">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
(continues on next page)
<xsd:complexType name="CT_StrRef">
<xsd:sequence>
<xsd:element name="f" type="xsd:string"/>
<xsd:element name="strCache" type="CT_StrData" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_StrData">
<xsd:sequence>
<xsd:element name="ptCount" type="CT_UnsignedInt" minOccurs="0"/>
<xsd:element name="pt" type="CT_StrVal" minOccurs="0" maxOccurs=
˓→"unbounded"/>
<xsd:complexType name="CT_StrVal">
<xsd:sequence>
<xsd:element name="v" type="s:ST_Xstring"/>
</xsd:sequence>
<xsd:attribute name="idx" type="xsd:unsignedInt" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_NumRef">
<xsd:sequence>
<xsd:element name="f" type="xsd:string"/>
<xsd:element name="numCache" type="CT_NumData" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_NumData">
<xsd:sequence>
<xsd:element name="formatCode" type="s:ST_Xstring" minOccurs="0"/>
<xsd:element name="ptCount" type="CT_UnsignedInt" minOccurs="0"/>
<xsd:element name="pt" type="CT_NumVal" minOccurs="0" maxOccurs=
˓→"unbounded"/>
<xsd:complexType name="CT_NumVal">
<xsd:sequence>
<xsd:element name="v" type="s:ST_Xstring"/>
</xsd:sequence>
<xsd:attribute name="idx" type="xsd:unsignedInt" use="required"/>
<xsd:attribute name="formatCode" type="s:ST_Xstring"/>
</xsd:complexType>
<xsd:simpleType name="ST_Xstring">
(continues on next page)
Chart - ValueAxis.major/minor_unit
The value axis has major and minor divisions, corresponding to where tick marks, tick labels, and gridlines appear,
when present. How frequently these appear is determined by the major/minor units setting, specified as a floating point
number of units to skip between divisions. These settings may be specified explictly, or PowerPoint can determine a
sensible default based on the chart data. The latter setting is labeled ‘Auto’ in the UI. By default, major and minor unit
are both set to ‘Auto’ on new charts.
Candidate protocol
The properties ValueAxis.major_unit and ValueAxis.minor_unit are used to access and change this
setting.
None is used as an out-of-band value to signify Auto behavior. No separate boolean properties are required.
>>> value_axis = chart.value_axis
>>> value_axis.major_unit
None
>>> value_axis.major_unit = 10
>>> value_axis.major_unit
10.0
>>> value_axis.major_unit = -4.2
Traceback ...
ValueError: must be positive numeric value
>>> value_axis.major_unit = None
>>> value_axis.major_unit
None
Microsoft API
Axis.MajorUnit Returns or sets the major units for the value axis. Read/write Double.
Axis.MinorUnit Returns or sets the minor units on the value axis. Read/write Double.
Axis.MajorUnitIsAuto True if PowerPoint calculates the major units for the value axis. Read/write Boolean.
Axis.MinorUnitIsAuto True if PowerPoint calculates minor units for the value axis. Read/write Boolean.
PowerPoint behavior
Major and minor unit values are viewed and changed using the Scale pane of the Format Axis dialog. Checkboxes are
used to set a value to Auto. Changing the floating point value causes the Auto checkbox to turn off.
XML Semantics
• Only a value axis axis or date axis can have a <c:majorUnit> or a <c:minorUnit> element.
• Auto behavior is signified by having no element for that unit.
XML specimens
<c:valAx>
<c:axId val="-2101345848"/>
<c:scaling>
<c:orientation val="minMax"/>
</c:scaling>
<c:delete val="0"/>
<c:axPos val="l"/>
<c:majorGridlines/>
<c:numFmt formatCode="General" sourceLinked="1"/>
<c:majorTickMark val="out"/>
<c:minorTickMark val="none"/>
<c:tickLblPos val="nextTo"/>
<c:crossAx val="-2030568888"/>
<c:crosses val="autoZero"/>
<c:crossBetween val="between"/>
<c:majorUnit val="20.0"/>
</c:valAx>
<xsd:complexType name="CT_ValAx">
<xsd:sequence>
<xsd:group ref="EG_AxShared" minOccurs="1" maxOccurs="1"/>
<xsd:element name="crossBetween" type="CT_CrossBetween" minOccurs="0"/>
<xsd:element name="majorUnit" type="CT_AxisUnit" minOccurs="0"/>
<xsd:element name="minorUnit" type="CT_AxisUnit" minOccurs="0"/>
<xsd:element name="dispUnits" type="CT_DispUnits" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_DateAx">
<xsd:sequence>
<xsd:group ref="EG_AxShared"/>
<xsd:element name="auto" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="lblOffset" type="CT_LblOffset" minOccurs="0"/>
<xsd:element name="baseTimeUnit" type="CT_TimeUnit" minOccurs="0"/>
<xsd:element name="majorUnit" type="CT_AxisUnit" minOccurs="0"/>
<xsd:element name="majorTimeUnit" type="CT_TimeUnit" minOccurs="0"/>
<xsd:element name="minorUnit" type="CT_AxisUnit" minOccurs="0"/>
<xsd:element name="minorTimeUnit" type="CT_TimeUnit" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:group name="EG_AxShared">
<xsd:sequence>
<xsd:element name="axId" type="CT_UnsignedInt"/>
<xsd:element name="scaling" type="CT_Scaling"/>
<xsd:element name="delete" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="axPos" type="CT_AxPos"/>
(continues on next page)
<xsd:complexType name="CT_AxisUnit">
<xsd:attribute name="val" type="ST_AxisUnit" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_AxisUnit">
<xsd:restriction base="xsd:double">
<xsd:minExclusive value="0"/>
</xsd:restriction>
</xsd:simpleType>
c:areaChart
c:area3DChart
c:barChart
• ./c:barDir{val=bar}
– ./c:grouping{val=clustered} => BAR_CLUSTERED
– ./c:grouping{val=stacked} => BAR_STACKED
– ./c:grouping{val=percentStacked} => BAR_STACKED_100
• ./c:barDir{val=col}
– ./c:grouping{val=clustered} => COLUMN_CLUSTERED
– ./c:grouping{val=stacked} => COLUMN_STACKED
– ./c:grouping{val=percentStacked} => COLUMN_STACKED_100
c:bar3DChart
• ./c:barDir{val=bar}
– ./c:grouping{val=clustered}
c:bubbleChart
c:doughnutChart
• . => DOUGHNUT
• ./c:ser/c:explosion{val>0} => DOUGHNUT_EXPLODED
c:lineChart
• ./c:grouping{val=standard}
– ./c:ser/c:marker/c:symbol{val=none} => LINE
– ./c:marker{val=1} => LINE_MARKERS
• ./c:grouping{val=stacked}
– ./c:marker{val=1} => LINE_MARKERS_STACKED
– ./c:ser/c:marker/c:symbol{val=none} => LINE_STACKED
• ./c:grouping{val=percentStacked}
– ./c:marker{val=1} => LINE_MARKERS_STACKED_100
– ./c:ser/c:marker/c:symbol{val=none} => LINE_STACKED_100
c:line3DChart
• . => THREE_D_LINE
c:ofPieChart
c:pieChart
• . => PIE
• ./c:ser/c:explosion{val>0} => PIE_EXPLODED
c:pie3DChart
• . => THREE_D_PIE
• ./c:ser/c:explosion{val>0} => THREE_D_PIE_EXPLODED
c:radarChart
c:scatterChart
c:stockChart
c:surface3DChart
c:surfaceChart
XML specimens
<c:barChart>
<c:barDir val="col"/>
<c:grouping val="clustered"/>
<c:ser>
<c:idx val="0"/>
<c:order val="0"/>
<c:cat>...</c:cat>
<c:val>...</c:val>
</c:ser>
<c:axId val="-2068027336"/>
<c:axId val="-2113994440"/>
</c:barChart>
<xsd:complexType name="CT_BubbleChart">
<xsd:sequence>
<xsd:element name="varyColors" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="ser" type="CT_BubbleSer" minOccurs="0"
˓→maxOccurs="unbounded"/>
<xsd:complexType name="CT_RadarChart">
<xsd:sequence>
<xsd:element name="radarStyle" type="CT_RadarStyle"/>
<xsd:element name="varyColors" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="ser" type="CT_RadarSer" minOccurs="0" maxOccurs=
˓→"unbounded"/>
<xsd:complexType name="CT_ScatterChart">
<xsd:sequence>
<xsd:element name="scatterStyle" type="CT_ScatterStyle"/>
<xsd:element name="varyColors" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="ser" type="CT_ScatterSer" minOccurs="0" maxOccurs=
˓→"unbounded"/>
<xsd:complexType name="CT_StockChart">
(continues on next page)
<xsd:complexType name="CT_SurfaceChart">
<xsd:sequence>
<xsd:element name="wireframe" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="ser" type="CT_SurfaceSer" minOccurs="0" maxOccurs=
˓→"unbounded"/>
<xsd:complexType name="CT_Surface3DChart">
<xsd:sequence>
<xsd:element name="wireframe" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="ser" type="CT_SurfaceSer" minOccurs="0" maxOccurs=
˓→"unbounded"/>
Chart - InvertIfNegative
Can be set on a bar series or on a data point. It’s not clear what its meaning is on a non-bar data point. c:barSer/
c:invertIfNegative is the target element. Also valid on a bubble series.
Protocol
Semantics
PowerPoint® behavior
In my tests, the <c:invertIfNegative> element is always present in a new bar chart and always explicitly
initialized to False.
XML specimens
<xsd:complexType name="CT_BarSer">
<xsd:sequence>
<xsd:group ref="EG_SerShared"/>
<xsd:element name="invertIfNegative" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="pictureOptions" type="CT_PictureOptions" minOccurs="0"/>
<xsd:element name="dPt" type="CT_DPt" minOccurs="0"
˓→maxOccurs="unbounded"/>
<xsd:complexType name="CT_BubbleSer">
<xsd:sequence>
<xsd:group ref="EG_SerShared"/>
<xsd:element name="invertIfNegative" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="dPt" type="CT_DPt" minOccurs="0"
˓→maxOccurs="unbounded"/>
Chart - BaseAxis.has_gridlines
A chart axis can have gridlines that extend the axis tick marks across the body of the plot area. Gridlines for major
and minor tick marks can be controlled separately. Both vertical and horizontal axes can have gridlines.
Candidate protocol
Microsoft API
PowerPoint behavior
• Turning gridlines on and off is controlled from the ribbon (on the Mac at least)
• Each set of gridlines (horz/vert, major/minor) can be formatted individually.
• The formatting dialog has panes for Line, Shadow, and Glow & Soft Edges
XML Semantics
XML specimens
<c:catAx>
<c:axId val="-2097691448"/>
<c:scaling>
<c:orientation val="minMax"/>
</c:scaling>
<c:delete val="0"/>
<c:axPos val="b"/>
<c:majorGridlines/>
<c:minorGridlines/>
(continues on next page)
<xsd:complexType name="CT_DateAx">
<xsd:sequence>
<xsd:group ref="EG_AxShared"/>
<xsd:element name="auto" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="lblOffset" type="CT_LblOffset" minOccurs="0"/>
<xsd:element name="baseTimeUnit" type="CT_TimeUnit" minOccurs="0"/>
<xsd:element name="majorUnit" type="CT_AxisUnit" minOccurs="0"/>
<xsd:element name="majorTimeUnit" type="CT_TimeUnit" minOccurs="0"/>
<xsd:element name="minorUnit" type="CT_AxisUnit" minOccurs="0"/>
<xsd:element name="minorTimeUnit" type="CT_TimeUnit" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_SerAx">
<xsd:sequence>
<xsd:group ref="EG_AxShared"/>
<xsd:element name="tickLblSkip" type="CT_Skip" minOccurs="0"/>
<xsd:element name="tickMarkSkip" type="CT_Skip" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:group name="EG_AxShared">
<xsd:sequence>
<xsd:element name="axId" type="CT_UnsignedInt"/>
<xsd:element name="scaling" type="CT_Scaling"/>
<xsd:element name="delete" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="axPos" type="CT_AxPos"/>
(continues on next page)
<xsd:complexType name="CT_ChartLines">
<xsd:sequence>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
Chart - Series
A series in a sequence of points that correspond to the categories of a plot. A chart may have more than one series,
which gives rise, for example, to a clustered column chart or a line chart with multiple lines plotted.
A series belongs to a plot. When a chart has multiple plots, such as a bar chart with a superimposed line plot, each of
the series in the chart belong to one plot or the other.
Although the Microsoft API has a method on Chart to access all the series in a chart, it also has the same method for
accessing the series of a plot (ChartGroup in MS API).
There are eight distinct series types, corresponding to major chart types. They all share a common base of attributes
and others appear on one or more of the types.
Series Access
Series are perhaps most naturally accessed from a plot, to which they belong:
>>> plot.series
<pptx.chart.series.SeriesCollection instance at x11091e750>
However, there is also a property on Chart which allows access to all the series in the chart:
>>> chart.series
<pptx.chart.series.SeriesCollection instance at x11091f970>
Each series in a chart has an explicit sequence indicator, the value of its required c:order child element. The series for
a plot appear in order of this value. The series for a chart appear in plot order, then their order within that plot, such
that all series for the first plot appear before those in the next plot, and so on.
Properties
Series.format
All series have an optional c:spPr element that control the drawing shape properties of the series such as fill and line,
including transparency and shadow.
Series.points
Perhaps counterintuitively, a Point object does not provide access to all the attributes one might think. It only provides
access to attributes of the visual representation of the point in that chart, such as the color, datum label, or marker. It
does not provide access to the data point values, such as the Y value or the bubble size.
Surface charts do not have a distinct data point representation (rather just an inflection in the surface. So series of
surface charts will not have the .points member. Since surface charts are not yet implemented, this will come into play
sometime later.
Note that bubble and XY have a different way of organizing their data points so have a distinct implementation from
that of category charts.
Implementation notes:
• Introduce _BaseCategorySeries and subclass all category series types from it. Add tests to test inheritance. No
acceptance test since this is internals-only.
• It’s possible the only requirement is to create CategoryPoints. The rest of the implementation might work all on
its own. Better spike it and see.
Protocol
XML specimens
<c:ser>
<c:idx val="0"/>
<c:order val="0"/>
(continues on next page)
<xsd:complexType name="CT_DPt">
<xsd:sequence>
<xsd:element name="idx" type="CT_UnsignedInt"/>
<xsd:element name="invertIfNegative" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="marker" type="CT_Marker" minOccurs="0"/>
<xsd:element name="bubble3D" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="explosion" type="CT_UnsignedInt" minOccurs="0"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0"/>
<xsd:element name="pictureOptions" type="CT_PictureOptions" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
Spike approach
• [ ] driver with one blank slide, builder column chart single series.
• [ ] Can edit Excel data in resulting file
• [ ] resulting file has an embedded Excel package of expected name
• [ ] XML uses worksheet references, not just cached data
Proposed protocol
MS API Protocol
ChartData objects
BreakLink Removes the link between the data for a chart and a Microsoft Excel workbook.
IsLinked True if the data for the chart is linked to an external Microsoft Excel workbook. Read-only Boolean.
Workbook Returns the workbook that contains the chart data associated with the chart. Read-only Object.
XML specimens
<mc:Choice xmlns:c14="http://schemas.microsoft.com/office/drawing/2007/8/2/chart"
Requires="c14">
<c14:style val="102"/>
</mc:Choice>
<mc:Fallback>
<c:style val="2"/>
</mc:Fallback>
</mc:AlternateContent>
<c:chart>
<!-- 179 rows elided -->
</c:chart>
<c:txPr>
<a:bodyPr/>
<a:lstStyle/>
<a:p>
<a:pPr>
<a:defRPr sz="1800"/>
</a:pPr>
(continues on next page)
<xsd:complexType name="CT_ChartSpace">
<xsd:sequence>
<xsd:element name="date1904" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="lang" type="CT_TextLanguageID" minOccurs="0"/>
<xsd:element name="roundedCorners" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="style" type="CT_Style" minOccurs="0"/>
<xsd:element name="clrMapOvr" type="a:CT_ColorMapping" minOccurs="0"/>
<xsd:element name="pivotSource" type="CT_PivotSource" minOccurs="0"/>
<xsd:element name="protection" type="CT_Protection" minOccurs="0"/>
<xsd:element name="chart" type="CT_Chart"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0"/>
<xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0"/>
<xsd:element name="externalData" type="CT_ExternalData" minOccurs="0"/>
<xsd:element name="printSettings" type="CT_PrintSettings" minOccurs="0"/>
<xsd:element name="userShapes" type="CT_RelId" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_ExternalData">
<xsd:sequence>
<xsd:element name="autoUpdate" type="CT_Boolean" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute ref="r:id" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_Boolean">
<xsd:attribute name="val" type="xsd:boolean" default="true"/>
</xsd:complexType>
Chart Axes
PowerPoint chart axes come in four varieties: category axis, value axis, date axis, and series axis. A series axis only
appears on a 3D chart and is also known as its depth axis.
A chart may have two category axes and/or two value axes. The second axis, if there is one, is known as the secondary
category axis or secondary value axis.
A category axis may appear as either the horizontal or vertical axis, depending upon the chart type. Likewise for a
value axis.
PowerPoint behavior
Reverse-order
Normally, categories appear left-to-right in the order specified and values appear vertically in increasing order. This
default ordering can be reversed when desired.
One common case is for the categories in a “horizontal” bar-chart (as opposed to the “vertical” column-chart). Because
the value axis appears at the bottom, categories appear from bottom-to-top on the categories axis. For many readers
this is odd, perhaps because we read top-to-bottom.
The axis “direction” can be switched using the Axis.reverse_order property. This controls the value of the
c:xAx/c:scaling/c:orientation{val=minMax|maxMin} XML element/attribute. The default is False.
MS API protocol:
>>> axis.tick_label_position
XL_TICK_LABEL_POSITION.NEXT_TO_AXIS
>>> axis.tick_label_position = XL_TICK_LABEL_POSITION.LOW
>>> axis.tick_label_position
XL_TICK_LABEL_POSITION.LOW
MS API protocol:
>>> axis.TickLabelPosition
xlTickLabelPositionNextToAxis
>>> axis.TickLabelPosition = xlTickLabelPositionLow
c:catAx/c:tickLblPos{val=nextTo}
TickLabels.number_format
Tick-mark label text for the category axis comes from the name of the associated category in the chart. The default
tick-mark label text for the category axis is the number that indicates the position of the category relative to the left
end of this axis. To change the number of unlabeled tick marks between tick-mark labels, you must change the
TickLabelSpacing property for the category axis.
Tick-mark label text for the value axis is calculated based on the MajorUnit, MinimumScale, and MaximumScale
properties of the value axis. To change the tick-mark label text for the value axis, you must change the values of these
properties.
MS API protocol:
When sourceLinked attribute is True, UI shows “General” number format category regardless of contents of
formatCode attribute.
The sourceLinked attribute defaults to True when the <c:numFmt> element is present but that attribute is omit-
ted.
When the <c:numFmt> element is not present, the behavior is as though the element <c:numFmt
formatCode="General" sourceLinked="0"/> was present.
The default PowerPoint chart contains this numFmt element:
_BaseAxis.visible property
XML specimens
<c:catAx>
<c:axId val="-2097691448"/>
<c:scaling>
<c:orientation val="minMax"/>
</c:scaling>
<c:delete val="0"/>
<c:axPos val="b"/>
<c:numFmt formatCode="General" sourceLinked="0"/>
<c:majorTickMark val="out"/>
<c:minorTickMark val="none"/>
<c:tickLblPos val="nextTo"/>
<c:txPr>
<a:bodyPr/>
<a:lstStyle/>
<a:p>
<a:pPr>
<a:defRPr sz="1000"/>
</a:pPr>
<a:endParaRPr lang="en-US"/>
</a:p>
</c:txPr>
<c:crossAx val="-2097683336"/>
<c:crosses val="autoZero"/>
<c:auto val="1"/>
<c:lblAlgn val="ctr"/>
<c:lblOffset val="100"/>
<c:noMultiLvlLbl val="0"/>
</c:catAx>
<xsd:complexType name="CT_PlotArea">
<xsd:sequence>
<!-- 17 others -->
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="valAx" type="CT_ValAx"/>
<xsd:element name="catAx" type="CT_CatAx"/>
<xsd:element name="dateAx" type="CT_DateAx"/>
<xsd:element name="serAx" type="CT_SerAx"/>
</xsd:choice>
<xsd:element name="dTable" type="CT_DTable" minOccurs="0"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_DateAx">
<xsd:sequence>
<xsd:group ref="EG_AxShared"/>
<xsd:element name="auto" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="lblOffset" type="CT_LblOffset" minOccurs="0"/>
<xsd:element name="baseTimeUnit" type="CT_TimeUnit" minOccurs="0"/>
<xsd:element name="majorUnit" type="CT_AxisUnit" minOccurs="0"/>
<xsd:element name="majorTimeUnit" type="CT_TimeUnit" minOccurs="0"/>
(continues on next page)
<xsd:complexType name="CT_SerAx">
<xsd:sequence>
<xsd:group ref="EG_AxShared"/>
<xsd:element name="tickLblSkip" type="CT_Skip" minOccurs="0"/>
<xsd:element name="tickMarkSkip" type="CT_Skip" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:group name="EG_AxShared">
<xsd:sequence>
<xsd:element name="axId" type="CT_UnsignedInt"/>
<xsd:element name="scaling" type="CT_Scaling"/>
<xsd:element name="delete" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="axPos" type="CT_AxPos"/>
<xsd:element name="majorGridlines" type="CT_ChartLines" minOccurs="0"/>
<xsd:element name="minorGridlines" type="CT_ChartLines" minOccurs="0"/>
<xsd:element name="title" type="CT_Title" minOccurs="0"/>
<xsd:element name="numFmt" type="CT_NumFmt" minOccurs="0"/>
<xsd:element name="majorTickMark" type="CT_TickMark" minOccurs="0"/>
<xsd:element name="minorTickMark" type="CT_TickMark" minOccurs="0"/>
<xsd:element name="tickLblPos" type="CT_TickLblPos" minOccurs="0"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0"/>
<xsd:element name="txPr" type="a:CT_TextBody" minOccurs="0"/>
<xsd:element name="crossAx" type="CT_UnsignedInt"/>
<xsd:choice minOccurs="0" maxOccurs="1">
<xsd:element name="crosses" type="CT_Crosses"/>
<xsd:element name="crossesAt" type="CT_Double"/>
</xsd:choice>
</xsd:sequence>
</xsd:group>
<xsd:complexType name="CT_ChartLines">
<xsd:sequence>
<xsd:element name="spPr" type="a:CT_ShapeProperties" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Crosses">
<xsd:attribute name="val" type="ST_Crosses" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_Scaling">
<xsd:sequence>
<xsd:element name="logBase" type="CT_LogBase" minOccurs="0"/>
<xsd:element name="orientation" type="CT_Orientation" minOccurs="0"/>
<xsd:element name="max" type="CT_Double" minOccurs="0"/>
<xsd:element name="min" type="CT_Double" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
(continues on next page)
<xsd:complexType name="CT_NumFmt">
<xsd:attribute name="formatCode" type="xsd:string" use="required"/>
<xsd:attribute name="sourceLinked" type="xsd:boolean"/>
</xsd:complexType>
<xsd:complexType name="CT_Orientation">
<xsd:attribute name="val" type="ST_Orientation" default="minMax"/>
</xsd:complexType>
<xsd:complexType name="CT_TickLblPos">
<xsd:attribute name="val" type="ST_TickLblPos" default="nextTo"/>
</xsd:complexType>
<xsd:complexType name="CT_TickMark">
<xsd:attribute name="val" type="ST_TickMark" default="cross"/>
</xsd:complexType>
<xsd:complexType name="CT_Boolean">
<xsd:attribute name="val" type="xsd:boolean" default="true"/>
</xsd:complexType>
<xsd:complexType name="CT_Double">
<xsd:attribute name="val" type="xsd:double" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_Crosses">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="autoZero"/>
<xsd:enumeration value="max"/>
<xsd:enumeration value="min"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_Orientation">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="maxMin"/>
<xsd:enumeration value="minMax"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_TickLblPos">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="high"/>
<xsd:enumeration value="low"/>
<xsd:enumeration value="nextTo"/>
<xsd:enumeration value="none"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_TickMark">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="cross"/>
<xsd:enumeration value="in"/>
<xsd:enumeration value="none"/>
<xsd:enumeration value="out"/>
</xsd:restriction>
(continues on next page)
Chart Shape
A chart is not actually a shape. It is a graphical object held inside a graphics frame. The graphics frame is a shape and
the chart must be retrieved from it.
Protocol
Acceptance tests
Table
Cell Merge
PowerPoint allows a user to merge table cells, causing multiple grid cells to appear and behave as a single cell.
Terminology
The following distinctions are important to the implementation and also to using the API.
table grid A PowerPoint (DrawingML) table has an underlying grid which is a strict two-dimensional (n X m) array;
each row in the table grid has m cells and each column has n cells. Grid cell boundaries are aligned both
vertically and horizontally.
grid cell Each of the n x m cells in a table is a grid cell. Every grid cell is addressable, even those “shadowed” by a
merge-origin cell.
Apparent cell boundaries can be modified by merging two or more grid cells.
merge-origin cell The top-left grid cell in a merged cell. This cell will be visible, have the combined extent of all
spanned cells, and contain any visible content.
spanned cell All grid cells in a merged cell are spanned cells, excepting the one at the top-left (the merge-origin cell).
Intuitively, the merge-origin cell “spans” all the other grid cells in the merge range.
Content in a spanned cell is not visible, and is typically moved to the merge-origin cell as part of the merge
operation, leaving each spanned cell with exactly one empty paragraph. This content becomes visible again if
the merged cell is split.
unmerged cell While not a distinction directly embodied in the code, any cell which is not a merge-origin cell and is
also not a spanned cell is a “regular” cell and not part of a merged cell.
Protocol
A cell is accessed by grid location (regardless of any merged regions). All grid cells are addressable, even those
“shadowed” by a merge (such a shadowed cell is a spanned cell):
A “regular” cell not participating in a merge is neither the merge origin nor spanned:
>>> cell = table.cell(0, 2)
>>> cell
<pptx.table._Cell object at 0x...>
>>> cell.is_merge_origin
False
>>> cell.is_spanned
False
Use Cases
def merged_cell_report(cell):
"""Return str summarizing position and size of merged *cell*."""
return (
(continues on next page)
Use Case: Access only cells that display text (are not spanned):
def iter_visible_cells(table):
return (cell for cell in table.iter_cells() if not cell.is_spanned)
def has_merged_cells(table):
for cell in table.iter_cells():
if cell.is_merge_origin:
return True
PowerPoint behaviors
• Two or more cells are merged by selecting them using the mouse, then selecting “Merge cells” from the context
menu.
• Content from spanned cells is moved to the merge origin cell.
• A merged cell can be split (“unmerged” roughly). The UI allows the merge to be split into an arbitrary number
of rows and columns and adjusts the table grid and row heights etc. to accommodate, adding (potentially very
many) new merged cells as required.
python-pptx just removes the merge, restoring the underlying table grid cells to regular (unmerged) cells.
Specimen XML
<a:tr>
<a:tc gridSpan="3"/>
<a:tc hMerge="true"/> <!-- PowerPoint uses boolean value "1" -->
<a:tc hMerge="true"/>
</a:tr>
<a:tr>
<a:tc rowSpan="3"/>
</a:tr>
<a:tr>
<a:tc vMerge="true"/> <!-- PowerPoint uses boolean value "1" -->
</a:tr>
<a:tr>
<a:tc vMerge="true"/>
</a:tr>
Super-simplified 2D merge:
<a:tr>
<a:tc rowSpan="3" gridSpan="3"/>
<a:tc rowSpan="3" hMerge="true"/>
<a:tc rowSpan="3" hMerge="true"/>
</a:tr>
<a:tr>
<a:tc gridSpan="3" vMerge="true"/>
<a:tc hMerge="true" vMerge="true"/>
<a:tc hMerge="true" vMerge="true"/>
</a:tr>
<a:tr>
<a:tc gridSpan="3" vMerge="true"/>
<a:tc hMerge="true" vMerge="true"/>
<a:tc hMerge="true" vMerge="true"/>
</a:tr>
<a:tbl>
<a:tblGrid>
<a:gridCol w="2032000"/>
<a:gridCol w="2032000"/>
<a:gridCol w="2032000"/>
</a:tblGrid>
<a:tr h="370840">
<a:tc gridSpan="2">
<a:txBody>...</a:txBody>
<a:tcPr/>
</a:tc>
<a:tc hMerge="1">
<a:txBody>...</a:txBody>
<a:tcPr/>
</a:tc>
<a:tc>
<a:txBody>...</a:txBody>
<a:tcPr/>
</a:tc>
</a:tr>
<a:tr h="370840">
<a:tc>...</a:tc>
<a:tc>...</a:tc>
<a:tc>...</a:tc>
</a:tr>
</a:tbl>
<a:tbl>
<a:tr h="370840">
<a:tc rowSpan="2">
<a:txBody>
<a:bodyPr/>
<a:lstStyle/>
<a:p>
<a:r>
<a:rPr lang="en-US" dirty="0" smtClean="0"/>
(continues on next page)
Schema excerpt
<xsd:complexType name="CT_TableCell">
<xsd:sequence>
<xsd:element name="txBody" type="CT_TextBody" minOccurs="0"/>
<xsd:element name="tcPr" type="CT_TableCellProperties" minOccurs="0"/>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="rowSpan" type="xsd:int" default="1"/>
<xsd:attribute name="gridSpan" type="xsd:int" default="1"/>
<xsd:attribute name="hMerge" type="xsd:boolean" default="false"/>
<xsd:attribute name="vMerge" type="xsd:boolean" default="false"/>
<xsd:attribute name="id" type="xsd:string"/>
</xsd:complexType>
Table
One of the shapes available for placing on a PowerPoint slide is the table. As shapes go, it is one of the more complex.
In addition to having standard shape properties such as position and size, it contains what amount to sub-shapes that
each have properties of their own. Prominent among these sub-element types are row, column, and cell.
Table Properties
first_row read/write boolean property which, when true, indicates the first row should be formatted differently, as
for a heading row at the top of the table.
first_col read/write boolean property which, when true, indicates the first column should be formatted differently,
as for a side-heading column at the far left of the table.
last_row read/write boolean property which, when true, indicates the last row should be formatted differently, as
for a totals row at the bottom of the table.
last_col read/write boolean property which, when true, indicates the last column should be formatted differently,
as for a side totals column at the far right of the table.
horz_banding read/write boolean property indicating whether alternate color “banding” should be applied to the
body rows.
vert_banding read/write boolean property indicating whether alternate color “banding” should be applied to the
table columns.
PowerPoint UI behavior
The MS PowerPoint® client exhibits the following behavior related to table properties:
Upon insertion of a default, empty table <a:tblPr firstRow=”1” bandRow=”1”> A tblPr element is present with
a firstRow and bandRow attribute, each set to True.
After setting firstRow property off <a:tblPr bandRow=”1”> The firstRow attribute is removed, not set to 0 or false.
The <a:tblPr> element is always present, even when it contains no attributes, because it contains an <a:tableStyleId>
element, even when the table style is set to none using the UI.
API requirements
Table class
• vert_banding – read/write boolean property indicating whether alternate color “banding” should be applied
to the table columns.
_Cell class
_Column class
_ColumnCollection class
• add(before) – add a new column to the left of the column having index before, returning a reference to the
new column. before defaults to -1, which adds the column as the last column in the table.
_Row class
• height – read/write integer height of the row in English Metric Units (EMU).
_RowCollection class
• add(before) – add a new row before the row having index before, returning a reference to the new row.
before defaults to -1, which adds the row as the last row in the table.
Behavior
A table is created by specifying a row and column count, a position, and an overall size. Initial column widths are set
by dividing the overall width by the number of columns, resolving any rounding errors in the last column. Conversely,
when a column’s width is specified, the table width is adjusted to the sum of the widths of all columns. Initial row
heights are set similarly and overall table height adjusted to the sum of row heights when a row’s height is specified.
MS API Analysis
There is a Shape.HasTable property which is true when a (GraphicFrame) shape contains a table.
Most interesting Table members:
• Cell(row, col) method to access individual cells.
• Columns collection reference, with Add method (Delete method is on Column object)
• Rows collection reference
• FirstCol and FirstRow boolean properties that indicate whether to apply special formatting from theme or what-
ever to first column/row.
• LastCol, LastRow, and HorizBanding, all also boolean with similar behaviors.
• TableStyle read-only to table style in theme. Table.ApplyStyle() method is used to set table style.
• Columns.Add()
• Rows.Add()
Column Members page on MSDN.
• Delete()
• Width property
Cell Members page on MSDN.
• Merge() and Split() methods
• Borders reference to Borders collection of LineFormat objects
• Shape reference to shape object that cell is or has.
LineFormat Members page on MSDN.
• ForeColor
• Weight
XML Semantics
A tableStyles.xml part is present in default document, containing the single (default) style “Medium Style 2 - Accent
1”. Colors are specified indirectly by reference to theme-specified values.
Specimen XML
<p:graphicFrame>
<p:nvGraphicFramePr>
<p:cNvPr id="2" name="Table 1"/>
<p:cNvGraphicFramePr>
<a:graphicFrameLocks noGrp="1"/>
(continues on next page)
Schema excerpt
<xsd:complexType name="CT_Table">
<xsd:sequence>
<xsd:element name="tblPr" type="CT_TableProperties" minOccurs="0"/>
<xsd:element name="tblGrid" type="CT_TableGrid"/>
<xsd:element name="tr" type="CT_TableRow" minOccurs="0" maxOccurs=
˓→"unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_TableProperties">
<xsd:sequence>
<xsd:group ref="EG_FillProperties" minOccurs="0"/>
<xsd:group ref="EG_EffectProperties" minOccurs="0"/>
<xsd:choice minOccurs="0">
<xsd:element name="tableStyle" type="CT_TableStyle"/>
<xsd:element name="tableStyleId" type="s:ST_Guid"/>
</xsd:choice>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="rtl" type="xsd:boolean" default="false"/>
<xsd:attribute name="firstRow" type="xsd:boolean" default="false"/>
<xsd:attribute name="firstCol" type="xsd:boolean" default="false"/>
<xsd:attribute name="lastRow" type="xsd:boolean" default="false"/>
<xsd:attribute name="lastCol" type="xsd:boolean" default="false"/>
<xsd:attribute name="bandRow" type="xsd:boolean" default="false"/>
<xsd:attribute name="bandCol" type="xsd:boolean" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_TableGrid">
<xsd:sequence>
<xsd:element name="gridCol" type="CT_TableCol" minOccurs="0" maxOccurs="unbounded
˓→"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_TableCol">
<xsd:sequence>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="w" type="ST_Coordinate" use="required"/>
</xsd:complexType>
(continues on next page)
<xsd:complexType name="CT_TableRow">
<xsd:sequence>
<xsd:element name="tc" type="CT_TableCell" minOccurs="0"
˓→maxOccurs="unbounded"/>
<xsd:complexType name="CT_TableCell">
<xsd:sequence>
<xsd:element name="txBody" type="CT_TextBody" minOccurs="0"/>
<xsd:element name="tcPr" type="CT_TableCellProperties" minOccurs="0"/>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="rowSpan" type="xsd:int" default="1"/>
<xsd:attribute name="gridSpan" type="xsd:int" default="1"/>
<xsd:attribute name="hMerge" type="xsd:boolean" default="false"/>
<xsd:attribute name="vMerge" type="xsd:boolean" default="false"/>
<xsd:attribute name="id" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType name="CT_TextBody">
<xsd:sequence>
<xsd:element name="bodyPr" type="CT_TextBodyProperties"/>
<xsd:element name="lstStyle" type="CT_TextListStyle" minOccurs="0"/>
<xsd:element name="p" type="CT_TextParagraph" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_TableCellProperties">
<xsd:sequence>
<xsd:element name="lnL" type="CT_LineProperties" minOccurs="0"/>
<xsd:element name="lnR" type="CT_LineProperties" minOccurs="0"/>
<xsd:element name="lnT" type="CT_LineProperties" minOccurs="0"/>
<xsd:element name="lnB" type="CT_LineProperties" minOccurs="0"/>
<xsd:element name="lnTlToBr" type="CT_LineProperties" minOccurs="0"/>
<xsd:element name="lnBlToTr" type="CT_LineProperties" minOccurs="0"/>
<xsd:element name="cell3D" type="CT_Cell3D" minOccurs="0"/>
<xsd:group ref="EG_FillProperties" minOccurs="0"/>
<xsd:element name="headers" type="CT_Headers" minOccurs="0"/>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="marL" type="ST_Coordinate32" default="91440"/>
<xsd:attribute name="marR" type="ST_Coordinate32" default="91440"/>
<xsd:attribute name="marT" type="ST_Coordinate32" default="45720"/>
<xsd:attribute name="marB" type="ST_Coordinate32" default="45720"/>
<xsd:attribute name="vert" type="ST_TextVerticalType" default="horz"/>
<xsd:attribute name="anchor" type="ST_TextAnchoringType" default="t"/>
<xsd:attribute name="anchorCtr" type="xsd:boolean" default="false"/>
<xsd:attribute name="horzOverflow" type="ST_TextHorzOverflowType" default="clip"/>
</xsd:complexType>
<xsd:simpleType name="ST_Coordinate">
<xsd:union memberTypes="ST_CoordinateUnqualified s:ST_UniversalMeasure"/>
</xsd:simpleType>
(continues on next page)
<xsd:simpleType name="ST_CoordinateUnqualified">
<xsd:restriction base="xsd:long">
<xsd:minInclusive value="-27273042329600"/>
<xsd:maxInclusive value="27273042316900"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_UniversalMeasure">
<xsd:restriction base="xsd:string">
<xsd:pattern value="-?[0-9]+(\.[0-9]+)?(mm|cm|in|pt|pc|pi)"/>
</xsd:restriction>
</xsd:simpleType>
Resources
• PowerPoint allows many formatting characteristics of a table to be set at once by assigning a table style to a
table.
• PowerPoint includes an array of built-in table styles that a user can browse in the table style gallery. These
styles are built into the PowerPoint application, and are only added to a .pptx file on first use.
• Zero or more table-styles can appear in the ppt/tableStyles.xml part. Each is keyed with a UUID, by which it is
referred to by a particular table that uses that style.
• A table may be assigned a table style by placing the matching UUID in the a:tbl/a:tblPr/a:tableStyleId element
text.
• A default table style may be specified by placing its id in a:tblStyleLst/@def in the tableStyles.xml part.
Shape
SlideShapes
Shapes on a slide are specified in the shape tree, a hierarchical data structure rooted in a <p:spTree> element.
Schema excerpt
<xsd:complexType name="CT_CommonSlideData">
<xsd:sequence>
<xsd:element name="bg" type="CT_Background" minOccurs="0"/>
<xsd:element name="spTree" type="CT_GroupShape"/>
<xsd:element name="custDataLst" type="CT_CustomerDataList" minOccurs="0"/>
<xsd:element name="controls" type="CT_ControlList" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="optional" default=""/>
</xsd:complexType>
<xsd:complexType name="CT_GroupShape">
<xsd:sequence>
<xsd:element name="nvGrpSpPr" type="CT_GroupShapeNonVisual"/>
<xsd:element name="grpSpPr" type="a:CT_GroupShapeProperties"/>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="sp" type="CT_Shape"/>
<xsd:element name="grpSp" type="CT_GroupShape"/>
<xsd:element name="graphicFrame" type="CT_GraphicalObjectFrame"/>
<xsd:element name="cxnSp" type="CT_Connector"/>
<xsd:element name="pic" type="CT_Picture"/>
<xsd:element name="contentPart" type="CT_Rel"/>
</xsd:choice>
<xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
Shapes - In General
Each visual element in a PowerPoint presentation is a shape. A shape appears on the “canvas” of a slide, which
includes the various types of master. Within a slide, shapes appear in a shape tree, corresponding to an <p:spTree>
element.
The following table summarizes the six shape types:
Some of these shape types have important sub-types. For example, a placeholder, a text box, and a preset geometry
shape such as a circle, are all defined with an <p:sp> element.
The <p:sp> element is used for three types of shape: placeholder, text box, and geometric shapes. A geometric shape
with preset geometry is referred to as an auto shape. Placeholder shapes are documented on the Placeholders page.
Auto shapes are documented on the Auto Shape page.
Geometric shapes are the familiar shapes that may be placed on a slide such as a rectangle or an ellipse. In the
PowerPoint UI they are simply called shapes. There are two types of geometric shapes, preset geometry shapes and
custom geometry shapes.
>>> shape.shape_id
42
>>> shape.name
u'Picture 5'
>>> shape.name = 'T501 - Foo; B. Baz; 2014'
>>> shape.name
u'T501 - Foo; B. Baz; 2014'
Shape.rotation
Read/write float degrees of clockwise rotation. Negative values can be used for counter-clockwise rotation.
XML Semantics ST_Angle is an integer value, 60,000 to each degree. PowerPoint appears to only ever use positive
values. Oddly, the UI uses positive values for counter-clockwise rotation while the XML uses positive increase
for clockwise rotation.
PowerPoint behavior It appears graphic frame shapes can’t be rotated. AutoShape, group, connector, and picture all
rotate fine.
Proposed protocol:
>>> shape.rotation
0.0
>>> shape.rotation = 45.2
>>> shape.rotation
45.2
Math:
def rot_from_angle(value):
"""
Return positive integer rotation in 60,000ths of a degree
corresponding to *value* expressed as a float number of degrees.
"""
DEGREE_INCREMENTS = 60000
THREE_SIXTY = 360 * DEGREE_INCREMENTS
# modulo normalizes negative and >360 degree values
return int(round(value * DEGREE_INCREMENTS)) % THREE_SIXTY
Specimen XML
<p:sp>
<p:nvSpPr>
<p:cNvPr id="3" name="Rounded Rectangle 2"/>
<p:cNvSpPr/>
<p:nvPr/>
</p:nvSpPr>
<p:spPr>
<a:xfrm>
<a:off x="760096" y="562720"/>
<a:ext cx="2520824" cy="914400"/>
</a:xfrm>
<a:prstGeom prst="roundRect">
<a:avLst>
<a:gd name="adj" fmla="val 30346"/>
</a:avLst>
</a:prstGeom>
</p:spPr>
<p:style>
<a:lnRef idx="1">
<a:schemeClr val="accent1"/>
</a:lnRef>
<a:fillRef idx="3">
<a:schemeClr val="accent1"/>
</a:fillRef>
<a:effectRef idx="2">
<a:schemeClr val="accent1"/>
</a:effectRef>
<a:fontRef idx="minor">
<a:schemeClr val="lt1"/>
</a:fontRef>
</p:style>
<p:txBody>
<a:bodyPr rtlCol="0" anchor="ctr"/>
<a:lstStyle/>
<a:p>
<a:pPr algn="ctr"/>
<a:r>
<a:rPr lang="en-US" dirty="0" smtClean="0"/>
<a:t>This is text inside a rounded rectangle</a:t>
</a:r>
<a:endParaRPr lang="en-US" dirty="0"/>
</a:p>
</p:txBody>
</p:sp>
<p:sp>
<p:nvSpPr>
<p:cNvPr id="2" name="TextBox 1"/>
<p:cNvSpPr txBox="1"/>
<p:nvPr/>
</p:nvSpPr>
(continues on next page)
<p:graphicFrame>
<p:nvGraphicFramePr>
<p:cNvPr id="2" name="Table 1"/>
<p:cNvGraphicFramePr>
<a:graphicFrameLocks noGrp="1"/>
</p:cNvGraphicFramePr>
<p:nvPr/>
</p:nvGraphicFramePr>
<p:xfrm>
<a:off x="1524000" y="1397000"/>
<a:ext cx="6096000" cy="741680"/>
</p:xfrm>
<a:graphic>
<a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/table">
<!-- graphical object XML or ref goes here -->
</a:graphicData>
</a:graphic>
</p:graphicFrame>
Connector shape:
<p:cxnSp>
<p:nvCxnSpPr>
<p:cNvPr id="6" name="Straight Connector 5"/>
<p:cNvCxnSpPr/>
<p:nvPr/>
</p:nvCxnSpPr>
<p:spPr>
<a:xfrm>
<a:off x="3131840" y="3068960"/>
<a:ext cx="2736304" cy="0"/>
</a:xfrm>
<a:prstGeom prst="line">
<a:avLst/>
</a:prstGeom>
</p:spPr>
<p:style>
<a:lnRef idx="2">
<a:schemeClr val="accent1"/>
</a:lnRef>
<a:fillRef idx="0">
<a:schemeClr val="accent1"/>
</a:fillRef>
<a:effectRef idx="1">
<a:schemeClr val="accent1"/>
</a:effectRef>
<a:fontRef idx="minor">
<a:schemeClr val="tx1"/>
</a:fontRef>
</p:style>
</p:cxnSp>
Picture shape:
<p:pic>
<p:nvPicPr>
<p:cNvPr id="6" name="Picture 5" descr="python-logo.gif"/>
<p:cNvPicPr>
<a:picLocks noChangeAspect="1"/>
</p:cNvPicPr>
<p:nvPr/>
</p:nvPicPr>
<p:blipFill>
<a:blip r:embed="rId2"/>
<a:stretch>
<a:fillRect/>
</a:stretch>
</p:blipFill>
<p:spPr>
<a:xfrm>
<a:off x="5580112" y="1988840"/>
<a:ext cx="2679700" cy="901700"/>
</a:xfrm>
<a:prstGeom prst="rect">
<a:avLst/>
</a:prstGeom>
<a:ln>
<a:solidFill>
<a:schemeClr val="bg1">
<a:lumMod val="85000"/>
</a:schemeClr>
</a:solidFill>
</a:ln>
</p:spPr>
</p:pic>
Resources
Schema excerpt
<xsd:complexType name="CT_Shape">
<xsd:sequence>
<xsd:element name="nvSpPr" type="CT_ShapeNonVisual"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties"/>
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0"/>
<xsd:element name="txBody" type="a:CT_TextBody" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="useBgFill" type="xsd:boolean" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_ShapeNonVisual">
(continues on next page)
<xsd:complexType name="CT_ShapeProperties">
<xsd:sequence>
<xsd:element name="xfrm" type="CT_Transform2D"
˓→minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="bwMode" type="ST_BlackWhiteMode"/>
</xsd:complexType>
<xsd:complexType name="CT_ShapeStyle">
<xsd:sequence>
<xsd:element name="lnRef" type="CT_StyleMatrixReference"/>
<xsd:element name="fillRef" type="CT_StyleMatrixReference"/>
<xsd:element name="effectRef" type="CT_StyleMatrixReference"/>
<xsd:element name="fontRef" type="CT_FontReference"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_TextBody">
<xsd:sequence>
<xsd:element name="bodyPr" type="CT_TextBodyProperties"/>
<xsd:element name="lstStyle" type="CT_TextListStyle" minOccurs="0"/>
<xsd:element name="p" type="CT_TextParagraph" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_ExtensionListModify">
<xsd:sequence>
<xsd:group ref="EG_ExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="mod" type="xsd:boolean" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_NonVisualDrawingProps">
<xsd:sequence>
(continues on next page)
<xsd:complexType name="CT_NonVisualDrawingShapeProps">
<xsd:sequence>
<xsd:element name="spLocks" type="CT_ShapeLocking" minOccurs="0"/>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="txBox" type="xsd:boolean" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_ApplicationNonVisualDrawingProps">
<xsd:sequence>
<xsd:element name="ph" type="CT_Placeholder" minOccurs="0"/>
<xsd:group ref ="a:EG_Media" minOccurs="0"/>
<xsd:element name="custDataLst" type="CT_CustomerDataList" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="isPhoto" type="xsd:boolean" default="false"/>
<xsd:attribute name="userDrawn" type="xsd:boolean" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_Transform2D">
<xsd:sequence>
<xsd:element name="off" type="CT_Point2D" minOccurs="0"/>
<xsd:element name="ext" type="CT_PositiveSize2D" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="rot" type="ST_Angle" default="0"/>
<xsd:attribute name="flipH" type="xsd:boolean" default="false"/>
<xsd:attribute name="flipV" type="xsd:boolean" default="false"/>
</xsd:complexType>
<xsd:group name="EG_Geometry">
<xsd:choice>
<xsd:element name="custGeom" type="CT_CustomGeometry2D"/>
<xsd:element name="prstGeom" type="CT_PresetGeometry2D"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="CT_CustomGeometry2D">
<xsd:sequence>
<xsd:element name="avLst" type="CT_GeomGuideList" minOccurs="0"/>
<xsd:element name="gdLst" type="CT_GeomGuideList" minOccurs="0"/>
<xsd:element name="ahLst" type="CT_AdjustHandleList" minOccurs="0"/>
<xsd:element name="cxnLst" type="CT_ConnectionSiteList" minOccurs="0"/>
<xsd:element name="rect" type="CT_GeomRect" minOccurs="0"/>
<xsd:element name="pathLst" type="CT_Path2DList"/>
</xsd:sequence>
</xsd:complexType>
(continues on next page)
<xsd:complexType name="CT_PresetGeometry2D">
<xsd:sequence>
<xsd:element name="avLst" type="CT_GeomGuideList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="prst" type="ST_ShapeType" use="required"/>
</xsd:complexType>
<xsd:group name="EG_FillProperties">
<xsd:choice>
<xsd:element name="noFill" type="CT_NoFillProperties"/>
<xsd:element name="solidFill" type="CT_SolidColorFillProperties"/>
<xsd:element name="gradFill" type="CT_GradientFillProperties"/>
<xsd:element name="blipFill" type="CT_BlipFillProperties"/>
<xsd:element name="pattFill" type="CT_PatternFillProperties"/>
<xsd:element name="grpFill" type="CT_GroupFillProperties"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="CT_LineProperties">
<xsd:sequence>
<xsd:group ref="EG_LineFillProperties" minOccurs="0"/>
<xsd:group ref="EG_LineDashProperties" minOccurs="0"/>
<xsd:group ref="EG_LineJoinProperties" minOccurs="0"/>
<xsd:element name="headEnd" type="CT_LineEndProperties" minOccurs="0"/>
<xsd:element name="tailEnd" type="CT_LineEndProperties" minOccurs="0"/>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="w" type="ST_LineWidth"/>
<xsd:attribute name="cap" type="ST_LineCap"/>
<xsd:attribute name="cmpd" type="ST_CompoundLine"/>
<xsd:attribute name="algn" type="ST_PenAlignment"/>
</xsd:complexType>
<xsd:complexType name="CT_Point2D">
<xsd:attribute name="x" type="ST_Coordinate" use="required"/>
<xsd:attribute name="y" type="ST_Coordinate" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_PositiveSize2D">
<xsd:attribute name="cx" type="ST_PositiveCoordinate" use="required"/>
<xsd:attribute name="cy" type="ST_PositiveCoordinate" use="required"/>
</xsd:complexType>
<xsd:group name="EG_EffectProperties">
<xsd:choice>
<xsd:element name="effectLst" type="CT_EffectList"/>
<xsd:element name="effectDag" type="CT_EffectContainer"/>
</xsd:choice>
</xsd:group>
<xsd:group name="EG_Media">
<xsd:choice>
<xsd:element name="audioCd" type="CT_AudioCD"/>
<xsd:element name="wavAudioFile" type="CT_EmbeddedWAVAudioFile"/>
<xsd:element name="audioFile" type="CT_AudioFile"/>
<xsd:element name="videoFile" type="CT_VideoFile"/>
(continues on next page)
<xsd:simpleType name="ST_DrawingElementId">
<xsd:restriction base="xsd:unsignedInt"/>
</xsd:simpleType>
<xsd:simpleType name="ST_Angle">
<xsd:restriction base="xsd:int"/>
</xsd:simpleType>
Shapes of the following types can appear in the shape tree of a slide (<p:spTree>) and each will require support for
querying size and position.
• sp – Auto Shape (completed)
• pic – Picture (completed)
• graphicFrame – container for table and chart shapes
• grpSp – Group Shape
• cxnSp – Connector (line)
• contentPart – has no position, but should return None instead of raising an exception
Protocol
XML specimens
Here is a representative sample of shape XML showing the placement of the position and size elements (in the
<a:xfrm> element).
Auto shape (rounded rectangle in this case):
<p:sp>
<p:nvSpPr>
<p:cNvPr id="3" name="Rounded Rectangle 2"/>
<p:cNvSpPr/>
<p:nvPr/>
</p:nvSpPr>
<p:spPr>
<a:xfrm>
(continues on next page)
<xsd:complexType name="CT_Shape">
<xsd:sequence>
<xsd:element name="nvSpPr" type="CT_ShapeNonVisual" minOccurs="1" maxOccurs=
˓→"1"/>
</xsd:sequence>
<xsd:attribute name="useBgFill" type="xsd:boolean" use="optional" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_Picture">
<xsd:sequence>
<xsd:element name="nvPicPr" type="CT_PictureNonVisual" minOccurs="1"
˓→maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_ShapeProperties">
<xsd:sequence>
<xsd:element name="xfrm" type="CT_Transform2D" minOccurs="0" maxOccurs="1"/>
...
</xsd:sequence>
<xsd:attribute name="bwMode" type="ST_BlackWhiteMode" use="optional"/>
</xsd:complexType>
(continues on next page)
<xsd:complexType name="CT_Transform2D">
<xsd:sequence>
<xsd:element name="off" type="CT_Point2D" minOccurs="0" maxOccurs="1"/>
<xsd:element name="ext" type="CT_PositiveSize2D" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="rot" type="ST_Angle" use="optional" default="0"/>
<xsd:attribute name="flipH" type="xsd:boolean" use="optional" default="false"/>
<xsd:attribute name="flipV" type="xsd:boolean" use="optional" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_Point2D">
<xsd:attribute name="x" type="ST_Coordinate" use="required"/>
<xsd:attribute name="y" type="ST_Coordinate" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_PositiveSize2D">
<xsd:attribute name="cx" type="ST_PositiveCoordinate" use="required"/>
<xsd:attribute name="cy" type="ST_PositiveCoordinate" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_PositiveCoordinate">
<xsd:restriction base="xsd:long">
<xsd:minInclusive value="0"/>
<xsd:maxInclusive value="27273042316900"/>
</xsd:restriction>
</xsd:simpleType>
Autofit setting
Overview
PowerPoint provides the autofit property to specify how to handle text that is too big to fit within its shape. The three
possible settings are:
• resize shape to fit text
• resize text to fit shape
• resize neither the shape nor the text, allowing the text to extend beyond the bounding box
Auto size is closely related to word wrap.
There are certain constraining settings for resizing the text, not sure if those are supported in PowerPoint or not.
Protocol
Scenarios
Default new textbox. When adding a new texbox from the PowerPoint toolbar, the new textbox sizes itself to fit
the entered text. This corresponds to the setting MSO_AUTO_SIZE.SHAPE_TO_FIT_TEXT and word_wrap =
None.
MSO_AUTO_SIZE.NONE, word_wrap = False. Text is free form, with PowerPoint exhibiting no formatting
behavior. Text appears just as entered and lines are broken only where hard breaks are inserted.
MSO_AUTO_SIZE.NONE, word_wrap = True. Text is wrapped into a column the width of the shape, but is not
constrained vertically.
MSO_AUTO_SIZE.SHAPE_TO_FIT_TEXT, word_wrap = False. The width of the shape expands as new text
is entered. Line breaks occur only where hard breaks are entered. The height of the shape grows to accommodate the
number of lines of entered text. Width and height shrink as extents of the text are reduced by deleting text or reducing
font size.
MSO_AUTO_SIZE.SHAPE_TO_FIT_TEXT, word_wrap = True. Text is wrapped into a column the width of
the shape, with the height of the shape growing to accommodate the resulting number of lines.
MSO_AUTO_SIZE.TEXT_TO_FIT_SHAPE, word_wrap = False. Experiment . . .
MSO_AUTO_SIZE.TEXT_TO_FIT_SHAPE, word_wrap = True. Experiment . . .
XML specimens
<xsd:complexType name="CT_TextBody">
<xsd:sequence>
<xsd:element name="bodyPr" type="CT_TextBodyProperties"/>
<xsd:element name="lstStyle" type="CT_TextListStyle" minOccurs="0"/>
<xsd:element name="p" type="CT_TextParagraph" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_TextBodyProperties">
<xsd:sequence>
<xsd:element name="prstTxWarp" type="CT_PresetTextShape" minOccurs="0"/>
<xsd:group ref="EG_TextAutofit" minOccurs="0"/>
<xsd:element name="scene3d" type="CT_Scene3D" minOccurs="0"/>
<xsd:group ref="EG_Text3D" minOccurs="0"/>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:group name="EG_TextAutofit">
<xsd:choice>
<xsd:element name="noAutofit" type="CT_TextNoAutofit"/>
<xsd:element name="normAutofit" type="CT_TextNormalAutofit"/>
<xsd:element name="spAutoFit" type="CT_TextShapeAutofit"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="CT_TextNormalAutofit">
<xsd:attribute name="fontScale" type="ST_TextFontScalePercentOrPercentString"
use="optional" default="100%"/>
<xsd:attribute name="lnSpcReduction" type="ST_TextSpacingPercentOrPercentString"
use="optional" default="0%"/>
</xsd:complexType>
<xsd:complexType name="CT_TextShapeAutofit"/>
<xsd:complexType name="CT_TextNoAutofit"/>
<xsd:group name="EG_Text3D">
<xsd:choice>
<xsd:element name="sp3d" type="CT_Shape3D"/>
<xsd:element name="flatTx" type="CT_FlatText"/>
</xsd:choice>
</xsd:group>
Group Shape
PowerPoint Behaviors
XML Semantics
• chOff and chExt represent child offset and child extents, respectively. These are used if the group itself is
transformed, in particular when it is scaled.
MS API
XML Specimens
<p:grpSp>
<p:nvGrpSpPr>
<p:cNvPr id="5" name="Group 4"/>
<p:cNvGrpSpPr/>
<p:nvPr/>
</p:nvGrpSpPr>
<p:grpSpPr>
<a:xfrm>
<a:off x="3347864" y="2204864"/>
<a:ext cx="3506688" cy="2930624"/>
<a:chOff x="3347864" y="2204864"/>
<a:chExt cx="3506688" cy="2930624"/>
</a:xfrm>
</p:grpSpPr>
<p:sp>
<p:nvSpPr>
<p:cNvPr id="2" name="Rounded Rectangle 1"/>
<p:cNvSpPr/>
<p:nvPr/>
</p:nvSpPr>
<p:spPr>
<a:xfrm>
<a:off x="3347864" y="2204864"/>
<a:ext cx="914400" cy="914400"/>
(continues on next page)
<xsd:complexType name="CT_GroupShape">
<xsd:sequence>
<xsd:element name="nvGrpSpPr" type="CT_GroupShapeNonVisual"/>
(continues on next page)
<xsd:complexType name="CT_GroupShapeNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps"/>
<xsd:element name="cNvGrpSpPr" type="a:CT_NonVisualGroupDrawingShapeProps"/>
<xsd:element name="nvPr" type="CT_ApplicationNonVisualDrawingProps"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_GroupShapeProperties">
<xsd:sequence>
<xsd:element name="xfrm" type="CT_GroupTransform2D" minOccurs="0"/>
<xsd:group ref="EG_FillProperties" minOccurs="0"/>
<xsd:group ref="EG_EffectProperties" minOccurs="0"/>
<xsd:element name="scene3d" type="CT_Scene3D" minOccurs="0"/>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="bwMode" type="ST_BlackWhiteMode"/>
</xsd:complexType>
<xsd:complexType name="CT_GroupTransform2D">
<xsd:sequence>
<xsd:element name="off" type="CT_Point2D" minOccurs="0"/>
<xsd:element name="ext" type="CT_PositiveSize2D" minOccurs="0"/>
<xsd:element name="chOff" type="CT_Point2D" minOccurs="0"/>
<xsd:element name="chExt" type="CT_PositiveSize2D" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="rot" type="ST_Angle" default="0"/>
<xsd:attribute name="flipH" type="xsd:boolean" default="false"/>
<xsd:attribute name="flipV" type="xsd:boolean" default="false"/>
</xsd:complexType>
<xsd:group name="EG_EffectProperties">
<xsd:choice>
<xsd:element name="effectLst" type="CT_EffectList"/>
<xsd:element name="effectDag" type="CT_EffectContainer"/>
</xsd:choice>
</xsd:group>
<xsd:group name="EG_FillProperties">
<xsd:choice>
<xsd:element name="noFill" type="CT_NoFillProperties"/>
<xsd:element name="solidFill" type="CT_SolidColorFillProperties"/>
<xsd:element name="gradFill" type="CT_GradientFillProperties"/>
<xsd:element name="blipFill" type="CT_BlipFillProperties"/>
(continues on next page)
Auto Shape
Summary
AutoShape is the name the MS Office API uses for a shape with preset geometry, those referred to in the PowerPoint
UI simply as shape. Typical examples are a rectangle, a circle, or a star shape. An auto shape has a type (preset
geometry), an outline line style, a fill, and an effect, in addition to a position and size. The outline, fill, and effect can
each be None.
Each auto shape is contained in an <p:sp> element.
There are 187 pre-defined auto shape types, each corresponding to a distinct preset geometry. Some types have one
or more adjustment value, which corresponds to the position of an adjustment handle (small yellow diamond) on the
shape in the UI that changes an aspect of the shape geometry, for example the corner radius of a rounded rectangle.
• MsoAutoShapeType Enumeration page on MSDN
Adjustment values
Many auto shapes may be adjusted to change their shape beyond just their width, height, and rotation. In the Pow-
erPoint application, this is accomplished by dragging small yellow diamond-shaped handles that appear on the shape
when it is selected.
In the XML, the position of these adjustment handles is reflected in the contents of the <a:avLst> element:
<a:prstGeom prst="roundRect">
<a:avLst>
<a:gd name="adj" fmla="val 30346"/>
</a:avLst>
</a:prstGeom>
The <a:avLst> element can be empty, even if the shape has available adjustments.
guide a guide is essentially a variable within DrawingML. Its value is the result of a simple expression like "*/
100000 w ss". Its value may then be used in other expressions or directly to specify a point, by referring to
it by name.
<a:gd> stands for guide . . .
Where are the custom geometries defined? The geometries for autoshapes are defined in
presetShapeDefinitions.xml, located in:
pptx/ref/ISO-IEC-29500-1/schemas/dml-geometries/OfficeOpenXML-DrawingMLGeometries/
.
What is the range of the formula values? In general, the nominal adjustment value range for the preset shapes is 0
to 100000. However, the actual value stored can be outside that range, depending on the formulas involved. For
example, in the case of the chevron shape, the range is from 0 to 100000 * width / short-side. When the shape
is taller than it is wide, width is the short side and the range is 0 to 100000. However, when the shape is wider
than it is tall, the range can be much larger. Required values are probably best discovered via experimentation
or calculation based on the preset formula.
The <a:avLst> element does not appear initially when the shape is inserted. However, if the adjustment handle is
moved and then moved back to the default value, the <a:avLst> element is not removed. The default value becomes
the effective value for the guide if the <a:avLst> element is not present.
The adjustment value is preserved over scaling of the object. Its effective value can change however, depending on the
formula. In the case of the chevron shape, the effective value is a function of ss, the “short side”, and the adjustment
handle moves on screen when the chevron is made wider than it is tall.
A certain level of documentation for auto shapes could be generated from the XML shape definition file. The preset
name and the number of adjustment values it has (guide definitions) and the adjustment value name can readily be
determined by inspection of the XML.
What coordinate system are the formula values expressed in? There appear to be two coordinate systems at work.
The 0 to 100000 bit the adjustment handles are expressed in appears to be the (arbitrary) shape coordinate
system. The built-in values like w, ss, etc., appear to be in the slide coordinate system, the one the xfrm
element traffics in.
Probably worth experimenting with some custom shapes to find out (edit and rezip with bash one-liner).
useful web resources What useful web resources are out there on DrawingML?
http://officeopenxml.com/drwSp-custGeom.php
<p:sp>
<p:nvSpPr>
<p:cNvPr id="3" name="Rounded Rectangle 2"/>
<p:cNvSpPr/>
<p:nvPr/>
</p:nvSpPr>
<p:spPr>
<a:xfrm>
<a:off x="760096" y="562720"/>
<a:ext cx="2520824" cy="914400"/>
</a:xfrm>
<a:prstGeom prst="roundRect">
<a:avLst>
<a:gd name="adj" fmla="val 30346"/>
</a:avLst>
</a:prstGeom>
</p:spPr>
<p:style>
<a:lnRef idx="1">
<a:schemeClr val="accent1"/>
</a:lnRef>
<a:fillRef idx="3">
<a:schemeClr val="accent1"/>
</a:fillRef>
<a:effectRef idx="2">
(continues on next page)
Resources
Shadow
Shadow is inherited, and a shape often appears with a shadow without explicitly applying a shadow format.
The only difference in a shape with shadow turned off is the presence of an empty <a:effectLst/> child in its <p:spPr>
element. Inherited shadow is turned off when p:spPr/a:effectLst is present with no a:outerShdw child element. Other
effect child elements may be present.
A shadow is one type of “effect”. The others are glow/soft-edges and reflection.
Shadow may be of type outer (perhaps most common), inner, or perspective.
Scope
Protocol
The .shadow property on a shape always returns the ShadowFormat object for that shape, regardless of whether its
shadow is explicit or inherited:
The .shadow property is idempotent, meaning the same ShadowFormat object (verified by comparing ID) is returned
on every call, for the lifetime of the shape object:
>>> shape.shadow
<pptx.dml.effect.ShadowFormat object at 0x108080490>
>>> shape.shadow
<pptx.dml.effect.ShadowFormat object at 0x108080490>
The ShadowFormat.inherit property indicates whether the shape inherits its shadow effect or overrides it with an
explicitly defined setting. The default setting for a new shape is True:
>>> shadow.inherit
True
Assigning False breaks the inheritance link by explicitly defining a “no-shadow” setting for the shape. This causes the
shape to appear without a shadow, regardless of the applied theme:
Note that this has the side-effect of disabling inheritance of all effects for that shape.
PowerPoint behaviors
• All 5 shape-types can display a shadow, but graphics-frame objects like chart and table use a different mechanism
than the other shapes. Those won’t be supported initially.
– AutoShape
– Connector
– Picture
– Group Shape (parent is p:grpSpPr rather than p:spPr)
– Graphics Frame (UI allows, but uses a different mechanism)
• Adding shadow to a group shape adds that shadow to each component shape in the group.
• There is a “new-shape format” concept. This format determines what a new shape looks like, but does not
change the appearance of shapes already in place. It’s basically a template imprinted on new shapes when they
are added.
Theme Effects are a thing here. They are Subtle, Moderate, and Intense.
There are 40 built-in theme effects. Each of these have . . .
• Setting visible off (Format Shape > Shadow > Clear Shadow checkbox) for a customized shadow removes
all customized settings and they are not recoverable by setting the shadow visible again (clicking the shadow
checkbox).
MS API
ShadowFormat object
• ShadowFormat.Visible
Specimen XML
Shape inheriting shadow. Note the absence of p:spPr/a:effectLst, causing all effects to be inherited:
<p:sp>
<p:nvSpPr>
<p:cNvPr id="4" name="Rounded Rectangle 3"/>
<p:cNvSpPr/>
<p:nvPr/>
</p:nvSpPr>
<p:spPr>
<a:xfrm>
<a:off x="4114800" y="2971800"/>
<a:ext cx="914400" cy="914400"/>
</a:xfrm>
<a:prstGeom prst="roundRect">
<a:avLst/>
</a:prstGeom>
</p:spPr>
<p:style>
<a:lnRef idx="1">
<a:schemeClr val="accent1"/>
(continues on next page)
XML Semantics
<a:effectStyle>
<a:effectLst>
<a:outerShdw blurRad="40000" dist="23000" dir="5400000"
rotWithShape="0">
<a:srgbClr val="000000">
<a:alpha val="35000"/>
</a:srgbClr>
</a:outerShdw>
</a:effectLst>
</a:effectStyle>
Schema excerpt
</xsd:sequence>
<xsd:attribute name="bwMode" type="ST_BlackWhiteMode"/>
</xsd:complexType>
<xsd:complexType name="CT_EffectList">
<xsd:sequence>
<xsd:element name="blur" type="CT_BlurEffect" minOccurs="0"/>
<xsd:element name="fillOverlay" type="CT_FillOverlayEffect" minOccurs="0"/>
<xsd:element name="glow" type="CT_GlowEffect" minOccurs="0"/>
<xsd:element name="innerShdw" type="CT_InnerShadowEffect" minOccurs="0"/>
<xsd:element name="outerShdw" type="CT_OuterShadowEffect" minOccurs="0"/>
<xsd:element name="prstShdw" type="CT_PresetShadowEffect" minOccurs="0"/>
<xsd:element name="reflection" type="CT_ReflectionEffect" minOccurs="0"/>
<xsd:element name="softEdge" type="CT_SoftEdgesEffect" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_OuterShadowEffect">
<xsd:sequence>
<xsd:group ref="EG_ColorChoice" minOccurs="1" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="blurRad" type="ST_PositiveCoordinate" default="0"/>
<xsd:attribute name="dist" type="ST_PositiveCoordinate" default="0"/>
<xsd:attribute name="dir" type="ST_PositiveFixedAngle" default="0"/>
<xsd:attribute name="sx" type="ST_Percentage" default="100%"/>
<xsd:attribute name="sy" type="ST_Percentage" default="100%"/>
<xsd:attribute name="kx" type="ST_FixedAngle" default="0"/>
<xsd:attribute name="ky" type="ST_FixedAngle" default="0"/>
<xsd:attribute name="algn" type="ST_RectAlignment" default="b"/>
<xsd:attribute name="rotWithShape" type="xsd:boolean" default="true"/>
</xsd:complexType>
<xsd:simpleType name="ST_RectAlignment">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="tl"/>
<xsd:enumeration value="t"/>
<xsd:enumeration value="tr"/>
<xsd:enumeration value="l"/>
<xsd:enumeration value="ctr"/>
<xsd:enumeration value="r"/>
<xsd:enumeration value="bl"/>
<xsd:enumeration value="b"/>
<xsd:enumeration value="br"/>
</xsd:restriction>
</xsd:simpleType>
Freeform Shapes
PowerPoint AutoShapes, such as rectangles, circles, and triangles, have a preset geometry. The user simply picks from
a selection of some 160 pre-defined shapes to place one on the slide, at which point they can be scaled. Many shapes
allow their geometry to be adjusted in certain ways using adjustment points (by dragging the small yellow diamonds).
PowerPoint also supports a much less commonly used but highly flexible sort of shape having custom geometry.
Whereas a shape with preset geometry has that geometry defined internally to PowerPoint and simply referred to by
a keyname (such as ‘rect’), a shape with custom geometry spells out the custom geometry step-by-step in an XML
subtree, using a sequence of moveTo, lineTo, and other drawing commands.
Vocabulary
• A freeform shape is composed of one or more paths. Each path may be configured to get a stroke, a fill, both,
or neither. This allows drawing some shapes such as call-outs where, say, a reference line should be stroked but
not filled, and the callout balloon contour should be filled but not stroked.
Each path also has its own local coordinate system, which may come in handy when using guides. I haven’t
seen any clear examples of this yet but I haven’t gone looking either.
In any case, only a single path will be supported in the initial implementation.
• A path is composed of one or more contours. A contour can be a closed contour or and open contour. The
closure state only affects the continuity of the contour outline (although it also adds a straight line between start
and end if needed).
• A contour is specified by a starting point (<a:moveTo>) followed by a sequence of line segments, each of which
can be a straight or curved. Curve segments will not be supported in the initial implementation.
The term contour is not “official”, but there are behaviors that depend on “continuous pen-down strokes”, such
as “cut-out” behavior. Consequently, a term is needed.
Scope
Limits of scope
A very simple case can be had by specifying the verticies in slide coordinates:
This method may be used to place a freeform shape when you know exactly where you want the vertices to be
positioned on the slide. The position and size of the shape (its bounding box) is worked out automatically from the
minimum and maximum x and y positions of the points specified.
The shape is automatically closed if the last vertex is the same as the beginning vertex; otherwise the shape is left
open.
The library automatically subtracts the top-left corner (origin) coordinates from each point to write the XML.
The next step up in complexity is where a custom coordinate system is to be used to specify vertices for a single shape.
In this alternative, all the verticies are specified in custom coordinates and a scaling factor is provided:
This method creates a shape of exactly the same appearance as the prior example. It’s probably not the most natural
approach because all coordinates have to be translated to their position on the slide. However, it is an option and it’s
more compact. It could also be made to work with floating point values.
This could also work by creating the shape at (0, 0) on the slide and then simply moving the shape to where you
wanted using its .top and .left properties.
This is perhaps the most natural approach for doing something fancy, like creating individual shapes for each of the 50
US states within a particular area of the slide such that their boundaries all align with adjacent states to make a map of
As we can see here, the size of the shape is exactly the same, but it has been translated to be relative to the slide
coordinates provided in the .build_freeform() call.
Another use case is where you want to specify a shape entirely in terms of its local coordinates, relative to its local
origin (top-left corner). This might be used when you want a custom shape that is not one of the 168 provided preset
geometry shapes, say an orthoganal projection cube or something like that, and then place that in a variety of locations
around the slide.
For this you build the shape as in Use Case 2, allowing the origin to default to (0, 0), and then specify a position for
the shape in the .convert_to_shape() call. You can even call .convert_to_shape() multiple times to “rubber stamp” the
shape in various positions around the slide.
Can you call .convert_to_shape() multiple times? Maybe that would be good!
Usage Notes
Closing a contour. A contour is only truly closed if it ends with a <a:close> element. It can appear closed if its end
point is the same as its start point, but close inspection of the line-ends will reveal there is no smooth transition around
the starting corner. This is more apparent when a wide line style is used for the outline.
A <a:close> element will cause a straight line segment to be drawn between the last point point of the contour and
the first. So it’s not necessary to repeat the first point as the last one if a straight line segment suits. The advantage is
small however, and might only be an optimization to consider when thousands of freeform shapes were being drawn
in a single presentation.
Candidate Protocol
The x and y arguments specify the starting pen location in local coordinates. The scale argument determines the
rendered size of the shape relative to the values specified for the vertices. The scale argument can be an (x_scale,
y_scale) pair to specify a shape coordinate system that is rectangular rather than square.
Add vertices to the freeform shape an arbitrary number of straight line segments can be added to the shape using the
add_line_segments() method:
The method also specifies whether the contour so generated should be closed (True by default). Closing a contour
causes its end point to be connected to its starting point with a straight line segment. It also causes the contour to form
a smooth perimeter outline. A contour that is not closed will have line end caps and may be assigned line ends like
arrowheads.
Although PowerPoint supports a variety of curved line segments, those will not be implemented in this initial effort.
Add second and further contours A path can have multiple distinct contours. These contours can be separate and
distinct or they can overlap. A contour that is completely enclosed by another contour forms a “cutout” in the enclosing
contour. Where two contours partially overlap, the fill begins at the outermost boundary and stops when it reaches
another boundary.
>>> freeform_builder.move_to(x, y)
Possible approach:
Optionally specify an alternate coordinate system in the initial call such that parameters are:
• x, y - X and Y coordinates of initial pen position. If no scaling factor is provided, these are interpreted as Length
values from the top-left corner of the slide.
• scale=1.0 (optional) - Determines the scaling of the x and y values used to specify the vertices. This is a
proportion to a Length unit, which is an Emu, 914400 to the inch. This value is conveniently formed by division
with a Length subclass, like 1000/Inches(1) to give “1000 units per inch” in that case. This could just as easily
be 2142/Cm(1) to give “2142 units per centimeter”. The default value of 1.0 means “1 unit per Emu”.
• left (optional) - X-axis position of top-left corner of freeform shape bounding box, specified as a Length (not
scaled) value relative to left edge of slide. If this value is not specified, it is calculated from the minimum x
position of the points in the shape.
• top (optional) - Y-axis position of top-left corner of freeform shape bounding box, specified as a Length (not
scaled) value relative to top edge of the slide. If this value is not specified, it is calculated from the minimum y
position of the points in the shape.
• y_scale=None (optional, not implemented) - Y-axis scaling factor (defaults to same as X-axis scaling factor)
The shape size (extents) are calculated from max_X and max_Y in given coordinates, multiplied by the scaling factor.
Experimentation
Q. How does PowerPoint behave if we leave out all the “guides” and connection points, i.e. if the a:gdLst and
a:cxnLst elements are empty?
A. It likes it just fine. Might not be a bad idea to leave empty a:gdLst and a:cxnLst elements in there though, when
creating a new freeform XML subtree, just to be a little safer compatibility-wise since PowerPoint seems to
always put them in there.
Q. What happens if a second path overlaps the first one, i.e. partly in and partly out?
A. The “outside” portion of the overlapping contour becomes the outside of the shape and the region between
that contour and the boundary of the first shape is shaded. This produces two (or more) “point” areas on the
perimeter of the first shape where the width is zero.
Q. What happens if the last point is not the same as the first point and the path is closed?
A. A straight-line segment is added between the last point and the starting point. The appearance is just as it is
when the last point is the same as the starting point.
Q. What happens if you do a shape with an a:moveTo in the middle (producing a gap in the outline) but then close
the shape? Does it still get a fill or is it considered open then?
A. The moveTo operation essentially resets the “starting” point for closure purposes. The remainder of the path is
closed, but the part before the moveTo remains an open contour.
Q. What happens when the last point is the same as the first point but there is no a:close element?
A. The shape outline is discontinuous at the start/end point and does not form a smooth contour at that point. The
visual appearance depends on the line ends and line end caps chosen.
PowerPoint UI behaviors
• A freeform shape can be created using the ribbon Shape > Lines and Connectors > Freeform command. There
is also a “Curve” and “Scribble” option.
• A shape is then created by placing points with the mouse. In the freeform case, each vertex defines a line
segment. In the case of a curve freeform, the vertices are control points.
• Clicking close to the starting point closes the shape. Double-clicking also ends the drawing, leaving the shape
open.
• Once created, an “Edit Points” option appears on the context menu when right-clicking the shape. This allows
the points to be fine-tuned.
• Hypothesis: PowerPoint uses an arbitrary scale of 10,000 (period, not per inch) as the coordinate space for a
freeform shape added or edited using the UI. The rules are more complicated, not sure what they are, but it
seems to start with a square of about that and move from there.
MS API
MS API protocol
Example:
• Specify each vertex separately in an .AddNodes() method call. It seems like it should actually be named
.AddNode(), but perhaps they consider control points to be nodes separate from the vertex point.
A line segment can be specified by specifying the x, y vertex of the ending point.
A curve segment can be specified by specifying additional control points (nodes). The vertex can be specified
to be a corner (one control point on starting vertex), smooth (tangent at the vertex), or symmetric (we’d have to
experiment to see what that does exactly, no ready available documentation).
• The path is closed (or not) when the .ConvertToShape() method is called on the FreeformBuilder object. It looks
like it’s closed if the last point is coincident with the first and open otherwise.
• There is no way to make a multi-path shape as far as I can tell.
• The MS API provides no way to “lift the pen” to make a discontinuous path as far as I can tell. (And so does
not provide a way to make “cutouts” like a lake within a landmass shape.)
MS API Objects
• Shapes.BuildFreeform(x, y)
https://msdn.microsoft.com/VBA/PowerPoint-VBA/articles/shapes-buildfreeform-method-powerpoint
• FreeformBuilder
https://msdn.microsoft.com/VBA/PowerPoint-VBA/articles/freeformbuilder-object-powerpoint
• FreeformBuilder.AddNodes()
https://msdn.microsoft.com/en-us/vba/powerpoint-vba/articles/freeformbuilder-addnodes-method-powerpoint
• FreeformBuilder.ConvertToShape()
https:
//msdn.microsoft.com/VBA/PowerPoint-VBA/articles/freeformbuilder-converttoshape-method-powerpoint
Cannot be called before adding at least one segment to the shape.
• Shape.Nodes
• MsoSegmentType enumeration
https://msdn.microsoft.com/VBA/Office-Shared-VBA/articles/msosegmenttype-enumeration-office
• MsoEditingType enumeration
https://msdn.microsoft.com/VBA/Office-Shared-VBA/articles/msoeditingtype-enumeration-office
XML Semantics
• The w and h attributes of a a:path element specify size of the shape canvas in local coordinates.
– The origin of the shape canvas is at its top left corner and has the value (0, 0) in local coordinates. The
vertices must be translated by the X and Y minima to place the bounding box tightly around the shape.
• The a:rect element specifies the text-box extents for the shape.
• The a:pathLst element contains zero or more a:path elements, each of which specify a path.
• A path has a private and arbitrary integral coordinate system defined by the w and h attributes on the a:path
element. This means that each path in an a:custGeom/a:pathLst has an independent scaling for its coordinate
system.
• A path is composed of a sequence of the following possible elements:
– a:moveTo
– a:lnTo
– a:arcTo
– a:quadBezTo
– a:cubicBezTo
– a:close
A path may begin with an a:moveTo element. This essentially locates the starting location of the “pen”. Each
subsequent drawing command extends the shape by adding a line segment. If the path does not begin with an
a:moveTo element, the path does not appear (it is not drawn). Note this is contrary to the (unofficial) documen-
tation indicating that (0, 0) is used as the default starting pen location.
A path can be open or closed. If an a:close element is added, a straight line segment is drawn from the current
pen location to the initial location of the drawing sequence and the shape appears with a fill. If the pen is already
at the starting location, no additional line segment appears. If no a:close element is added, the shape remains
“open” and only the path appears (no fill).
A path can contain more than one drawing sequence, i.e. one sequence can be “closed” and another sequence
started. If a subsequent drawing sequence is entirely enclosed within a prior sequence, it appears as a “cutout”,
or an interior boundary. This behavior does not occur when the two drawing sequences are in separate paths,
even within the same shape.
The pen can be “lifted” using an a:moveTo element, in which case no line segment is drawn between the prior
location and the new location. This can be used to produce a discontinuous outline.
A path has a boolean stroke attribute (default True) that specifies whether a line should appear on the path.
• The a:pathLst element can contain multiple a:path elements. In this case, each path is essentially a “sub-shape”,
such as a shape that depicts the islands of Hawaii.
If a prior path is not closed, its end point path will be connected to the first point of the subsequent path.
The paths within a shape all have the same z-position, i.e. they appear on a single plane such that all outlines
appear, even when they intersect. There is no cropping behavior such as occurs for individual shapes on a slide.
Fill behavior
Hypothesis: Any shape can have a fill, even an “open” shape. The question of whether a shape has a fill is not
determined by whether it is closed, but by whether a fill is applied to the shape.
In the PowerPoint UI, a closed shape is automatically assigned a fill when it is drawn. Conversely, an open shape is
not assigned a fill. This behavior is built into the drawing code and is not dependent solely on the “closed-ness” of the
shape.
The XML template for a freeform shape (as of this writing) includes an element for a fill and effect, consistent with
the PowerPoint defaults for a closed shape. The fill would need to be removed from an open shape if the user didn’t
want it.
Coordinate system
• Each path has its own local coordinate system, distinct both from the shape coordinate system and the coordinate
systems of the other paths in the shape.
• The x and y extents of a path coordinate system are specified by the w and h attributes on the a:path element,
respectively. The top, left corner of the path bounding box is (0, 0) and the bottom, right corner is at (h, w).
Coordinates are positive integers in the range 0 to 27,273,042,316,900 (about 2^44.63).
Resources
XML Specimens
This triangle is hand-built using the ‘Freeform’ shape tool in the PowerPoint UI. A couple things to notice:
• The shape includes a full complement of <a:gd> and <a:cxn> elements. The shape works fine without these
and providing a way to specify these is out of scope for the current effort.
• The freeform shape itself is specified in p:sp/p:spPr/a:custGeom. That’s a little interesting that the geometry is
considered a shape property (spPr) rather than somehow more core to the shape.
• The <a:pathLst> element contains only a single path. I haven’t yet discovered how to add a second path to a
shape using the UI.
<p:sp>
<p:nvSpPr>
<p:cNvPr id="2" name="Freeform 1"/>
<p:cNvSpPr/>
<p:nvPr/>
</p:nvSpPr>
(continues on next page)
The rest of these shape subtrees have the <a:gdLst> and <a:cxnLst> elements removed for brevity and many focus
simply on the a:pathLst element for compact presentation.
This one is a little tricky to see, but if you look closely, you’ll see that the outline at the apex of the triangle is not
“closed”. This behavior arises when there is no <a:close/> element at the end of the path, even when the end-point is
the same as the start-point:
<a:pathLst>
<a:path w="100" h="100">
<a:moveTo><a:pt x="50" y="0"/></a:moveTo>
<a:lnTo><a:pt x="100" y="100"/></a:lnTo>
<a:lnTo><a:pt x="0" y="100"/></a:lnTo>
<a:lnTo><a:pt x="50" y="0"/></a:lnTo>
(continues on next page)
</xsd:sequence>
<xsd:attribute name="bwMode" type="ST_BlackWhiteMode" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_CustomGeometry2D">
<xsd:sequence>
<xsd:element name="avLst" type="CT_GeomGuideList" minOccurs="0"/>
<xsd:element name="gdLst" type="CT_GeomGuideList" minOccurs="0"/>
<xsd:element name="ahLst" type="CT_AdjustHandleList" minOccurs="0"/>
<xsd:element name="cxnLst" type="CT_ConnectionSiteList" minOccurs="0"/>
(continues on next page)
<xsd:complexType name="CT_Path2DList">
<xsd:sequence>
<xsd:element name="path" type="CT_Path2D" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Path2D">
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="close" type="CT_Path2DClose"/>
<xsd:element name="moveTo" type="CT_Path2DMoveTo"/>
<xsd:element name="lnTo" type="CT_Path2DLineTo"/>
<xsd:element name="arcTo" type="CT_Path2DArcTo"/>
<xsd:element name="quadBezTo" type="CT_Path2DQuadBezierTo"/>
<xsd:element name="cubicBezTo" type="CT_Path2DCubicBezierTo"/>
</xsd:choice>
<xsd:attribute name="w" type="ST_PositiveCoordinate" default="0"/>
<xsd:attribute name="h" type="ST_PositiveCoordinate" default="0"/>
<xsd:attribute name="fill" type="ST_PathFillMode" default="norm"/>
<xsd:attribute name="stroke" type="xsd:boolean" default="true"/>
<xsd:attribute name="extrusionOk" type="xsd:boolean" default="true"/>
</xsd:complexType>
<xsd:complexType name="CT_Path2DClose"/>
<xsd:complexType name="CT_Path2DLineTo">
<xsd:sequence>
<xsd:element name="pt" type="CT_AdjPoint2D"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Path2DMoveTo">
<xsd:sequence>
<xsd:element name="pt" type="CT_AdjPoint2D"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_AdjPoint2D">
<xsd:attribute name="x" type="ST_AdjCoordinate" use="required"/>
<xsd:attribute name="y" type="ST_AdjCoordinate" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_GeomGuideName">
<xsd:restriction base="xsd:token"/>
</xsd:simpleType>
<xsd:simpleType name="ST_GeomGuideFormula">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
<xsd:complexType name="CT_GeomGuide">
<xsd:attribute name="name" type="ST_GeomGuideName" use="required"/>
<xsd:attribute name="fmla" type="ST_GeomGuideFormula" use="required"/>
(continues on next page)
<xsd:complexType name="CT_GeomGuideList">
<xsd:sequence>
<xsd:element name="gd" type="CT_GeomGuide" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name="ST_AdjCoordinate">
<xsd:union memberTypes="ST_Coordinate ST_GeomGuideName"/>
</xsd:simpleType>
<xsd:simpleType name="ST_AdjCoordinate">
<xsd:union memberTypes="ST_Coordinate ST_GeomGuideName"/>
</xsd:simpleType>
<xsd:simpleType name="ST_PositiveCoordinate">
<xsd:restriction base="xsd:long">
<xsd:minInclusive value="0"/>
<xsd:maxInclusive value="27273042316900"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_Coordinate">
<xsd:union memberTypes="ST_CoordinateUnqualified s:ST_UniversalMeasure"/>
</xsd:simpleType>
<xsd:simpleType name="ST_CoordinateUnqualified">
<xsd:restriction base="xsd:long">
<xsd:minInclusive value="-27273042329600"/>
<xsd:maxInclusive value="27273042316900"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_UniversalMeasure">
<xsd:restriction base="xsd:string">
<xsd:pattern value="-?[0-9]+(\.[0-9]+)?(mm|cm|in|pt|pc|pi)"/>
</xsd:restriction>
</xsd:simpleType>
Line/Connector Shape
Lines are a sub-category of auto shape that differ in certain properties and behaviors. In particular, they have a start
point and end point in addition to extents (left, top, width, height).
Connectors are based on the <p:cxnSp> element and have one of a handful of different preset geometry values, such
as line. Freeform connectors, despite the name, are not connectors, and are a custom geometry shape based on the
p:sp element.
Connectors can be “connected” to an auto shape such that a connected end point remains connected when the auto
shape is moved. This relies on a concept of “connection points” on the auto shape. These connections points are preset
features of the auto shape, similar to how adjustment points are pre-defined. Connection points are identified by index.
Connector shapes do not have a text frame and cannot have text that is anchored to the shape.
Design Issues
• See how PowerPoint interprets the remaining connector types like bentConnector2
Unimplemented Scope
• Connector.shape_type = MSO_LINE
• BaseShape.is_connector + ConnectorShape.is_connector (not yet implemented)
• [ ] see how a connector returns for connector.AutoShapeType in MS API.
PowerPoint behaviors
• Once connected, moving the target shape moves the connector the same amount, however, the relative position of
the connector end-point is not adjusted to align to the connection point; rather, the relative offset is maintained.
Also, when the connector is selected, the connected point is highlighted in red, even though it is not coincident
with the connection point.
• Arrow heads are not a direct property of a connector, despite perhaps appearing so in the UI. Line endings are a
property of the line style of the connector (and other shapes).
MS API
Protocols
Properties:
>>> connector.is_connector
True
>>> connector.type
MSO_SHAPE_TYPE.LINE
>>> connector.start_x
914400
>>> connector.end_y
914400
>>> connector.adjustments
<pptx.shapes.shared.Adjustments instance at 0x123456789>
Creation protocol:
MS API Protocol
Behaviors
UI display
Connector shapes do not display a bounding box when selected in the UI. Rather their start and end points are high-
lighted with a small gray circle that can be moved. If there is an adjustment, such as a mid-point, it is indicated in the
normal way with a small yellow diamond. These endpoints and adjustment diamond cannot be individually selected.
Naming
What determines the name automatically applied to a line or connector shape? Can it change after shape creation, for
example by applying an arrowhead?
Enumerations
MsoConnectorType
http://msdn.microsoft.com/en-us/library/office/ff860918(v=office.15).aspx
Specimen XML
<p:cxnSp>
<p:nvCxnSpPr>
<p:cNvPr id="3" name="Straight Connector 2"/>
<p:cNvCxnSpPr/>
<p:nvPr/>
</p:nvCxnSpPr>
<p:spPr>
<a:xfrm>
<a:off x="611560" y="620688"/>
<a:ext cx="914400" cy="914400"/>
</a:xfrm>
<a:prstGeom prst="line">
(continues on next page)
<p:cxnSp>
<p:nvCxnSpPr>
<p:cNvPr id="7" name="Straight Arrow Connector 6"/>
<p:cNvCxnSpPr/>
<p:nvPr/>
</p:nvCxnSpPr>
<p:spPr>
<a:xfrm>
<a:off x="950964" y="1673307"/>
<a:ext cx="1257921" cy="0"/>
</a:xfrm>
<a:prstGeom prst="straightConnector1">
<a:avLst/>
</a:prstGeom>
<a:ln>
<a:tailEnd type="arrow"/>
</a:ln>
</p:spPr>
<p:style>
<a:lnRef idx="2">
<a:schemeClr val="accent1"/>
</a:lnRef>
<a:fillRef idx="0">
<a:schemeClr val="accent1"/>
</a:fillRef>
<a:effectRef idx="1">
<a:schemeClr val="accent1"/>
</a:effectRef>
<a:fontRef idx="minor">
<a:schemeClr val="tx1"/>
</a:fontRef>
</p:style>
</p:cxnSp>
<p:cxnSp>
<p:nvCxnSpPr>
<p:cNvPr id="9" name="Elbow Connector 8"/>
<p:cNvCxnSpPr/>
<p:nvPr/>
</p:nvCxnSpPr>
<p:spPr>
<a:xfrm>
<a:off x="950964" y="2124739"/>
<a:ext cx="1257921" cy="415317"/>
</a:xfrm>
<a:prstGeom prst="bentConnector3">
<a:avLst/>
</a:prstGeom>
</p:spPr>
<p:style>
<a:lnRef idx="2">
<a:schemeClr val="accent1"/>
</a:lnRef>
<a:fillRef idx="0">
<a:schemeClr val="accent1"/>
</a:fillRef>
<a:effectRef idx="1">
<a:schemeClr val="accent1"/>
</a:effectRef>
<a:fontRef idx="minor">
<a:schemeClr val="tx1"/>
</a:fontRef>
</p:style>
</p:cxnSp>
<p:cxnSp>
<p:nvCxnSpPr>
<p:cNvPr id="11" name="Curved Connector 10"/>
<p:cNvCxnSpPr/>
<p:nvPr/>
</p:nvCxnSpPr>
<p:spPr>
<a:xfrm>
<a:off x="950964" y="2925277"/>
<a:ext cx="1257921" cy="619967"/>
</a:xfrm>
<a:prstGeom prst="curvedConnector3">
<a:avLst/>
</a:prstGeom>
</p:spPr>
<p:style>
<a:lnRef idx="2">
<a:schemeClr val="accent1"/>
</a:lnRef>
<a:fillRef idx="0">
<a:schemeClr val="accent1"/>
</a:fillRef>
<a:effectRef idx="1">
<a:schemeClr val="accent1"/>
(continues on next page)
Freeform connector:
<p:sp>
<p:nvSpPr>
<p:cNvPr id="12" name="Freeform 11"/>
<p:cNvSpPr/>
<p:nvPr/>
</p:nvSpPr>
<p:spPr>
<a:xfrm>
<a:off x="981058" y="4086962"/>
<a:ext cx="1372277" cy="686176"/>
</a:xfrm>
<a:custGeom>
<a:avLst/>
<a:gdLst>
<a:gd name="connsiteX0" fmla="*/ 0 w 1372277"/>
<a:gd name="connsiteY0" fmla="*/ 0 h 686176"/>
<a:gd name="connsiteX1" fmla="*/ 379182 w 1372277"/>
<a:gd name="connsiteY1" fmla="*/ 306973 h 686176"/>
<a:gd name="connsiteX2" fmla="*/ 944945 w 1372277"/>
<a:gd name="connsiteY2" fmla="*/ 48152 h 686176"/>
</a:gdLst>
<a:ahLst/>
<a:cxnLst>
<a:cxn ang="0">
<a:pos x="connsiteX0" y="connsiteY0"/>
</a:cxn>
<a:cxn ang="0">
<a:pos x="connsiteX1" y="connsiteY1"/>
</a:cxn>
<a:cxn ang="0">
<a:pos x="connsiteX2" y="connsiteY2"/>
</a:cxn>
</a:cxnLst>
<a:rect l="l" t="t" r="r" b="b"/>
<a:pathLst>
<a:path w="1372277" h="686176">
<a:moveTo>
<a:pt x="0" y="0"/>
</a:moveTo>
<a:cubicBezTo>
<a:pt x="110845" y="149474"/>
<a:pt x="221691" y="298948"/>
<a:pt x="379182" y="306973"/>
</a:cubicBezTo>
<a:cubicBezTo>
<a:pt x="536673" y="314998"/>
<a:pt x="811529" y="4012"/>
<a:pt x="944945" y="48152"/>
(continues on next page)
Analysis
• The p:style element represents indirection of the connector visual attributes to the theme part.
• What’s up with the p:style element? Does that have to be there? What happens if we just leave that out? Is the
accent1 default universal enough to pop in there without consideration?
• Seems like the most common lines are connectors
• Connectors are a distinct shape type. They are very similar to regular <p:sp>-based auto shapes, but lack a
text frame.
• Hypothesis: There are really two types, connectors and free-form.
– Connectors are based on the <p:cxnSp> element and have a preset geometry (<a:prstGeom> child of
<p:spPr>).
– Free-form lines are based on the <p:sp> element and have a custom geometry (<a:custGeom> child
of <p:spPr>).
• Connectors don’t have a fill. Free-form shapes do. Fill of free-form shapes extends between the line and a
line connecting the end points, whether present or not. Since the lines can cross, this produces some possibly
surprising fill behaviors; there is no clear concept of inside and outside for such a shape.
<xsd:complexType name="CT_GroupShape">
<xsd:sequence>
<xsd:element name="nvGrpSpPr" type="CT_GroupShapeNonVisual"/>
<xsd:element name="grpSpPr" type="a:CT_GroupShapeProperties"/>
(continues on next page)
<xsd:complexType name="CT_Connector">
<xsd:sequence>
<xsd:element name="nvCxnSpPr" type="CT_ConnectorNonVisual"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties"/>
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_ConnectorNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps"/>
<xsd:element name="cNvCxnSpPr" type="a:CT_NonVisualConnectorProperties"/>
<xsd:element name="nvPr" type="CT_ApplicationNonVisualDrawingProps"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Connection">
<xsd:attribute name="id" type="ST_DrawingElementId" use="required"/>
<xsd:attribute name="idx" type="xsd:unsignedInt" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_NonVisualConnectorProperties">
<xsd:sequence>
<xsd:element name="cxnSpLocks" type="CT_ConnectorLocking" minOccurs="0"/>
<xsd:element name="stCxn" type="CT_Connection" minOccurs="0"/>
<xsd:element name="endCxn" type="CT_Connection" minOccurs="0"/>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_ShapeProperties">
<xsd:sequence>
<xsd:element name="xfrm" type="CT_Transform2D"
˓→minOccurs="0"/>
<xsd:group ref="EG_Geometry"
˓→minOccurs="0"/>
<xsd:group ref="EG_FillProperties"
˓→minOccurs="0"/>
<xsd:group ref="EG_EffectProperties"
˓→minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="bwMode" type="ST_BlackWhiteMode" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_ShapeStyle">
<xsd:sequence>
<xsd:element name="lnRef" type="CT_StyleMatrixReference"/>
<xsd:element name="fillRef" type="CT_StyleMatrixReference"/>
<xsd:element name="effectRef" type="CT_StyleMatrixReference"/>
<xsd:element name="fontRef" type="CT_FontReference"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_StyleMatrixReference">
<xsd:choice minOccurs="0">
<xsd:element name="scrgbClr" type="CT_ScRgbColor"/>
<xsd:element name="srgbClr" type="CT_SRgbColor"/>
<xsd:element name="hslClr" type="CT_HslColor"/>
<xsd:element name="sysClr" type="CT_SystemColor"/>
<xsd:element name="schemeClr" type="CT_SchemeColor"/>
<xsd:element name="prstClr" type="CT_PresetColor"/>
</xsd:choice>
<xsd:attribute name="idx" type="ST_StyleMatrixColumnIndex" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_FontReference">
<xsd:choice minOccurs="0">
<xsd:element name="scrgbClr" type="CT_ScRgbColor"/>
<xsd:element name="srgbClr" type="CT_SRgbColor"/>
<xsd:element name="hslClr" type="CT_HslColor"/>
<xsd:element name="sysClr" type="CT_SystemColor"/>
<xsd:element name="schemeClr" type="CT_SchemeColor"/>
<xsd:element name="prstClr" type="CT_PresetColor"/>
</xsd:choice>
<xsd:attribute name="idx" type="ST_FontCollectionIndex" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_DrawingElementId">
<xsd:restriction base="xsd:unsignedInt"/>
</xsd:simpleType>
<xsd:simpleType name="ST_ShapeType">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="line"/>
<xsd:enumeration value="straightConnector1"/>
<xsd:enumeration value="bentConnector2"/>
<xsd:enumeration value="bentConnector3"/>
<xsd:enumeration value="bentConnector4"/>
<xsd:enumeration value="bentConnector5"/>
<xsd:enumeration value="curvedConnector2"/>
<xsd:enumeration value="curvedConnector3"/>
<xsd:enumeration value="curvedConnector4"/>
<xsd:enumeration value="curvedConnector5"/>
(continues on next page)
Picture
Protocol
Add a picture:
>>> picture.crop_right
None
>>> picture.crop_right = 25000 # ---in 1000ths of a percent
>>> picture.crop_right
25000.0
XML Specimens
<p:pic>
<p:nvPicPr>
<p:cNvPr id="2" name="Picture 1" descr="sonic.gif"/>
<p:cNvPicPr>
<a:picLocks noChangeAspect="1"/>
</p:cNvPicPr>
<p:nvPr/>
</p:nvPicPr>
<p:blipFill>
<a:blip r:embed="rId2">
<a:extLst>
<a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}">
<a14:useLocalDpi
xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main"
val="0"/>
</a:ext>
</a:extLst>
</a:blip>
<a:stretch>
<a:fillRect/>
</a:stretch>
</p:blipFill>
<p:spPr>
<a:xfrm>
(continues on next page)
<p:blipFill rotWithShape="1">
<a:blip r:embed="rId2"/>
<a:srcRect l="9330" t="15904" r="21873" b="28227"/>
<a:stretch/>
</p:blipFill>
Schema excerpt
<xsd:complexType name="CT_Picture">
<xsd:sequence>
<xsd:element name="nvPicPr" type="CT_PictureNonVisual"/>
<xsd:element name="blipFill" type="a:CT_BlipFillProperties"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties"/>
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_PictureNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps"/>
<xsd:element name="cNvPicPr" type="a:CT_NonVisualPictureProperties"/>
<xsd:element name="nvPr" type="CT_ApplicationNonVisualDrawingProps"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_BlipFillProperties">
<xsd:sequence>
<xsd:element name="blip" type="CT_Blip" minOccurs="0"/>
<xsd:element name="srcRect" type="CT_RelativeRect" minOccurs="0"/>
<xsd:group ref="EG_FillModeProperties" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="dpi" type="xsd:unsignedInt"/>
<xsd:attribute name="rotWithShape" type="xsd:boolean"/>
</xsd:complexType>
<xsd:complexType name="CT_ShapeProperties">
<xsd:sequence>
<xsd:element name="xfrm" type="CT_Transform2D" minOccurs="0"/>
<xsd:group ref="EG_Geometry" minOccurs="0"/>
<xsd:group ref="EG_FillProperties" minOccurs="0"/>
<xsd:element name="ln" type="CT_LineProperties" minOccurs="0"/>
<xsd:group ref="EG_EffectProperties" minOccurs="0"/>
(continues on next page)
<xsd:complexType name="CT_ShapeStyle">
<xsd:sequence>
<xsd:element name="lnRef" type="CT_StyleMatrixReference"/>
<xsd:element name="fillRef" type="CT_StyleMatrixReference"/>
<xsd:element name="effectRef" type="CT_StyleMatrixReference"/>
<xsd:element name="fontRef" type="CT_FontReference"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_ApplicationNonVisualDrawingProps">
<xsd:sequence>
<xsd:element name="ph" type="CT_Placeholder" minOccurs="0"/>
<xsd:group ref="a:EG_Media" minOccurs="0"/>
<xsd:element name="custDataLst" type="CT_CustomerDataList" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="isPhoto" type="xsd:boolean" default="false"/>
<xsd:attribute name="userDrawn" type="xsd:boolean" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_Blip">
<xsd:sequence>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="alphaBiLevel" type="CT_AlphaBiLevelEffect"/>
<xsd:element name="alphaCeiling" type="CT_AlphaCeilingEffect"/>
<xsd:element name="alphaFloor" type="CT_AlphaFloorEffect"/>
<xsd:element name="alphaInv" type="CT_AlphaInverseEffect"/>
<xsd:element name="alphaMod" type="CT_AlphaModulateEffect"/>
<xsd:element name="alphaModFix" type="CT_AlphaModulateFixedEffect"/>
<xsd:element name="alphaRepl" type="CT_AlphaReplaceEffect"/>
<xsd:element name="biLevel" type="CT_BiLevelEffect"/>
<xsd:element name="blur" type="CT_BlurEffect"/>
<xsd:element name="clrChange" type="CT_ColorChangeEffect"/>
<xsd:element name="clrRepl" type="CT_ColorReplaceEffect"/>
<xsd:element name="duotone" type="CT_DuotoneEffect"/>
<xsd:element name="fillOverlay" type="CT_FillOverlayEffect"/>
<xsd:element name="grayscl" type="CT_GrayscaleEffect"/>
<xsd:element name="hsl" type="CT_HSLEffect"/>
<xsd:element name="lum" type="CT_LuminanceEffect"/>
<xsd:element name="tint" type="CT_TintEffect"/>
</xsd:choice>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attributeGroup ref="AG_Blob"/>
<xsd:attribute name="cstate" type="ST_BlipCompression" default="none"/>
</xsd:complexType>
<xsd:complexType name="CT_NonVisualDrawingProps">
<xsd:sequence>
<xsd:element name="hlinkClick" type="CT_Hyperlink" minOccurs="0"/>
(continues on next page)
<xsd:complexType name="CT_NonVisualPictureProperties">
<xsd:sequence>
<xsd:element name="picLocks" type="CT_PictureLocking" minOccurs="0"/>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="preferRelativeResize" type="xsd:boolean" default="true"/>
</xsd:complexType>
<xsd:complexType name="CT_Point2D">
<xsd:attribute name="x" type="ST_Coordinate" use="required"/>
<xsd:attribute name="y" type="ST_Coordinate" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_PositiveSize2D">
<xsd:attribute name="cx" type="ST_PositiveCoordinate" use="required"/>
<xsd:attribute name="cy" type="ST_PositiveCoordinate" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_RelativeRect">
<xsd:attribute name="l" type="ST_Percentage" default="0%"/>
<xsd:attribute name="t" type="ST_Percentage" default="0%"/>
<xsd:attribute name="r" type="ST_Percentage" default="0%"/>
<xsd:attribute name="b" type="ST_Percentage" default="0%"/>
</xsd:complexType>
<xsd:complexType name="CT_StretchInfoProperties">
<xsd:sequence>
<xsd:element name="fillRect" type="CT_RelativeRect" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_Transform2D">
<xsd:sequence>
<xsd:element name="off" type="CT_Point2D" minOccurs="0"/>
<xsd:element name="ext" type="CT_PositiveSize2D" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="rot" type="ST_Angle" default="0"/>
<xsd:attribute name="flipH" type="xsd:boolean" default="false"/>
<xsd:attribute name="flipV" type="xsd:boolean" default="false"/>
</xsd:complexType>
<xsd:attributeGroup name="AG_Blob">
<xsd:attribute ref="r:embed" default=""/>
<xsd:attribute ref="r:link" default=""/>
</xsd:attributeGroup>
<xsd:group name="EG_EffectProperties">
(continues on next page)
<xsd:group name="EG_FillModeProperties">
<xsd:choice>
<xsd:element name="tile" type="CT_TileInfoProperties"/>
<xsd:element name="stretch" type="CT_StretchInfoProperties"/>
</xsd:choice>
</xsd:group>
<xsd:group name="EG_FillProperties">
<xsd:choice>
<xsd:element name="noFill" type="CT_NoFillProperties"/>
<xsd:element name="solidFill" type="CT_SolidColorFillProperties"/>
<xsd:element name="gradFill" type="CT_GradientFillProperties"/>
<xsd:element name="blipFill" type="CT_BlipFillProperties"/>
<xsd:element name="pattFill" type="CT_PatternFillProperties"/>
<xsd:element name="grpFill" type="CT_GroupFillProperties"/>
</xsd:choice>
</xsd:group>
<xsd:group name="EG_Geometry">
<xsd:choice>
<xsd:element name="custGeom" type="CT_CustomGeometry2D"/>
<xsd:element name="prstGeom" type="CT_PresetGeometry2D"/>
</xsd:choice>
</xsd:group>
<xsd:group name="EG_Media">
<xsd:choice>
<xsd:element name="audioCd" type="CT_AudioCD"/>
<xsd:element name="wavAudioFile" type="CT_EmbeddedWAVAudioFile"/>
<xsd:element name="audioFile" type="CT_AudioFile"/>
<xsd:element name="videoFile" type="CT_VideoFile"/>
<xsd:element name="quickTimeFile" type="CT_QuickTimeFile"/>
</xsd:choice>
</xsd:group>
Graphic Frame
A graphic frame is a shape that contains a graphical object such as a table, chart, or SmartArt object. While often
referred to as a shape in common parlance, a table or chart is not a shape. The graphic frame container is the shape
and the table, chart, or SmartArt object is a DrawingML (DML) object within it.
A chart, for example, is a shared DML object. It can appear in a Word, Excel, or PowerPoint file, virtually unchanged
except for the container in which it appears.
The graphical content is contained in the p:graphicFrame/a:graphic/a:graphicData grandchild ele-
ment. The type of graphical object contained is specified by an XML namespace contained in the uri attribute
of the <a:graphicData> element. The graphical content may appear directly in the <p:graphicFrame> ele-
ment or may be in a separate part related by an rId. XML for a table is embedded inline. Chart XML is stored in a
related Chart part.
Protocol
Specimen XML
<p:graphicFrame>
<p:nvGraphicFramePr>
<p:cNvPr id="2" name="Table 1"/>
<p:cNvGraphicFramePr>
<a:graphicFrameLocks noGrp="1"/>
</p:cNvGraphicFramePr>
<p:nvPr/>
</p:nvGraphicFramePr>
<p:xfrm>
<a:off x="1524000" y="1397000"/>
<a:ext cx="6096000" cy="741680"/>
</p:xfrm>
<a:graphic>
<a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/table">
<a:tbl>
... remaining table XML ...
</a:tbl>
</a:graphicData>
</a:graphic>
</p:graphicFrame>
<p:graphicFrame>
<p:nvGraphicFramePr>
<p:cNvPr id="2" name="Chart 1"/>
<p:cNvGraphicFramePr/>
<p:nvPr>
<p:extLst>
(continues on next page)
r:id="rId2"/>
</a:graphicData>
</a:graphic>
</p:graphicFrame>
<xsd:complexType name="CT_GraphicalObject">
<xsd:sequence>
<xsd:element name="graphicData" type="CT_GraphicalObjectData"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_GraphicalObjectData">
<xsd:sequence>
<xsd:any minOccurs="0" maxOccurs="unbounded" processContents="strict"/>
</xsd:sequence>
<xsd:attribute name="uri" type="xsd:token" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_NonVisualDrawingProps">
<xsd:sequence>
<xsd:element name="hlinkClick" type="CT_Hyperlink" minOccurs="0"/>
<xsd:element name="hlinkHover" type="CT_Hyperlink" minOccurs="0"/>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="id" type="ST_DrawingElementId" use="required"/>
<xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="descr" type="xsd:string" default=""/>
<xsd:attribute name="hidden" type="xsd:boolean" default="false"/>
<xsd:attribute name="title" type="xsd:string" default=""/>
</xsd:complexType>
<xsd:complexType name="CT_NonVisualGraphicFrameProperties">
<xsd:sequence>
<xsd:element name="graphicFrameLocks" type="CT_GraphicalObjectFrameLocking"
˓→minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_GraphicalObjectFrameLocking">
<xsd:sequence>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="noGrp" type="xsd:boolean" default="false"/>
<xsd:attribute name="noDrilldown" type="xsd:boolean" default="false"/>
<xsd:attribute name="noSelect" type="xsd:boolean" default="false"/>
<xsd:attribute name="noChangeAspect" type="xsd:boolean" default="false"/>
<xsd:attribute name="noMove" type="xsd:boolean" default="false"/>
<xsd:attribute name="noResize" type="xsd:boolean" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_ApplicationNonVisualDrawingProps">
(continues on next page)
<xsd:group name="EG_Media">
<xsd:choice>
<xsd:element name="audioCd" type="CT_AudioCD"/>
<xsd:element name="wavAudioFile" type="CT_EmbeddedWAVAudioFile"/>
<xsd:element name="audioFile" type="CT_AudioFile"/>
<xsd:element name="videoFile" type="CT_VideoFile"/>
<xsd:element name="quickTimeFile" type="CT_QuickTimeFile"/>
</xsd:choice>
</xsd:group>
An embedded Excel worksheet can appear as a shape on a slide. The shape itself is a graphics-frame, in which the
worksheet “file” is embedded. The Excel binary appears as an additional part in the package. Other file types such as
DOCX and PDF can also be embedded in a similar way.
Support for different file (object) types is OS dependent. For example, there is no support for embedded PPTX objects
on MacOS although there is for Windows. Excel (XLSX) and Word (DOCX) are the two common denominators.
Proposed protocol
PowerPoint UI behaviors
• Insert a blank object. PowerPoint allows a “new”, blank OLE object to be inserted by selecting the type. The
available types appear to be determined by a set of “registered” OLE server applications.
This behavior seems quite bound to some user interaction to fill out the object and in any case is outside the
abilities of python-pptx running on an arbitrary OS. This behavior will have no counterpart in python-pptx. Only
the “insert-from-file” mode will be available in python-pptx.
• Auto-detect ‘progId‘ from file. When the “insert-from-file” option is chosen, PowerPoint automatically detects
the progId (str OLE server identifier, intuitively “file-type”) for the inserted file.
This would be a lot of work for python-pptx to accomplish and in the end would be partial at best. The base
case would be that python-pptx requires progId to be specified by the caller. python-pptx will provide an Enum
that provides ready access to common str progId cases like Excel Worksheet, Word Document, and PowerPoint
Presentation. Other cases could be resolved by experimentation and inspecting the XML to determine the
appropriate str progId value.
• Show as preview. PowerPoint allows the option to show the embedded object as either a “preview” of the
content or as an icon. The preview is an image (EMF for XLSX and perhaps other MS Office applications) and I
expect it is provided by the OLE server application (Excel in the XLSX case) which renders to an image instead
of rendering to the screen.
python-pptx has no access to an OLE server and therefore cannot request this image. Only the “display as
icon” mode will be supported in python-pptx. For this reason, the python-pptx call will have no display_as_icon
parameter and that “value” will always be True.
• User-selectable and partially-generated icon. When “display-as-icon” is selected, PowerPoint generates a
composite icon that combines a graphical icon and a caption. Together, these typically look like a file icon that
appears on the user’s desktop, except the file-name portion is a generic file-type name like “Microsoft Excel
Workbook”.
The icon portion can be replaced with an arbitrary icon selected by the user (Windows only). The icon can be
selected from a .ico file or an icon library or from the resource area of an .exe file.
The resulting image in the PPTX package is a Windows Meta File (WMF/EMF), a vector format, perhaps to
allow smooth scaling.
In the general case (i.e. non-Windows OS), python-pptx has neither the option of extracting icons from an
arbitrary icon or resource library or
• Link to file rather than embed. When inserting an object from a file, a user can choose to link the selected file
rather than embed it. This option appears in the Windows version only.
The only difference in the slide XML is the appearance of a <p:link> element under <p:oleObj> rather than a
<p:embed> element. In this case, the relationship referred to by r:id attribute of p:oleObj is an external link to
the target file and no OLE object part is added to the PPTX package.
• Auto-position and size. In the PowerPoint UI, the OLE object is inserted at a fixed size and in a default location.
Afterward the shape can be repositioned and resized to suit. In the API, the position and size are specified in the
call.
MS API Protocol
Shapes.AddOLEObject(
Left, Top, Width, Height,
ClassName,
FileName,
(continues on next page)
• Left, Top, Width and Height specify the position and size of the graphic-frame object. They also specify the
size of the icon image when display_as_icon is True and the size of the preview image when display_as_icon is
False or omitted. These are all optional, and are determined by PowerPoint if not specified. I believe the shape
is placed centered in the slide if the position is not specified and the size is determined by the icon or preview
graphic if not specified.
PowerPoint updates these values in the icon-image element to track those of the graphic-frame shape when the
user changes the size of the graphic-frame shape, but it seems to ignore these values when they don’t agree.
• ClassName identifies the “file-type” or more precisely, the OLE server (program) used to “open” the embedded
or linked file. This is used only when a new, empty object is being added because otherwise PowerPoint derives
this from the file specified with FileName
This can be either the OLE long class name or the ProgID for the object that’s to be created, but a class-
name ends up being converted to a ProgID. Either the ClassName or FileName argument for the object must
be specified, but not both. ClassName triggers the “insert-newly-created-object” mode and FileName triggers
“insert-existing-object” mode.
• DisplayAsIcon (optional boolean) determines whether the OLE object will be displayed as an icon or as a
“preview”. The default is False.
• IconFileName allows the user to specify an icon file containing the icon to display when DisplayAsIcon is True.
If not specified, a default icon for the OLE class is used. Note that this file can contain a collection of images,
which is why the IconIndex parameter is available. These icon files are Windows specific and would not typically
be found in other operating systems.
• IconIndex specifies the index of the desired icon within IconFileName. The first icon in the file has the index
number 0 (zero). If an icon with the given index number doesn’t exist in IconFileName, the icon with the index
number 1 (the second icon in the file) is used. The default value is 0 (zero).
• IconLabel is a str label (caption) to be displayed beneath the icon. By default, this is like “Microsoft Excel
Worksheet”. This caption is integrated into the specified “display-as-icon” image.
• Link is a boolean flag that determines whether the OLE object will be linked to the file from which it was created
(rather than embedded). If you specified a value for ClassName, this argument must be msoFalse (linking is not
an option in “insert-newly-created-object” mode).
Candiate protocol
SlideShapes.add_ole_object(
object_file,
prog_id,
left,
top,
width=None,
height=None,
icon=None,
link=False,
)
python-pptx only supports adding an OLE object in “display-as-icon” mode. It has no way of soliciting a preview
image from an OLE server application, so that option is not practical for us.
• object_file is the file containing the object to be inserted. It may be either a str path to the file or a (binary)
file-like object (typically io.Bytes) containing the bytes of the file and implementing file-object semantics like
.read() and .seek().
• prog_id is a PROG_ID Enum member or str identifier like “Excel.Sheet.12” specifying the “type” of the object
in terms of what application is used to “open” it. In Microsoft parlance, this identifies the OLE server called
upon to operate on this object.
The pptx.enum.shapes.PROG_ID enumeration defines these values for common cases like an Excel workbook,
an Word document, or another PowerPoint presentation. Probably we should also include PDFs and any other
common cases we can think of.
A regular str value can be discovered by inspecting the XML of an example presentation and these will work
just the same as a PROG_ID Enum value, allowing ready expansion to other OLE object types.
I expect that a file of any type could be included, even if it doesn’t have an OLE server application and it
could then at least be accessed via python-pptx, although I don’t suppose it would do anything useful from the
PowerPoint UI. In any case, I don’t believe it would raise an error and there wouldn’t be anything we could (or
would probably want) to do to stop someone from doing that.
• left and top are each an Emu object (or an int interpreted as Emu) and specify the position of the inserted-object
shape.
• width and height are optional Emu/int objects and together specify the size of the graphic-frame object. Their
use is not required and perhaps even discouraged unless the defaults of 1.00” (914400 EMU) wide and .84”
(771480 EMU) tall do not suit for some reason, perhaps because the provided icon image is a non-standard size.
The default size is that when a user inserts an object displayed as an icon in the PowerPoint UI and I at least
have been unable to make it look better by resizing it.
• icon is an arbitrary image that appears in the graphic-frame object in lieu of the inserted object. It is optional,
because a default icon is provided for each of the members of PROG_ID and this image need not be specified
when prog_id is an instance of PROG_ID. Like an image object used in SlideShapes.add_picture(), this object
can be either a str path or a file-like object (typically io.BytesIO) containing the image.
This parameter is technically optional, but is required when prog_id is not an member of PROG_ID (because
in that case we have no default icon available). The caller can always specify a custom icon image, even when
inserting an object type available in PROG_ID. In that case, the image provided is used instead of the default
icon.
• link is a boolean indicating the object should be linked rather than embedded. Linking probably only works in
a Windows environment. This option may not be implemented in the initial release and this parameter will not
appear in that case.
>>> shapes = slide.shapes
>>> embedded_xlsx_shape = shapes.AddOLEObject(left, top, width, height, file_name)
XML specimens
relationships:
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="x" Type="http://schemas.openxmlformats.org/officeDocument/2006/
˓→relationships/image" Target="../media/image4.emf"/>
</Relationships>
</a:ext>
</a:extLst>
</p:cNvPr>
<p:cNvGraphicFramePr>
<a:graphicFrameLocks noChangeAspect="1"/>
</p:cNvGraphicFramePr>
<p:nvPr>
<p:extLst>
<p:ext uri="{D42A27DB-BD31-4B8C-83A1-F6EECF244321}">
<p14:modId xmlns:p14="http://schemas.microsoft.com/office/powerpoint/2010/
˓→main" val="2099550745"/>
</p:ext>
</p:extLst>
</p:nvPr>
</p:nvGraphicFramePr>
<p:xfrm>
<a:off x="1792101" y="2202989"/>
<a:ext cx="659686" cy="1371600"/>
</p:xfrm>
<a:graphic>
<a:graphicData uri="http://schemas.openxmlformats.org/presentationml/2006/ole">
<mc:AlternateContent xmlns:mc="http://schemas.openxmlformats.org/markup-
˓→compatibility/2006">
<p:embed/>
</p:oleObj>
</mc:Choice>
<mc:Fallback>
<p:oleObj name="Worksheet" showAsIcon="1" r:id="rId4" imgW="381148" imgH=
˓→"792690" progId="Excel.Sheet.12">
<p:embed/>
<p:pic>
<p:nvPicPr>
<p:cNvPr id="0" name=""/>
<p:cNvPicPr/>
<p:nvPr/>
</p:nvPicPr>
<p:blipFill>
(continues on next page)
<xsd:complexType name="CT_GraphicalObjectFrame">
<xsd:sequence>
<xsd:element name="nvGraphicFramePr" type="CT_GraphicalObjectFrameNonVisual"/>
<xsd:element name="xfrm" type="a:CT_Transform2D"/>
<xsd:element ref="a:graphic"/> <!-- type="CT_GraphicalObject" -->
<xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="bwMode" type="a:ST_BlackWhiteMode"/>
</xsd:complexType>
<xsd:complexType name="CT_GraphicalObjectFrameNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps"/>
<xsd:element name="cNvGraphicFramePr" type="a:CT_NonVisualGraphicFrameProperties"/
˓→>
<xsd:complexType name="CT_NonVisualGraphicFrameProperties">
<xsd:sequence>
<xsd:element name="graphicFrameLocks" type="CT_GraphicalObjectFrameLocking"
˓→minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_GraphicalObjectFrameLocking">
<xsd:sequence>
(continues on next page)
<xsd:complexType name="CT_GraphicalObject">
<xsd:sequence>
<xsd:element name="graphicData" type="CT_GraphicalObjectData"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_GraphicalObjectData">
<xsd:sequence>
<xsd:any minOccurs="0" maxOccurs="unbounded" processContents="strict"/>
</xsd:sequence>
<!-- contains "http://schemas.openxmlformats.org/presentationml/2006/ole" for an
OLE-object graphic-frame -->
<xsd:attribute name="uri" type="xsd:token" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_OleObject">
<xsd:sequence>
<xsd:choice minOccurs="1" maxOccurs="1">
<xsd:element name="embed" type="CT_OleObjectEmbed"/>
<xsd:element name="link" type="CT_OleObjectLink"/>
</xsd:choice>
<xsd:element name="pic" type="CT_Picture" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="spid" type="a:ST_ShapeID" use="optional"/>
<xsd:attribute name="name" type="xsd:string" use="optional" default=""/>
<xsd:attribute name="showAsIcon" type="xsd:boolean" use="optional" default="false"/>
<xsd:attribute ref="r:id" use="optional"/>
<xsd:attribute name="imgW" type="a:ST_PositiveCoordinate32" use="optional"/>
<xsd:attribute name="imgH" type="a:ST_PositiveCoordinate32" use="optional"/>
<xsd:attribute name="progId" type="xsd:string" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_OleObjectEmbed">
<xsd:sequence>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="followColorScheme" type="ST_OleObjectFollowColorScheme" use=
˓→"optional"
default="none"/>
</xsd:complexType>
Movie
PowerPoint allows a video to be inserted into a slide and run in slide show mode. In the PowerPoint UI, a shape of
this type is called a movie.
A movie is implemented as a variant form of a p:pic element, which makes it closely related to a Picture object. This
close relationship makes sense, because a movie acts very much like an image when it is not playing and the two
shapes therefore share much of their behavior. When not playing, a movie shape displays a static image, called a
poster frame.
Candidate Protocol
A video can be added to a slide by specifying a video file, position, size, and optional poster frame:
>>> movie
<pptx.shape.picture.Movie object @ 0x12345678>
>>> movie.shape_type
MSO.MEDIA
>>> movie.media_type
PP_MEDIA_TYPE.MOVIE
>>> movie.media_format
<pptx.shape.picture.MediaFormat object @ 0x123456ab>
Animation/timing resources
MS API
• Slide.Timeline https://msdn.microsoft.com/en-us/library/office/ff745382.aspx
• TimeLine Object https://msdn.microsoft.com/en-us/library/office/ff743965.aspx
• Shapes.AddMediaObject() (deprecated in PowerPoint 2013, see AddMediaObject2) https://msdn.microsoft.
com/EN-US/library/office/ff745385.aspx
• Shapes.AddMediaObject2() https://msdn.microsoft.com/en-us/library/office/ff744080.aspx
• MediaFormat https://msdn.microsoft.com/en-us/library/office/ff745983.aspx
Enumerations
PP_MEDIA_TYPE - https://msdn.microsoft.com/en-us/library/office/ff746008.aspx
PP_MEDIA_TYPE.MOVIE 3 Movie
PP_MEDIA_TYPE.SOUND 2 Sound
PP_MEDIA_TYPE.OTHER 1 Others
PP_MEDIA_TYPE.MIXED -2 Mixed
Click Behavior
The video’s “play on click” behavior in slideshow mode is implemented by the use of a <p:timing> element in the
<p:sld> element. No “play” button or slider control appears when this element is not present.
Poster Frame
A poster frame is the static image displayed in the video location when the video is not playing. Each image that
appears on the YouTube home page representing a video is an example of a poster frame.
The poster frame is perhaps most frequently a frame from the video itself. In some contexts, the first frame is used by
default. The poster frame can be undefined, or empty, and it can also be an unrelated image.
Some of the example videos for this feature get a poster frame upon insertion; however at least one does not. In that
case, a media “speaker” icon (stretched to fit) is shown instead.
XML Semantics
• id= of p:cTn element just needs to be unique among p:cTn elements, apparently.
Example XML
<p:pic>
<p:nvPicPr>
<p:cNvPr id="6" name="video-filename.mp4">
(continues on next page)
<p:sld
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"
>
<p:cSld>
<!-- ... -->
</p:cSld>
<p:clrMapOvr>
<a:masterClrMapping/>
</p:clrMapOvr>
<p:timing>
<p:tnLst>
<p:par>
<p:cTn xmlns:p14="http://schemas.microsoft.com/office/powerpoint/2010/main"
˓→id="1" dur="indefinite" restart="never" nodeType="tmRoot">
<p:childTnLst>
<p:video>
<p:cMediaNode vol="80000">
<p:cTn id="7" fill="hold" display="0">
<p:stCondLst>
<p:cond delay="indefinite"/>
</p:stCondLst>
</p:cTn>
<p:tgtEl>
<p:spTgt spid="3"/>
</p:tgtEl>
</p:cMediaNode>
</p:video>
</p:childTnLst>
</p:cTn>
</p:par>
</p:tnLst>
</p:timing>
</p:sld>
<p:timing>
<p:tnLst>
<p:par>
<p:cTn xmlns:p14="http://schemas.microsoft.com/office/powerpoint/2010/main" id=
˓→"1" dur="indefinite" restart="never" nodeType="tmRoot">
<p:childTnLst>
<p:seq concurrent="1" nextAc="seek">
<p:cTn id="2" restart="whenNotActive" fill="hold" evtFilter="cancelBubble
˓→" nodeType="interactiveSeq">
<p:stCondLst>
<p:cond evt="onClick" delay="0">
<p:tgtEl>
(continues on next page)
<p:stCondLst>
<p:cond delay="0"/>
</p:stCondLst>
<p:childTnLst>
<p:cmd type="call" cmd="togglePause">
<p:cBhvr>
<p:cTn id="6" dur="1" fill="hold"/>
<p:tgtEl>
<p:spTgt spid="3"/>
</p:tgtEl>
</p:cBhvr>
</p:cmd>
</p:childTnLst>
</p:cTn>
</p:par>
</p:childTnLst>
</p:cTn>
</p:par>
</p:childTnLst>
</p:cTn>
</p:par>
</p:childTnLst>
</p:cTn>
<p:nextCondLst>
<p:cond evt="onClick" delay="0">
<p:tgtEl>
<p:spTgt spid="3"/>
</p:tgtEl>
</p:cond>
</p:nextCondLst>
</p:seq>
<p:video>
<p:cMediaNode vol="80000">
<p:cTn id="7" fill="hold" display="0">
(continues on next page)
<p:stCondLst>
<p:cond evt="onClick" delay="0">
<p:tgtEl>
<p:spTgt spid="4"/>
</p:tgtEl>
</p:cond>
</p:stCondLst>
<p:endSync evt="end" delay="0">
<p:rtn val="all"/>
</p:endSync>
<p:childTnLst>
<p:par>
<p:cTn id="9" fill="hold">
<p:stCondLst>
<p:cond delay="0"/>
</p:stCondLst>
<p:childTnLst>
<p:par>
<p:cTn id="10" fill="hold">
<p:stCondLst>
<p:cond delay="0"/>
</p:stCondLst>
<p:childTnLst>
<p:par>
<p:cTn id="11" presetID="2" presetClass="mediacall"
˓→presetSubtype="0" fill="hold" nodeType="clickEffect">
<p:stCondLst>
<p:cond delay="0"/>
</p:stCondLst>
<p:childTnLst>
<p:cmd type="call" cmd="togglePause">
<p:cBhvr>
<p:cTn id="12" dur="1" fill="hold"/>
<p:tgtEl>
<p:spTgt spid="4"/>
</p:tgtEl>
</p:cBhvr>
</p:cmd>
</p:childTnLst>
</p:cTn>
</p:par>
</p:childTnLst>
</p:cTn>
</p:par>
</p:childTnLst>
(continues on next page)
<!--slide{n}.xml.rels-->
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1"
Type="http://schemas.microsoft.com/office/2007/relationships/media"
Target="../media/media1.mp4"/>
<Relationship Id="rId2"
Type="http://sc.../officeDocument/2006/relationships/video"
Target="../media/media1.mp4"/>
<Relationship Id="rId3"
Type="http://sc.../officeDocument/2006/relationships/slideLayout"
Target="../slideLayouts/slideLayout1.xml"/>
<!-- this one is the poster frame -->
<Relationship Id="rId4"
Type="http://sc.../officeDocument/2006/relationships/image"
Target="../media/image1.png"/>
</Relationships>
<!--[Content_Types].xml-->
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<!-- ... -->
<Default Extension="mp4" ContentType="video/unknown"/>
<Default Extension="png" ContentType="image/png"/>
(continues on next page)
p:video element
XML Semantics
<xsd:complexType name="CT_PictureNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps" minOccurs=
˓→"1" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_NonVisualDrawingProps">
<xsd:sequence>
<xsd:element name="hlinkClick" type="CT_Hyperlink" minOccurs="0"
˓→maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="id" type="ST_DrawingElementId" use="required"/>
<xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="descr" type="xsd:string" use="optional" default=""/>
<xsd:attribute name="hidden" type="xsd:boolean" use="optional" default=
˓→"false"/>
<xsd:complexType name="CT_NonVisualPictureProperties">
<xsd:sequence>
<xsd:element name="picLocks" type="CT_PictureLocking" minOccurs="0"
˓→maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="preferRelativeResize" type="xsd:boolean" use="optional"
˓→default="true"/>
</xsd:complexType>
<xsd:complexType name="CT_ApplicationNonVisualDrawingProps">
<xsd:sequence>
<xsd:element name="ph" type="CT_Placeholder" minOccurs="0"
˓→maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="isPhoto" type="xsd:boolean" use="optional" default="false"/>
<xsd:attribute name="userDrawn" type="xsd:boolean" use="optional" default="false"/>
</xsd:complexType>
<xsd:group name="EG_Media">
<xsd:choice>
<xsd:element name="audioCd" type="CT_AudioCD"/>
<xsd:element name="wavAudioFile" type="CT_EmbeddedWAVAudioFile"/>
<xsd:element name="audioFile" type="CT_AudioFile"/>
<xsd:element name="videoFile" type="CT_VideoFile"/>
<xsd:element name="quickTimeFile" type="CT_QuickTimeFile"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="CT_BlipFillProperties">
<xsd:sequence>
<xsd:element name="blip" type="CT_Blip" minOccurs="0"/>
<xsd:element name="srcRect" type="CT_RelativeRect" minOccurs="0"/>
<xsd:group ref="EG_FillModeProperties" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="dpi" type="xsd:unsignedInt" use="optional"/>
<xsd:attribute name="rotWithShape" type="xsd:boolean" use="optional"/>
</xsd:complexType>
</xsd:choice>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"
˓→maxOccurs="1"/>
</xsd:sequence>
<xsd:attributeGroup ref="AG_Blob"/>
<xsd:attribute name="cstate" type="ST_BlipCompression" use="optional" default="none
˓→"/>
</xsd:complexType>
<xsd:attributeGroup name="AG_Blob">
<xsd:attribute ref="r:embed" use="optional" default=""/>
<xsd:attribute ref="r:link" use="optional" default=""/>
</xsd:attributeGroup>
<xsd:group name="EG_FillModeProperties">
<xsd:choice>
<xsd:element name="tile" type="CT_TileInfoProperties" minOccurs="1"
˓→maxOccurs="1"/>
<xsd:complexType name="CT_StretchInfoProperties">
<xsd:sequence>
<xsd:element name="fillRect" type="CT_RelativeRect" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_RelativeRect">
<xsd:attribute name="l" type="ST_Percentage" use="optional" default="0%"/>
<xsd:attribute name="t" type="ST_Percentage" use="optional" default="0%"/>
<xsd:attribute name="r" type="ST_Percentage" use="optional" default="0%"/>
<xsd:attribute name="b" type="ST_Percentage" use="optional" default="0%"/>
</xsd:complexType>
<xsd:complexType name="CT_ShapeProperties">
<xsd:sequence>
<xsd:element name="xfrm" type="CT_Transform2D" minOccurs="0"/>
<xsd:group ref="EG_Geometry" minOccurs="0"/>
<xsd:group ref="EG_FillProperties" minOccurs="0"/>
<xsd:element name="ln" type="CT_LineProperties" minOccurs="0"/>
<xsd:group ref="EG_EffectProperties" minOccurs="0"/>
<xsd:element name="scene3d" type="CT_Scene3D" minOccurs="0"/>
<xsd:element name="sp3d" type="CT_Shape3D" minOccurs="0"/>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="bwMode" type="ST_BlackWhiteMode" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_Transform2D">
<xsd:sequence>
<xsd:element name="off" type="CT_Point2D" minOccurs="0"/>
<xsd:element name="ext" type="CT_PositiveSize2D" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="rot" type="ST_Angle" default="0"/>
<xsd:attribute name="flipH" type="xsd:boolean" default="false"/>
<xsd:attribute name="flipV" type="xsd:boolean" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_Point2D">
<xsd:attribute name="x" type="ST_Coordinate" use="required"/>
<xsd:attribute name="y" type="ST_Coordinate" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_PositiveSize2D">
<xsd:attribute name="cx" type="ST_PositiveCoordinate" use="required"/>
<xsd:attribute name="cy" type="ST_PositiveCoordinate" use="required"/>
</xsd:complexType>
<xsd:group name="EG_Geometry">
<xsd:choice>
<xsd:element name="custGeom" type="CT_CustomGeometry2D"/>
<xsd:element name="prstGeom" type="CT_PresetGeometry2D"/>
</xsd:choice>
</xsd:group>
<xsd:group name="EG_EffectProperties">
<xsd:choice>
<xsd:element name="effectLst" type="CT_EffectList"/>
<xsd:element name="effectDag" type="CT_EffectContainer"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="CT_ShapeStyle">
<xsd:sequence>
<xsd:element name="lnRef" type="CT_StyleMatrixReference"/>
<xsd:element name="fillRef" type="CT_StyleMatrixReference"/>
<xsd:element name="effectRef" type="CT_StyleMatrixReference"/>
<xsd:element name="fontRef" type="CT_FontReference"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_CommonSlideData">
<xsd:sequence>
<xsd:element name="bg" type="CT_Background" minOccurs="0"/>
<xsd:element name="spTree" type="CT_GroupShape"/>
<xsd:element name="custDataLst" type="CT_CustomerDataList" minOccurs="0"/>
<xsd:element name="controls" type="CT_ControlList" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="optional" default=""/>
</xsd:complexType>
</xsd:complexType>
<xsd:complexType name="CT_SlideTiming">
<xsd:sequence>
<xsd:element name="tnLst" type="CT_TimeNodeList" minOccurs="0"/>
<xsd:element name="bldLst" type="CT_BuildList" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_TimeNodeList">
<xsd:choice minOccurs="1" maxOccurs="unbounded">
<xsd:element name="par" type="CT_TLTimeNodeParallel"/>
<xsd:element name="seq" type="CT_TLTimeNodeSequence"/>
<xsd:element name="excl" type="CT_TLTimeNodeExclusive"/>
<xsd:element name="anim" type="CT_TLAnimateBehavior"/>
<xsd:element name="animClr" type="CT_TLAnimateColorBehavior"/>
<xsd:element name="animEffect" type="CT_TLAnimateEffectBehavior"/>
<xsd:element name="animMotion" type="CT_TLAnimateMotionBehavior"/>
<xsd:element name="animRot" type="CT_TLAnimateRotationBehavior"/>
<xsd:element name="animScale" type="CT_TLAnimateScaleBehavior"/>
<xsd:element name="cmd" type="CT_TLCommandBehavior"/>
<xsd:element name="set" type="CT_TLSetBehavior"/>
<xsd:element name="audio" type="CT_TLMediaNodeAudio"/>
<xsd:element name="video" type="CT_TLMediaNodeVideo"/>
</xsd:choice>
</xsd:complexType>
<xsd:complexType name="CT_TLTimeNodeParallel">
<xsd:sequence>
<xsd:element name="cTn" type="CT_TLCommonTimeNodeData"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_TLTimeNodeSequence">
<xsd:sequence>
<xsd:element name="cTn" type="CT_TLCommonTimeNodeData"/>
<xsd:element name="prevCondLst" type="CT_TLTimeConditionList" minOccurs="0"/>
<xsd:element name="nextCondLst" type="CT_TLTimeConditionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="concurrent" type="xsd:boolean"/>
<xsd:attribute name="prevAc" type="ST_TLPreviousActionType"/>
<xsd:attribute name="nextAc" type="ST_TLNextActionType"/>
(continues on next page)
<xsd:complexType name="CT_TLCommonTimeNodeData">
<xsd:sequence>
<xsd:element name="stCondLst" type="CT_TLTimeConditionList" minOccurs="0"/>
<xsd:element name="endCondLst" type="CT_TLTimeConditionList" minOccurs="0"/>
<xsd:element name="endSync" type="CT_TLTimeCondition" minOccurs="0"/>
<xsd:element name="iterate" type="CT_TLIterateData" minOccurs="0"/>
<xsd:element name="childTnLst" type="CT_TimeNodeList" minOccurs="0"/>
<xsd:element name="subTnLst" type="CT_TimeNodeList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="id" type="ST_TLTimeNodeID"/>
<xsd:attribute name="presetID" type="xsd:int"/>
<xsd:attribute name="presetClass" type="ST_TLTimeNodePresetClassType"/>
<xsd:attribute name="presetSubtype" type="xsd:int"/>
<xsd:attribute name="dur" type="ST_TLTime"/>
<xsd:attribute name="repeatCount" type="ST_TLTime" default=
˓→"1000"/>
<xsd:complexType name="CT_TLMediaNodeVideo">
<xsd:sequence>
<xsd:element name="cMediaNode" type="CT_TLCommonMediaNodeData"/>
</xsd:sequence>
<xsd:attribute name="fullScrn" type="xsd:boolean" default="false"/>
</xsd:complexType>
Shape hyperlink
In addition to hyperlinks in text, PowerPoint supports hyperlinks on shapes. This feature is a subset of the more general
click action functionality on shapes.
A run or shape can have two distinct mouse event behaviors, one for (left) clicking and another for rolling over with
the mouse (hover). These are independent; a run or shape can have one, the other, both, or neither.
A “true” hyperlink in PowerPoint is indicated by having no action attribute on the a:hlinkClick element. The general
hyperlink mechanism of storing a URL in a mapped relationship is used by other verbs such as hlinkfile and program,
but these are considered distinct from hyperlinks for the sake of this analysis. That distinction is reflected in the API.
See also: _Run.hyperlink, pptx.text._Hyperlink
Candidate Protocol
• Shape
– .click_action - unconditionally returns an ActionSetting object, regardless of whether a click action is
defined. Returns an ActionSetting object even when the shape type does not support a click action (such
as a table).
• ActionSetting
– .action - returns a member of the PP_ACTION_TYPE (PP_ACTION) enumeration
– .action_url - returns the ppaction:// URL as a string, in its entirety, or None if no action attribute is present.
Maybe this should do XML character entity decoding.
– .action_verb - returns the verb in the ppaction:// URL, or None if no action URL is present. e.g. ‘hlinksld-
jump’
– .action_fields - returns a dictionary containing the fields in the query string of the action URL.
– .hyperlink - returns a Hyperlink object that represents the hyperlink defined for the shape. A Hyperlink
object is always returned.
– .target_slide - returns a Slide object when the action is a jump to another slide in the same presenta-
tion. This is the case when action is FIRST_SLIDE, LAST_SLIDE, PREVIOUS_SLIDE, NEXT_SLIDE, or
NAMED_SLIDE.
Supports assignment of a slide object, after which .action returns NAMED_SLIDE.
• Hyperlink
– .address - returns the URL contained in the relationship for this hyperlink.
– .screen_tip - tool-tip text displayed on mouse rollover is slideshow mode. Put in the XML hooks for this
but API call is second priority
Detect that a shape has a hyperlink:
Add a hyperlink:
p = shape.text_frame.paragraphs[0]
r = p.add_run()
r.text = 'link to python-pptx @ GitHub'
hlink = r.hyperlink
hlink.address = 'https://github.com/scanny/python-pptx'
Delete a hyperlink:
r.hyperlink = None
# or -----------
A Hyperlink instance is lazy-created on first reference. The object persists until garbage collected once created. The
link XML is not written until .address is specified. Setting hlink.address to None or ‘’ causes the hlink entry to
be removed if present.
Add “Jump to slide” click action:
Future Scope
Each of these assignments takes immediate effect and is “self-contained”; no further assignments are necessary to
produce the specified behavior.
Assigning NAMED_SLIDE to ActionSetting.action raises an exception. This action is created by assigning a Slide
object.
Glossary
click action The behavior to be executed when the user clicks on a shape. There are 14 possible behaviors, such as
navigate to a different slide, open a web page, and run a macro. The possible behaviors are described by the
members of the PP_ACTION_TYPE enumeration.
hover action All click action behaviors can also be triggered by a mouse-over (hover) event.
hyperlink A hyperlink is a particular class of click action that roughly corresponds to opening a web page, although
it can also be used to send an email. While a similar mechanism is used to specify other actions, such as open a
file, this term here is reserved for the action of navigating to a web URL (including mailto:// ).
action The click or hover action is specified in the XML using a URL on the ppaction:// protocol contained in the
action attribute of the a:hlinkClick (or a:hlinkHover) element. A hyperlink action is implied when no action
attribute is present.
action verb The specific action to be performed is contained in the host field of the ppaction://
URL. For instance, customshow appears in ppaction://customshow?id=0&return=true to indicate a
PP_ACTION.NAMED_SLIDE_SHOW action.
OLE verb The term verb also appears in this context to indicate an OLE verb such as Open or Edit. This is not to be
confused with an action verb.
# _ClickAction.action property
hlinkClick = shape_elm.hlinkClick
if hlinkClick is None:
return PP_ACTION.NONE
action_verb = hlinkClick.action_verb
if action_verb == 'hlinkshowjump':
relative_target = hlinkClick.action_fields['jump']
return {
'firstslide': PP_ACTION.FIRST_SLIDE,
'lastslide': PP_ACTION.LAST_SLIDE,
'lastslideviewed': PP_ACTION.LAST_SLIDE_VIEWED,
'nextslide': PP_ACTION.NEXT_SLIDE,
'previousslide': PP_ACTION.PREVIOUS_SLIDE,
'endshow': PP_ACTION.END_SHOW,
}[relative_target]
return {
None: PP_ACTION.HYPERLINK,
'hlinksldjump': PP_ACTION.NAMED_SLIDE,
'hlinkpres': PP_ACTION.PLAY,
'hlinkfile': PP_ACTION.OPEN_FILE,
'customshow': PP_ACTION.NAMED_SLIDE_SHOW,
'ole': PP_ACTION.OLE_VERB,
'macro': PP_ACTION.RUN_MACRO,
'program': PP_ACTION.RUN_PROGRAM,
}[action_verb]
The general domain here is mouse event behaviors, with respect to a shape. So far, the only two mouse events are
(left) click and hover (mouse over). These can trigger a variety of actions. I’m not sure if all actions can be triggered
by either event, but the XML appears to support it.
Action inventory
Hyperlinkable shapes
UI procedures
MS API
Shape.ActionSettings(ppMouseClick | ppMouseOver)
The Shape object has an ActionSettings property, which is a collection of two ActionSetting objects, one for click and
the other for hover. https://msdn.microsoft.com/EN-US/library/office/ff745656.aspx
ActionSetting
XML specimens
These are representative samples of shape XML showing the hyperlinks associated the shape (as opposed to text
contained by the shape).
• The a:hlinkClick element can be present or absent.
• Its parent, p:cNvPr is always present (is a required element).
• All of its attributes are optional, but an a:hlinkClick having no attributes has no meaning (or may trigger an
error).
• Its r:id element is always present on click actions created by PowerPoint. Its value is an empty string when the
action is first, last, next, previous, macro, and perhaps others.
• Adding a highlightClick attribute set True causes the shape to get a dashed line border for a short time when it
is clicked.
• There are some more obscure attributes like “stop playing sound before navigating” that are available on
CT_Hyperlink, perhaps meant for kiosk-style applications.
Summary
The action to perform on a mouse click is specified by the action attribute of the a:hlinkClick element. Its value is a
URL having the ppaction:// protocol, a verb, and an optional query string.
Some actions reference a relationship that specifies the target of the action.
hlinkshowjump action
<p:sp>
<p:nvSpPr>
<p:cNvPr id="7" name="Rounded Rectangle 6">
<!-- this element does the needful -->
<a:hlinkClick r:id="" action="ppaction://hlinkshowjump?jump=firstslide"/>
</p:cNvPr>
<p:cNvSpPr/>
<p:nvPr/>
</p:nvSpPr>
<p:spPr>
<a:xfrm>
<a:off x="1020781" y="1684235"/>
<a:ext cx="1495562" cy="1775031"/>
</a:xfrm>
<a:prstGeom prst="roundRect">
<a:avLst/>
</a:prstGeom>
</p:spPr>
<p:txBody>
<a:p>
<a:pPr algn="ctr"/>
<a:r>
<a:rPr lang="en-US" dirty="0" smtClean="0"/>
<a:t>Click to go to Foobar Slide</a:t>
</a:r>
<a:endParaRPr lang="en-US" dirty="0" smtClean="0"/>
</a:p>
</p:txBody>
</p:sp>
• jump key can have value firstslide, lastslide, previousslide, nextslide, lastslideviewed, endshow.
• Note that r:id attribute is empty string; no relationship is required to determine target slide.
hlinksldjump action
<p:sp>
<p:nvSpPr>
<p:cNvPr id="7" name="Rounded Rectangle 6">
<a:hlinkClick r:id="rId2" action="ppaction://hlinksldjump"/>
</p:cNvPr>
...
</p:sp>
The corresponding Relationship element must be of type slide, be internal, and point to the target slide in the package:
<Relationship
Id="rId2"
Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide"
Target="slide1.xml"/>
hlinkpres action
<p:sp>
<p:nvSpPr>
<p:cNvPr id="7" name="Rounded Rectangle 6">
<a:hlinkClick r:id="rId3" action="ppaction://hlinkpres?slideindex=3&
˓→slidetitle=Key Questions"/>
</p:cNvPr>
...
</p:sp>
The corresponding Relationship element must be of type hyperlink, be external, and point to the target presentation
with a URL (using the file:// protocol for a local file). The slide number and slide title are provided in the ppaction://
URL in the a:hlinkClick element:
<Relationship
Id="rId3"
Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
Target="file://localhost/Users/scanny/Documents/checksec-prelim-analysis.pptx"
TargetMode="External"/>
The corresponding Relationship element must be of type hyperlink, be external, and point to the target URL (using a
web protocol).
The target is often a web URL, such as https://github/scanny/python-pptx, including an optional anchor (e.g. #sub-
heading suffix to jump mid-page). The target can also be an email address, launching the local email client. A mailto:
URI is used in this case, with subject specifiable using a ‘?subject=xyz’ suffix.
An optional ScreenTip, a roll-over tool-tip sort of message, can also be specified for a hyperlink. The XML schema
does not limit its use to hyperlinks, although the PowerPoint UI may not provide access to this field in non-hyperlink
cases.:
<Relationship
Id="rId3"
Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
Target="https://www.google.com/"
TargetMode="External"/>
hlinkfile action
<p:sp>
<p:nvSpPr>
<p:cNvPr id="7" name="Rounded Rectangle 6">
<a:hlinkClick r:id="rId2" action="ppaction://hlinkfile"/>
...
</p:sp>
• PowerPoint opens the file (after a warning dialog) using the default application for the file.
The corresponding Relationship element must be of type hyperlink, be external, and point to the target file with a file://
protocol URL:
<Relationship
Id="rId2"
Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
Target="file:///C:\Install.log"
TargetMode="External"/>
customshow action
<p:sp>
<p:nvSpPr>
<p:cNvPr id="4" name="Rounded Rectangle 3">
<a:hlinkClick r:id="" action="ppaction://customshow?id=0&return=true"/>
...
</p:sp>
• The return query field determines whether focus returns to the current show after running the linked show. This
field can be omitted, and defaults to false.
ole action
<p:sp>
<p:nvSpPr>
<p:cNvPr id="9" name="Object 8">
(continues on next page)
This option is only available on an embedded (OLE) object. The verb field is ‘0’ for Edit and ‘1’ for Open.
Run macro
macro action
<p:sp>
<p:nvSpPr>
<p:cNvPr id="4" name="Rounded Rectangle 3">
<a:hlinkClick r:id="" action="ppaction://macro?name=Hello"/>
</p:cNvPr>
...
</p:sp>
Run a program
program action
<p:sp>
<p:nvSpPr>
<p:cNvPr id="4" name="Rounded Rectangle 3">
<a:hlinkClick r:id="rId2" action="ppaction://program"/>
...
</p:sp>
The corresponding Relationship element must be of type hyperlink, be external, and point to the target application
with a file:// protocol URL.
<Relationship
Id="rId2"
Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
Target="file:///C:\Program%20Files%20(x86)\Vim\vim74\gvim.exe"
TargetMode="External"/>
Play a sound
Playing a sound is not a distinct action; rather, like highlighting, it is an optional additional action to be performed on
a click or hover event.
<p:sp>
<p:nvSpPr>
<p:cNvPr id="5" name="Rounded Rectangle 4">
<a:hlinkClick r:id="" action="ppaction://..any..">
<a:snd r:embed="rId3" name="applause.wav"/>
</a:hlinkClick>
...
</p:sp>
The corresponding Relationship element must be of type audio, be internal, and point to a sound file embedded in the
presentation:
<Relationship
Id="rId3"
Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/audio"
Target="../media/audio1.wav"/>
<xsd:complexType name="CT_Shape">
<xsd:sequence>
<xsd:element name="nvSpPr" type="CT_ShapeNonVisual"/>
<xsd:element name="spPr" type="a:CT_ShapeProperties"/>
<xsd:element name="style" type="a:CT_ShapeStyle" minOccurs="0"/>
<xsd:element name="txBody" type="a:CT_TextBody" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="useBgFill" type="xsd:boolean" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_ShapeNonVisual">
<xsd:sequence>
<xsd:element name="cNvPr" type="a:CT_NonVisualDrawingProps"/>
<xsd:element name="cNvSpPr" type="a:CT_NonVisualDrawingShapeProps"/>
<xsd:element name="nvPr" type="CT_ApplicationNonVisualDrawingProps"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_NonVisualDrawingProps">
<xsd:sequence>
<xsd:element name="hlinkClick" type="CT_Hyperlink" minOccurs="0"/>
<xsd:element name="hlinkHover" type="CT_Hyperlink" minOccurs="0"/>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="id" type="ST_DrawingElementId" use="required"/>
<xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="descr" type="xsd:string" default=""/>
<xsd:attribute name="hidden" type="xsd:boolean" default="false"/>
<xsd:attribute name="title" type="xsd:string" default=""/>
</xsd:complexType>
<xsd:complexType name="CT_Hyperlink">
<xsd:sequence>
<xsd:element name="snd" type="CT_EmbeddedWAVAudioFile" minOccurs="0"/>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute ref="r:id"/>
<xsd:attribute name="invalidUrl" type="xsd:string" default=""/>
<xsd:attribute name="action" type="xsd:string" default=""/>
<xsd:attribute name="tgtFrame" type="xsd:string" default=""/>
<xsd:attribute name="tooltip" type="xsd:string" default=""/>
<xsd:attribute name="history" type="xsd:boolean" default="true"/>
<xsd:attribute name="highlightClick" type="xsd:boolean" default="false"/>
<xsd:attribute name="endSnd" type="xsd:boolean" default="false"/>
</xsd:complexType>
Placeholders
Slide Placeholders
Picture placeholder
A picture placeholder is an unpopulated placeholder into which an image can be inserted. This comprises three
concrete placeholder types, a picture placeholder, a clip art placeholder, and a content placeholder. Each of these, and
indeed any unpopulated placeholder, take the form of a p:sp element in the XML. Once populated with an image,
these placeholders become a placeholder picture and take the form of a p:pic element.
Candidate protocol
Placeholder access:
>>> picture_placeholder = slide.placeholders[1] # keyed by idx, not offset
>>> picture_placeholder
<pptx.shapes.placeholder.PicturePlaceholder object at 0x100830510>
>>> picture_placeholder.shape_type
MSO_SHAPE_TYPE.PLACEHOLDER (14)
PicturePlaceholder.insert_picture():
>>> placeholder_picture = picture_placeholder.insert_picture('image.png')
>>> placeholder_picture
<pptx.shapes.placeholder.PlaceholderPicture object at 0x10083087a>
>>> placeholder_picture.shape_type
MSO_SHAPE_TYPE.PLACEHOLDER (14)
Example XML
<p:sp>
<p:nvSpPr>
<p:cNvPr id="7" name="Picture Placeholder 6"/>
<p:cNvSpPr>
<a:spLocks noGrp="1"/>
</p:cNvSpPr>
<p:nvPr>
<p:ph type="pic" idx="1"/>
</p:nvPr>
</p:nvSpPr>
<p:spPr/>
</p:sp>
<p:pic>
<p:nvPicPr>
<p:cNvPr id="8" name="Picture Placeholder 7"
descr="aphrodite.brinsmead.jpg"/>
<p:cNvPicPr>
<a:picLocks noGrp="1" noChangeAspect="1"/>
</p:cNvPicPr>
<p:nvPr>
<p:ph type="pic" idx="1"/>
</p:nvPr>
</p:nvPicPr>
<p:blipFill>
<a:blip r:embed="rId2">
<a:extLst>
<a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}">
<a14:useLocalDpi xmlns:a14="http://../drawing/2010/main" val="0"/>
</a:ext>
</a:extLst>
</a:blip>
<a:srcRect t="20000" b="20000"/> <!-- 20% crop, top and bottom -->
<a:stretch>
<a:fillRect/>
</a:stretch>
</p:blipFill>
<p:spPr/>
</p:pic>
Table placeholder
A table placeholder is an unpopulated placeholder into which a table can be inserted. This comprises two con-
crete placeholder types, a table placeholder and a content placeholder. Both take the form of a p:sp element in the
XML. Once populated with a table, these placeholders become a placeholder graphic frame and take the form of a
p:graphicFrame element.
Candidate protocol
Placeholder access:
>>> table_placeholder = slide.placeholders[10] # keyed by idx, not offset
>>> table_placeholder
<pptx.shapes.placeholder.TablePlaceholder object at 0x100830510>
>>> table_placeholder.shape_type
MSO_SHAPE_TYPE.PLACEHOLDER (14)
TablePlaceholder.insert_table():
>>> ph_graphic_frame = table_placeholder.insert_table(rows=2, cols=2)
>>> ph_graphic_frame
<pptx.shapes.placeholder.PlaceholderGraphicFrame object at 0x10083087a>
>>> ph_graphic_frame.shape_type
MSO_SHAPE_TYPE.PLACEHOLDER (14)
>>> ph_graphic_frame.has_table
True
>>> table = ph_graphic_frame.table
>>> len(table.rows), len(table.columns)
(2, 2)
Example XML
Topic of inquiry
What placeholder shapes are added to a new slide when it is added to a presentation?
Abstract
Slides were created based on a variety of slide layouts so their placeholder elements could be inspected to reveal
slide construction behaviors that depend on the slide layout chosen. A placeholder shape appeared in each slide
corresponding to each of the placeholder shapes in the slide layout, excepting those of footer, date, and slide number
type. Placeholder shapes were <p:sp> elements for all placeholder types rather than matching the element type
of the shape they hold a place for. Each slide-side placeholder had a <p:ph> element that exactly matched the
corresponding element in the slide layout, with the exception that a hasCustomPrompt attribute, if present in the slide
layout, did not appear in the slide. Placeholders in the slide were named and numbered differently. All placeholders
in the slide layout had a <p:txBody> element, but only certain types had one in the slide. All placeholders were
locked against grouping.
Procedure
This procedure was run using PowerPoint for Mac 2011 running on an Intel-based Mac Pro running Mountain Lion
10.8.2.
1. Create a new presentation based on the “White” theme.
2. Add a new slide layout and add placeholders of the following types. The new slide layout is (automatically)
named Custom Layout.
• Chart
• Table
• SmartArt Graphic
• Media
• Clip Art
3. Add a new slide for each of the following layouts. Do not enter any content into the placeholders.
• Title Slide (added automatically on File > New)
• Title and Content
• Two Content
• Comparison
Observations
<p:sp>
<p:nvSpPr>
<p:cNvPr id="2" name="Title 1"/>
<p:cNvSpPr>
<a:spLocks noGrp="1"/>
</p:cNvSpPr>
<p:nvPr>
<p:ph type="ctrTitle"/>
</p:nvPr>
</p:nvSpPr>
<p:spPr/>
<p:txBody>
<a:bodyPr/>
<a:lstStyle/>
<a:p>
<a:endParaRPr lang="en-US"/>
</a:p>
</p:txBody>
</p:sp>
elements
• Placeholder shapes WERE created corresponding to layout placeholders of the following types in the slide
layout:
– 'title'
– 'body'
– 'ctrTitle'
– 'subTitle'
– 'obj'
– 'chart'
– 'tbl'
– 'clipArt'
– 'dgm' (SmartArt Graphic, perhaps abbreviation of ‘diagram’)
– 'media'
– 'pic'
– None (type attribute default is 'obj')
• Placeholder shapes WERE NOT created corresponding to layout placeholders of these types in the slide layout:
– 'dt' (date)
– 'sldNum' (slide number)
– 'ftr' (footer)
• The following placeholder types do not apply to slides (they apply to notes pages and/or handouts).
– 'hdr'
– 'sldImg'
• <p:txBody> element. Placeholder shapes of the following types had a <p:txBody> element. Placeholders of
all other types did not have a <p:txBody> element.
– 'title'
– 'body'
– 'ctrTitle'
– 'subTitle'
– 'obj' (and those without a type attribute)
• <p:cNvPr> element. Each placeholder shape in each slide had a <p:cNvPr> element (it is a required element)
populated with id and name attributes.
– The value of the id attribute of p:cNvPr does not correspond to its value in the slide layout. Shape ids
were renumbered starting from 2 and proceeding in sequence (e.g. 2, 3, 4, 5, . . . ). Note that id=”1” belongs
to the spTree element, at /p:sld/p:cSld/p:spTree/p:nvGrpSpPr/p:cNvPr@id.
– The value of the name attribute is of the form ‘%s %d’ % (type_name, num), where type_name is deter-
mined by the placeholder type (e.g. ‘Media Placeholder’) and num appears to default to id - 1. The
assigned name in each case was similar to its counterpart in the slide layout (same type_name), but its
number was generally different.
• <p:cNvSpPr> element. Placeholder shapes of all types had the element <a:spLocks noGrp="1"/> spec-
ifying the placeholder could not be grouped with any other shapes.
• <p:spPr> element. All placeholder shapes had an empty <p:spPr> element.
attributes
• type. The type attribute of the <p:ph> element was copied without change. Where no type attribute
appeared (defaults to “obj”, indicating a “content” placeholder), no type attribute was added to the <p:ph>
element.
• orient. The orient attribute of the <p:ph> element was copied without change. Where no orient attribute
appeared (defaults to “horz”), no orient attribute was added to the <p:ph> element.
• sz. The sz (size) attribute of the <p:ph> element was copied without change. Where no sz attribute appeared
(defaults to “full”), no sz attribute was added to the <p:ph> element.
• idx. The idx attribute of the <p:ph> element was copied without change. Where no idx attribute appeared
(defaults to “0”, indicating the singleton title placeholder), no idx attribute was added to the <p:ph> element.
• hasCustomPrompt. The hasCustomPrompt attribute of the <p:ph> element was NOT copied from the
slide layout to the slide.
Other observations
Placeholders created from the slide layout were always <p:sp> elements, even when they were a placeholder for a
shape of another type, e.g. <p:graphicFrame>. When the on-screen placeholder for a table was clicked to add a
table, the <p:sp element was replaced by a <p:graphicFrame> element containing the table. The <p:ph> ele-
ment was retained in the new shape. Reapplying the layout to the slide caused the table to move to the original location
of the placeholder (the idx may have been used for matching). Deleting the table caused the original placeholder to
reappear in its original position.
Conclusions
• Placeholder shapes are added to new slides based on the placeholders present in the slide layout specified on
slide creation.
• Placeholders for footer, slide number, and date are excluded.
• Each new placeholder is assigned an id starting from 2 and proceeding in increments of 1 (e.g. 2, 3, 4, . . . ).
• Each new placeholder is named based on its type and the id assigned.
• Placeholders are locked against grouping.
• Placeholders of selected types get a minimal <p:txBody> element.
• Slide placeholders receive an exact copy of the <p:ph> element in the corresponding slide layout placeholder,
except that the optional hasCustomPrompt attribute, if present, is not copied.
Open Questions
None.
Candidate protocol
Inheritance behaviors
A placeholder shape on a slide is initially little more than a reference to its “parent” placeholder shape on the slide
layout. If it is a placeholder shape that can accept text, it contains a <p:txBody> element. Position, size, and even
geometry are inherited from the layout placeholder, which may in turn inherit one or more of those properties from a
master placeholder.
Substitution behaviors
Content may be placed into a placeholder shape two ways, by insertion and by substitution. Insertion is simply placing
the text insertion point in the placeholder and typing or pasting in text. Substitution occurs when an object such as a
table or picture is inserted into a placeholder by clicking on a placeholder button.
An empty placeholder is always a <p:sp> (autoshape) element. When an object such as a table is inserted into
the placehoder by clicking on a placeholder button, the <p:sp> element is replaced with the appropriate new shape
element, a table element in this case. The <p:ph> element is retained in the new shape element and preserves the
linkage to the layout placeholder such that the ‘empty’ placeholder shape can be restored if the inserted object is
deleted.
Operations
Example XML
Content placeholder:
<p:sp>
<p:nvSpPr>
<p:cNvPr id="5" name="Content Placeholder 4"/>
<p:cNvSpPr>
<a:spLocks noGrp="1"/>
</p:cNvSpPr>
<p:nvPr>
<p:ph idx="1"/>
</p:nvPr>
</p:nvSpPr>
<p:spPr/>
<p:txBody>
<a:bodyPr/>
<a:lstStyle/>
<a:p>
<a:endParaRPr lang="en-US"/>
</a:p>
</p:txBody>
</p:sp>
Notable differences:
• placeholder has <a:spLocks> element
• placeholder has <p:ph> element
• placeholder has no <p:spPr> child elements, implying both that:
– all shape properties are initially inherited from the layout placeholder, including position, size, and geom-
etry
– any specific shape property value may be overridden by specifying it on the inheriting shape
Matching slide layout placeholder:
<p:sp>
<p:nvSpPr>
<p:cNvPr id="3" name="Content Placeholder 2"/>
<p:cNvSpPr>
(continues on next page)
Behaviors
Automatic naming
• Most placeholders are automatically named ‘{root_name} Placeholder {num}’ where root_name is something
like Chart and num is a positive integer. A typical example is Table Placeholder 3.
• A placeholder with vertical orientation, i.e. <p:ph orient="vert">, is prefixed with 'Vertical ',
e.g. Vertical Text Placeholder 2.
• The word 'Placeholder' is omitted when the type is ‘title’, ‘ctrTitle’, or ‘subTitle’.
On slide creation
When a new slide is added to a presentation, empty placeholders are added to it based on the placeholders present in
the specified slide layout.
Only content placeholders are created automatically. Special placeholders must be created individually with additional
calls. Special placeholders include header, footer, page numbers, date, and slide number; and perhaps others. In this
respect, it seems like special placeholders on a slide layout are simply default settings for those placeholders in case
they are added later.
• Placeholders can be deleted from slides and can be restored by calling methods like AddTitle on the shape
collection. AddTitle raises if there’s already a title placeholder, so need to call .hasTitle() beforehand.
• Switching the layout of an empty title slide to the blank layout resulted in the placeholder shapes (title, subtitle)
being removed.
• The same switch when the shapes had content (text), resulted in the shapes being preserved, complete with their
<p:ph> element. Position and dimension values were added that preserve the height, width, top position but set
the left position to zero.
• Restoring the original layout caused those position and dimension values to be removed (and “re-inherited”).
• Applying a new (or the same) style to a slide appears to reset selected properties such that they are re-inherited
from the new layout. Size and position are both reset. Background color and font, at least, are not reset.
• The “Reset Layout to Default Settings” option appears to reset all shape properties to inherited, without excep-
tion.
• Content of a placeholder shape is retained and displayed, even when the slide layout is changed to one without
a matching layout placeholder.
• The behavior when placeholders are added to a slide layout (from the slide master) may also be worth charac-
terizing.
– . . . show master placeholder . . .
– . . . add (arbitrary) placeholder . . .
Layout Placeholders
Candidate protocol
Example XML
<p:sp>
<p:nvSpPr>
<p:cNvPr id="3" name="Content Placeholder 2"/>
<p:cNvSpPr>
<a:spLocks noGrp="1"/>
</p:cNvSpPr>
<p:nvPr>
<p:ph idx="1"/>
</p:nvPr>
</p:nvSpPr>
<p:spPr/>
<p:txBody>
<a:bodyPr/>
<a:lstStyle/>
<a:p>
<a:pPr lvl="0"/>
<a:r>
<a:rPr lang="en-US" smtClean="0"/>
<a:t>Click to edit Master text styles</a:t>
</a:r>
</a:p>
<a:p>
... and others through lvl="4", five total
</a:p>
</p:txBody>
</p:sp>
Behaviors
• Hypothesis:
– Layout inherits properties from master based only on type (e.g. body, dt), with no bearing on idx value.
* expanded/repackaged, change body ph idx on layout and see if still inherits position.
* result: slide layout still appears with the proper position and size, however the slide placeholder
appears at (0, 0) and apparently with size of (0, 0).
– What behavior is exhibited when a slide layout contains two body placeholders, neither of which has a
matching idx value and neither of which has a specified size or position?
* result: both placeholders are present, directly superimposed upon each other. They both inherit posi-
tion and fill.
Master Placeholders
Candidate protocol
>>> slide_master.shapes[0]
(continues on next page)
Example XML
Behaviors
• Master placeholder specifies size, position, geometry, and text body properties, such as margins (inset) and
autofit
• It appears a slide master permits at most five placeholders, at most one each of title, body, date, footer, and slide
number
• A master placeholder is always a <p:sp> (autoshape) element. It does not allow the insertion of content,
although text entered in the shape somehow becomes the prompt text for inheriting placeholders.
• Hypothesis:
– Layout inherits properties from master based only on type (e.g. body, dt), with no bearing on idx value.
– Slide inherits from layout strictly on idx value.
– Need to experiment to see if position and size are inherited on body placeholder by type or if idx has any
effect
* expanded/repackaged, change body ph idx on layout and see if still inherits position.
* result: slide layout still appears with the proper position and size, however the slide placeholder
appears at (0, 0) and apparently with size of (0, 0).
– What behavior is exhibited when a slide layout contains two body placeholders, neither of which has a
matching idx value and neither of which has a specified size or position?
* result: both placeholders are present, directly superimposed upon each other. They both inherit posi-
tion and fill.
• GUI doesn’t seem to provide a way to add additional “footer” placeholders
• Does the MS API include populated object placeholders in the Placeholders collection?
From a user perspective, a placeholder is a container into which content can be inserted. The position, size, and
formatting of content inserted into the placeholder is determined by the placeholder, allowing those key presentation
design characteristics to be determined at design time and kept consistent across presentations created from a particular
template.
The placeholder appearing on a slide is only part of the overall placeholder mechanism however. Placeholder behavior
requires three different categories of placeholder shape; those that exist on a slide master, those on a slide layout, and
those that ultimately appear on a slide in a presentation.
These three categories of placeholder participate in a property inheritance hierarchy, either as an inheritor, an inheritee,
or both. Placeholder shapes on masters are inheritees only. Conversely placeholder shapes on slides are inheritors
only. Placeholders on slide layouts are both, a possible inheritor from a slide master placeholder and an inheritee to
placeholders on slides linked to that layout.
A layout inherits from its master differently than a slide inherits from its layout. A layout placeholder inherits from the
master placeholder sharing the same type. A slide placeholder inherits from the layout placeholder having the same
idx value.
Glossary
layout placeholder a shorthand name for the placeholder shape on the slide layout from which a particular place-
holder on a slide inherits shape properties
master placeholder the placeholder shape on the slide master which a layout placeholder inherits from, if any.
Schema excerpt
<xsd:complexType name="CT_ApplicationNonVisualDrawingProps">
<xsd:sequence>
<xsd:element name="ph" type="CT_Placeholder" minOccurs="0"/>
<xsd:choice minOccurs="0"> <!-- a:EG_Media -->
<xsd:element name="audioCd" type="CT_AudioCD"/>
<xsd:element name="wavAudioFile" type="CT_EmbeddedWAVAudioFile"/>
<xsd:element name="audioFile" type="CT_AudioFile"/>
<xsd:element name="videoFile" type="CT_VideoFile"/>
<xsd:element name="quickTimeFile" type="CT_QuickTimeFile"/>
</xsd:choice>
<xsd:element name="custDataLst" type="CT_CustomerDataList" minOccurs="0"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="isPhoto" type="xsd:boolean" default="false"/>
<xsd:attribute name="userDrawn" type="xsd:boolean" default="false"/>
</xsd:complexType>
<xsd:complexType name="CT_Placeholder">
<xsd:sequence>
<xsd:element name="extLst" type="CT_ExtensionListModify" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="type" type="ST_PlaceholderType" default="obj"/>
<xsd:attribute name="orient" type="ST_Direction" default="horz"/>
<xsd:attribute name="sz" type="ST_PlaceholderSize" default="full"/>
<xsd:attribute name="idx" type="xsd:unsignedInt" default="0"/>
<xsd:attribute name="hasCustomPrompt" type="xsd:boolean" default="false"/>
</xsd:complexType>
<xsd:simpleType name="ST_PlaceholderType">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="title"/>
<xsd:enumeration value="body"/>
<xsd:enumeration value="ctrTitle"/>
<xsd:enumeration value="subTitle"/>
<xsd:enumeration value="dt"/>
<xsd:enumeration value="sldNum"/>
<xsd:enumeration value="ftr"/>
<xsd:enumeration value="hdr"/>
<xsd:enumeration value="obj"/>
<xsd:enumeration value="chart"/>
<xsd:enumeration value="tbl"/>
<xsd:enumeration value="clipArt"/>
<xsd:enumeration value="dgm"/>
<xsd:enumeration value="media"/>
<xsd:enumeration value="sldImg"/>
<xsd:enumeration value="pic"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_PlaceholderSize">
(continues on next page)
<xsd:simpleType name="ST_Direction">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="horz"/>
<xsd:enumeration value="vert"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_PlaceholderSize">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="full"/>
<xsd:enumeration value="half"/>
<xsd:enumeration value="quarter"/>
</xsd:restriction>
</xsd:simpleType>
Place page number (and perhaps copyright, date) on master in plain text boxes. Use “Hide Background Graphics”
option on title slide to prevent them showing there if desired.
• In the slide placeholder method, an individually selectable footer item placeholder is present on the slide:
– It can be moved accidentally, losing the placement consistency originally imposed by the master. Recov-
ering exact placement requires reapplying the layout which may make other, unwanted changes.
– It can be deleted, which could be a plus or minus depending.
– It can be formatted inconsistently.
– In can be accidentally selected and generally pollutes the shape space of the slide.
• I’m not sure python-pptx does the right thing when adding slides from layouts containing footer items, at least
not the same thing as PowerPoint does in automatically working out which footer items to copy over.
Also, there’s no method to copy over footer items from the layout.
• Alternatives:
1. A page number can be placed on the master as a text box. This causes it to appear on every layout and
every slide. No refreshing is necessary as this item is inherited, not copied at slide or layout create time.
It can be excluded from an individual layout (such as a title slide layout) by setting the Hide Background
Graphics flag on a layout-by-layout basis. Unfortunately, this also hides other items such as a logo,
copyright text, and slide background, but these can be reapplied individually directly to that slide layout.
Since the title slide layout is generally the only one folks want to hide a slide number from, this is perhaps
not a great burden. Others, like perhaps closing slides, might have their own background anyway.
Hypothesis:
• There is a class of placeholders known as “footer elements”, comprising date and time, footer text, and slide
number.
• These placeholders can only be directly added to a master. They are not available as options to add directly to a
layout or to a slide.
• In every case, these placeholders are copied, although some attributes may be inherited at run time (not sure).
Footer items are copied from the master to a new layout. Likewise, items are copied from a layout to a slide, but
only when explicitly asked for using Insert > Header and Footer. PowerPoint sometimes adds these automatically
when they’re already present on other slides (don’t know the rules it uses).
Intended procedure
PowerPoint Behaviors
• Layout: Slide Master (ribbon) > Edit Layout > Allow Footers (checkbox)
– Adding or removing a footer item from a layout, does not automatically reflect that change on existing
slides based on that layout. The change is also not reflected when you reapply the layout, at least for
deleting case.
* It does not appear when you reapply the layout (‘Reset Layout to Default Settings’ on Mac)
• Position appears to be inherited as long as you haven’t moved the placeholder on the slide. This applies at master
-> layout as well as layout -> slide level.
– Refreshing the layout after the page number item has been deleted leaves the page number item, but
repositions it to a default (right justified to right slide edge) position. Apparently it attempts to inherit the
position from the layout but not presence (or not).
• The Allow Footers checkbox is inactive (not greyed out but can’t be set on) when there are no footer placeholder
items on the master.
• Allow footers seems to be something of a one-way street. You can’t clear the checkbox once it’s set. However,
if you delete the footer placeholder(s), the checkbox clears all by itself.
• The placeholder copied from master to layout can be repositioned and formatted (font etc.).
• Menu > Insert > Header and Footer . . . Is available on individual slides and can be applied to all slides. It also
works for removing footer items. This applies to slides, not to slide layouts.
This dialog is also available from the Page Setup dialog.
• Hide background graphics flag does not control footer items. It does however control visibility of all non-
placeholder items on the layout (or slide). It’s available at both the layout and slide level. Not sure how that’s
reflected in the XML.
• When creating a new slide layout, the footer placeholders from the master are all automatically shown. This is
to say that the “Allow Footers” ribbon option defaults to True when adding a new slide layout.
Clicking Allow Footers off hides all the footer items. They can also be deleted or formatted individually.
• In order to appear (at create time anyway), footer items need to be:
1. Present on the master
2. Present on the layout (‘Allow Footers’ turned on, ph not deleted)
3. Insert Header and Footer turned on for each ph element to be shown. This is applied on a slide-by-slide
basis.
Notes
• Header is a misnomer as far as slides are concerned. There are no header items for a slide. A notes page can
have a header though, which I expect is why it appears, since the same dialog is used for slides and notes pages
(and handouts).
• A master is intended only to contain certain items:
– Title
– Body
– Footer placeholders (date/time, footer text, slide number)
– Background and theme items, perhaps logos and static text
• http://www.powerpointninja.com/templates/powerpoint-templates-beware-of-the-footers/
• https://github.com/scanny/python-pptx/issues/64
CT_PresetGeometry2D
Spec text
This element specifies when a preset geometric shape should be used instead of a custom geometric
shape. The generating application should be able to render all preset geometries enumerated in the
ST_ShapeType list.
Schema excerpt
<xsd:complexType name="CT_PresetGeometry2D">
<xsd:sequence>
<xsd:element name="avLst" type="CT_GeomGuideList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="prst" type="ST_ShapeType" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_GeomGuideList">
<xsd:sequence>
<xsd:element name="gd" type="CT_GeomGuide" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_GeomGuide">
<xsd:attribute name="name" type="ST_GeomGuideName" use="required"/>
<xsd:attribute name="fmla" type="ST_GeomGuideFormula" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_GeomGuideName">
<xsd:restriction base="xsd:token"/>
</xsd:simpleType>
<xsd:simpleType name="ST_GeomGuideFormula">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
<xsd:simpleType name="ST_ShapeType">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="line"/>
<xsd:enumeration value="lineInv"/>
<xsd:enumeration value="triangle"/>
<xsd:enumeration value="rtTriangle"/>
<xsd:enumeration value="rect"/>
<xsd:enumeration value="diamond"/>
<xsd:enumeration value="parallelogram"/>
<xsd:enumeration value="trapezoid"/>
<xsd:enumeration value="nonIsoscelesTrapezoid"/>
<xsd:enumeration value="pentagon"/>
<xsd:enumeration value="hexagon"/>
<xsd:enumeration value="heptagon"/>
<xsd:enumeration value="octagon"/>
<xsd:enumeration value="decagon"/>
<xsd:enumeration value="dodecagon"/>
<xsd:enumeration value="star4"/>
<xsd:enumeration value="star5"/>
<xsd:enumeration value="star6"/>
<xsd:enumeration value="star7"/>
<xsd:enumeration value="star8"/>
<xsd:enumeration value="star10"/>
<xsd:enumeration value="star12"/>
<xsd:enumeration value="star16"/>
<xsd:enumeration value="star24"/>
<xsd:enumeration value="star32"/>
<xsd:enumeration value="roundRect"/>
<xsd:enumeration value="round1Rect"/>
<xsd:enumeration value="round2SameRect"/>
<xsd:enumeration value="round2DiagRect"/>
(continues on next page)
Text
Paragraph Spacing
A paragraph has three spacing properties. It can have spacing that separates it from the prior paragraph, spacing that
separates it from the following paragraph, and line spacing less than or greater than the default single line spacing.
Candidate protocol
An existing paragraph that somehow has space before or after set in terms of lines (<a:spcPct>) will return a value
of Length(0) for that property.
Get and set line spacing:
MS API
LineRuleAfter Determines whether line spacing after the last line in each paragraph is set to a specific number of
points or lines. Read/write.
LineRuleBefore Determines whether line spacing before the first line in each paragraph is set to a specific number of
points or lines. Read/write.
LineRuleWithin Determines whether line spacing between base lines is set to a specific number of points or lines.
Read/write.
SpaceAfter Returns or sets the amount of space after the last line in each paragraph of the specified text, in points or
lines. Read/write.
SpaceBefore Returns or sets the amount of space before the first line in each paragraph of the specified text, in points
or lines. Read/write.
SpaceWithin Returns or sets the amount of space between base lines in the specified text, in points or lines.
Read/write.
PowerPoint behavior
• The UI doesn’t appear to allow line spacing to be set in units of lines, although the XML and MS API allow it
to be specified so.
XML specimens
<a:p>
<a:r>
<a:t>Paragraph with default spacing</a:t>
</a:r>
</a:p>
<a:p>
<a:pPr>
<a:spcBef>
<a:spcPts val="600"/>
</a:spcBef>
</a:pPr>
<a:r>
<a:t>Paragraph spacing before = 6pt</a:t>
</a:r>
</a:p>
<a:p>
<a:pPr>
<a:spcAft>
<a:spcPts val="1200"/>
</a:spcAft>
</a:pPr>
<a:r>
<a:t>Paragraph spacing after = 12pt</a:t>
</a:r>
</a:p>
<a:p>
<a:pPr>
<a:lnSpc>
<a:spcPts val="2400"/>
</a:lnSpc>
</a:pPr>
(continues on next page)
<a:p>
<a:pPr>
<a:lnSpc>
<a:spcPct val="200000"/>
</a:lnSpc>
</a:pPr>
<a:r>
<a:t>Paragraph line spacing = 2 line</a:t>
</a:r>
<a:br/>
<a:r>
<a:t>second line</a:t>
</a:r>
</a:p>
Schema excerpt
<xsd:complexType name="CT_TextParagraph">
<xsd:sequence>
<xsd:element name="pPr" type="CT_TextParagraphProperties" minOccurs="0"/>
<xsd:group ref="EG_TextRun" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="endParaRPr" type="CT_TextCharacterProperties" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_TextParagraphProperties">
<xsd:sequence>
<xsd:element name="lnSpc" type="CT_TextSpacing" minOccurs="0"/>
<xsd:element name="spcBef" type="CT_TextSpacing" minOccurs="0"/>
<xsd:element name="spcAft" type="CT_TextSpacing" minOccurs="0"/>
<xsd:choice minOccurs="0"> <!-- EG_TextBulletColor -->
<xsd:element name="buClrTx" type="CT_TextBulletColorFollowText"/>
<xsd:element name="buClr" type="CT_Color"/>
</xsd:choice>
<xsd:choice minOccurs="0"> <!-- EG_TextBulletSize -->
<xsd:element name="buSzTx" type="CT_TextBulletSizeFollowText"/>
<xsd:element name="buSzPct" type="CT_TextBulletSizePercent"/>
<xsd:element name="buSzPts" type="CT_TextBulletSizePoint"/>
</xsd:choice>
<xsd:choice minOccurs="0"> <!-- EG_TextBulletTypeface -->
<xsd:element name="buFontTx" type="CT_TextBulletTypefaceFollowText"/>
<xsd:element name="buFont" type="CT_TextFont"/>
</xsd:choice>
(continues on next page)
<xsd:complexType name="CT_TextSpacing">
<xsd:choice>
<xsd:element name="spcPct" type="CT_TextSpacingPercent"/>
<xsd:element name="spcPts" type="CT_TextSpacingPoint"/>
</xsd:choice>
</xsd:complexType>
<xsd:complexType name="CT_TextSpacingPercent">
<xsd:attribute name="val" type="ST_TextSpacingPercentOrPercentString" use="required
˓→"/>
</xsd:complexType>
<xsd:simpleType name="ST_TextSpacingPercentOrPercentString">
<xsd:union memberTypes="ST_TextSpacingPercent s:ST_Percentage"/>
</xsd:simpleType>
<xsd:simpleType name="ST_TextSpacingPercent">
<xsd:restriction base="ST_PercentageDecimal">
<xsd:minInclusive value="0"/>
<xsd:maxInclusive value="13200000"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_Percentage">
<xsd:restriction base="xsd:string">
<xsd:pattern value="-?[0-9]+(\.[0-9]+)?%"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="CT_TextSpacingPoint">
<xsd:attribute name="val" type="ST_TextSpacingPoint" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_TextSpacingPoint">
(continues on next page)
An AutoShape has a text frame, referred to in the PowerPoint UI as the shape’s Text Box. One of the settings provided
is Autofit, which can be one of “Do not autofit”, “Resize text to fit shape”, or “Resize shape to fit text”. The scope of
this analysis is how best to provide an alternative to the “Resize text to fit shape” behavior that simply resizes the text
to the largest point size that will fit entirely within the shape extents.
This produces a similar visual effect, but the “auto-size” behavior does not persist to later changes to the text or shape.
It is just as though the user had reduced the font size just until all the text fit within the shape.
Candidate Protocol
Calling TextFrame.fit_text() sets auto-size to MSO_AUTO_SIZE.NONE, turns word-wrap on, and sets the
font size of all text in the shape to the maximum size that will fit entirely within the shape, not to exceed the optional
max_size. The default max_size is 18pt. The font size is applied directly on each run-level element in the shape. The
path to the matching font file must be specified:
>>> text_frame.fit_text('calibriz.ttf', max_size=18)
>>> text_frame.auto_size, text_frame.word_wrap
(MSO_AUTO_SIZE.NONE (0), True)
>>> text_frame.paragraphs[0].runs[0].font.size.pt
10
Current constraints
TextFrame.fit_text()
Incremental enhancements
• Allow font file to be specified. This allows TextFrame.fit_text() to be run from pip installed version.
OS-specific file locations and names can be determined by client.
• Allow bold and italic to be specified. This allows the client to determine whether to apply the bold and/or italic
typeface variant to the text.
• Allow typeface name to be specified. This allows the client to determine which base typeface is applied to the
text.
• Auto-locate font file based on typeface and variants. Relax requirement for client to specify font file, looking
it up in current system based on system type, typeface name, and variants.
PowerPoint behavior
XML specimens
<p:txBody>
<a:bodyPr wrap="none">
<a:spAutoFit/> <!-- fit shape to text -->
</a:bodyPr>
<a:lstStyle/>
<a:p/>
</p:txBody>
8” x 0.5” text box, default margins, defaulting to 18pt “full-size” text, auto-reduced to 12pt. <a:t> element text
wrapped for compact display:
<p:txBody>
<a:bodyPr wrap="square" rtlCol="0">
<a:noAutofit/>
</a:bodyPr>
<a:lstStyle/>
<a:p>
<a:r>
<a:rPr lang="en-US" sz=1200 dirty="0" smtClean="0"/>
<a:t>The art and craft of designing typefaces is called type design.
Designers of typefaces are called type designers and are often
employed by type foundries. In digital typography, type
designers are sometimes also called font developers or font
designers.</a:t>
</a:r>
<a:endParaRPr lang="en-US" sz=1200 dirty="0"/>
</a:p>
</p:txBody>
<xsd:complexType name="CT_TextBody">
<xsd:sequence>
<xsd:element name="bodyPr" type="CT_TextBodyProperties"/>
<xsd:element name="lstStyle" type="CT_TextListStyle" minOccurs="0"/>
<xsd:element name="p" type="CT_TextParagraph" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_TextNoAutofit"/>
<xsd:complexType name="CT_TextParagraph">
<xsd:sequence>
<xsd:element name="pPr" type="CT_TextParagraphProperties" minOccurs="0"/>
<xsd:choice minOccurs="0" maxOccurs="unbounded"/> <!-- EG_TextRun -->
<xsd:element name="r" type="CT_RegularTextRun"/>
<xsd:element name="br" type="CT_TextLineBreak"/>
<xsd:element name="fld" type="CT_TextField"/>
</xsd:choice>
<xsd:element name="endParaRPr" type="CT_TextCharacterProperties" minOccurs="0"/>
(continues on next page)
<xsd:complexType name="CT_RegularTextRun">
<xsd:sequence>
<xsd:element name="rPr" type="CT_TextCharacterProperties" minOccurs="0"/>
<xsd:element name="t" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_TextLineBreak">
<xsd:sequence>
<xsd:element name="rPr" type="CT_TextCharacterProperties" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_TextField">
<xsd:sequence>
<xsd:element name="rPr" type="CT_TextCharacterProperties" minOccurs="0"/>
<xsd:element name="pPr" type="CT_TextParagraphProperties" minOccurs="0"/>
<xsd:element name="t" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="id" type="s:ST_Guid" use="required"/>
<xsd:attribute name="type" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType name="CT_TextCharacterProperties">
<xsd:sequence>
<xsd:element name="ln" type="CT_LineProperties"
˓→minOccurs="0"/>
<xsd:group ref="EG_FillProperties"
˓→minOccurs="0"/>
<xsd:group ref="EG_EffectProperties"
˓→minOccurs="0"/>
<xsd:group ref="EG_TextUnderlineLine"
˓→minOccurs="0"/>
<xsd:group ref="EG_TextUnderlineFill"
˓→minOccurs="0"/>
</xsd:sequence>
(continues on next page)
<xsd:complexType name="CT_TextFont">
<xsd:attribute name="typeface" type="ST_TextTypeface" use="required"/>
<xsd:attribute name="panose" type="s:ST_Panose"/>
<xsd:attribute name="pitchFamily" type="ST_PitchFamily" default="0"/>
<xsd:attribute name="charset" type="xsd:byte" default="1"/>
</xsd:complexType>
<xsd:complexType name="CT_Hyperlink">
<xsd:sequence>
<xsd:element name="snd" type="CT_EmbeddedWAVAudioFile" minOccurs="0"/>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute ref="r:id"/>
<xsd:attribute name="invalidUrl" type="xsd:string" default=""/>
<xsd:attribute name="action" type="xsd:string" default=""/>
<xsd:attribute name="tgtFrame" type="xsd:string" default=""/>
<xsd:attribute name="tooltip" type="xsd:string" default=""/>
<xsd:attribute name="history" type="xsd:boolean" default="true"/>
<xsd:attribute name="highlightClick" type="xsd:boolean" default="false"/>
<xsd:attribute name="endSnd" type="xsd:boolean" default="false"/>
</xsd:complexType>
<xsd:simpleType name="ST_TextCapsType">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="none"/>
<xsd:enumeration value="small"/>
<xsd:enumeration value="all"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_TextFontSize">
<xsd:restriction base="xsd:int">
<xsd:minInclusive value="100"/>
<xsd:maxInclusive value="400000"/>
</xsd:restriction>
</xsd:simpleType>
(continues on next page)
<xsd:simpleType name="ST_TextTypeface">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
An AutoShape has a text frame, referred to in the PowerPoint UI as the shape’s Text Box. One of the settings provided
is Autofit, which can be one of “Do not autofit”, “Resize text to fit shape”, or “Resize shape to fit text”. The scope of
this analysis is how best to implement the “Resize text to fit shape” behavior.
A robust implementation would be complex and would lead the project outside the currently intended scope. In
particular, because the shape size, text content, the “full” point size of the text, and the autofit and wrap settings of
the text frame all interact to determine the proper “fit” of adjusted text, all events that could change the state of any of
these five factors would need to be coupled to an “update” method. There would also need to be at least two “fitting”
algorithms, one for when wrap was turned on and another for when it was off.
The initial solution we’ll pursue is a special-purpose method on TextFrame that reduces the permutations of these
variables to one and places responsibility on the developer to call it at the appropriate time. The method will calculate
based on the current text and shape size, set wrap on, and set auto_size to fit text to the shape. If any of the variables
change, the developer will be responsible for re-calling the method.
Current constraints
TextFrame.autofit_text()
• User must manually set all shape text to a uniform 12pt default full-size font point size.
– This is intended to be done before the call, but might work okay if done after too, as long as it matches the
default 12pt.
• Only 12pt “full-size” is supported. There is no mechanism to specify other sizes.
• Unconditionally sets autofit and wrap.
• Path to font file must be provided manually.
• User must manually set the font typeface of all shape text to match the provided font file.
Incremental enhancements
• .fit_text() or .autofit_text(). Two related methods are used to fit text in a shape using different approaches.
TextFrame.autofit_text() uses the TEXT_TO_FIT_SHAPE autofit setting to shrink a full-size para-
graph of text. Later edits to that text using PowerPoint will re-fit the text automatically, up to the original
(full-size) font size.
TextFrame.fit_text() takes the approach of simply setting the font size for all text in the shape to the
best-fit size. No automatic resizing occurs on later edits in PowerPoint, although the user can switch on auto-fit
for that text box, perhaps after setting the full-size point size to their preferred size.
• Specified full point size. Allow the point size maximum to be specified; defaults to 18pt. All text in the shape
is set to this size before calculating the best-fit based on that size.
• Specified font. In the process, this specifies the font to use, although it may require a tuple specifying the type
family name as well as the bold and italic states, plus a file path.
• Auto-locate installed font file. Search for and use the appropriate locally-installed font file corresponding to
the selected typeface. On Windows, the font directory can be located using a registry key, and is perhaps often
C:WindowsFonts. However the font filename is not the same as the UI typeface name, so some mapping would
be required, including detecting whether bold and/or italic were specified.
• Accommodate line breaks. Either from <a:br> elements or multiple paragraphs. Would involve ending lines
at a break, other than the last paragraph.
• Add line space reduction. PowerPoint always reduces line spacing by as much as 20% to maximize the
font size used. Add this factor into the calculation to improve the exact match likelihood for font scale and
lnSpcReduction and thereby reduce occurence of “jumping” of text to a new size on edit.
Candidate Protocol
Shape size and text are set before calling TextFrame.autofit_text() or TextFrame.fit_text():
Calling TextFrame.autofit_text() turns on auto fit (text to shape), switches on word wrap, and calculates
the best-fit font scaling factor:
>>> text_frame.autofit_text()
>>> text_frame.auto_size, text_frame.word_wrap, text_frame._font_scale
(TEXT_TO_FIT_SHAPE (2), True, 55.0)
Calling TextFrame.fit_text() produces the same sized text, but autofit is not turned on. Rather the actual font
size for text in the shape is set to the calculated “best fit” point size:
>>> text_frame.fit_text()
>>> text_frame.auto_size, text_frame.word_wrap, text_frame._font_scale
(None, True, None)
>>> text_frame.paragraphs[0].font.size.pt
10
PowerPoint behavior
XML specimens
<p:txBody>
<a:bodyPr wrap="none">
<a:spAutoFit/> <!-- fit shape to text -->
</a:bodyPr>
<a:lstStyle/>
<a:p/>
</p:txBody>
8” x 0.5” text box, default margins, defaulting to 18pt “full-size” text, auto-reduced to 10pt. <a:t> element text
wrapped for compact display:
<p:txBody>
<a:bodyPr wrap="square" rtlCol="0">
<a:normAutofit fontScale="55000" lnSpcReduction="20000"/>
</a:bodyPr>
<a:lstStyle/>
<a:p>
<a:r>
<a:rPr lang="en-US" dirty="0" smtClean="0"/>
<a:t>The art and craft of designing typefaces is called type design.
Designers of typefaces are called type designers and are often
employed by type foundries. In digital typography, type
designers are sometimes also called font developers or font
designers.</a:t>
</a:r>
<a:endParaRPr lang="en-US" dirty="0"/>
</a:p>
</p:txBody>
<xsd:complexType name="CT_TextBody">
<xsd:sequence>
<xsd:element name="bodyPr" type="CT_TextBodyProperties"/>
<xsd:element name="lstStyle" type="CT_TextListStyle" minOccurs="0"/>
<xsd:element name="p" type="CT_TextParagraph" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
(continues on next page)
<xsd:complexType name="CT_TextNormalAutofit">
<xsd:attribute name="fontScale" type="ST_TextFontScalePercentOrPercentString"
use="optional" default="100%"/>
<xsd:attribute name="lnSpcReduction" type="ST_TextSpacingPercentOrPercentString"
use="optional" default="0%"/>
</xsd:complexType>
<xsd:complexType name="CT_TextShapeAutofit"/>
<xsd:complexType name="CT_TextNoAutofit"/>
<xsd:simpleType name="ST_TextFontScalePercentOrPercentString">
<xsd:union memberTypes="ST_TextFontScalePercent s:ST_Percentage"/>
</xsd:simpleType>
<xsd:simpleType name="ST_TextFontScalePercent">
<xsd:restriction base="ST_PercentageDecimal">
<xsd:minInclusive value="1000"/>
<xsd:maxInclusive value="100000"/>
</xsd:restriction>
(continues on next page)
Text
All text in PowerPoint appears in a shape. Of the six shape types, only an AutoShape can directly contain text. This
includes text placeholders, text boxes, and geometric auto shapes. These correspond to shapes based on the <p:sp>
XML element.
Each auto shape has a text frame, represented by a TextFrame object. A text frame contains one or more paragraphs,
and each paragraph contains a sequence of zero or more run, line break, or field elements (<a:r>, <a:br>, and
<a:fld>, respectively).
Notes
XML specimens
<p:txBody>
<a:bodyPr wrap="none" rtlCol="0">
<a:spAutoFit/>
</a:bodyPr>
<a:lstStyle/>
<a:p>
<a:r>
<a:rPr lang="en-US" dirty="0" smtClean="0"/>
<a:t>This text box has a break here -></a:t>
</a:r>
<a:br>
<a:rPr lang="en-US" dirty="0" smtClean="0"/>
</a:br>
<a:r>
<a:rPr lang="en-US" dirty="0" smtClean="0"/>
<a:t>and a Field here -> </a:t>
</a:r>
<a:fld id="{466D331B-39A1-D247-9EB6-2F41F44AA032}" type="datetime2">
<a:rPr lang="en-US" smtClean="0"/>
<a:t>Monday, September 15, 14</a:t>
</a:fld>
<a:endParaRPr lang="en-US" dirty="0"/>
</a:p>
</p:txBody>
Schema excerpt
<xsd:complexType name="CT_TextBody">
<xsd:sequence>
<xsd:element name="bodyPr" type="CT_TextBodyProperties"/>
<xsd:element name="lstStyle" type="CT_TextListStyle" minOccurs="0"/>
<xsd:element name="p" type="CT_TextParagraph" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_TextBodyProperties">
<xsd:sequence>
<xsd:element name="prstTxWarp" type="CT_PresetTextShape" minOccurs="0"/>
<xsd:group ref="EG_TextAutofit" minOccurs="0"/>
<xsd:element name="scene3d" type="CT_Scene3D" minOccurs="0"/>
<xsd:group ref="EG_Text3D" minOccurs="0"/>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="rot" type="ST_Angle"/>
<xsd:attribute name="spcFirstLastPara" type="xsd:boolean"/>
<xsd:attribute name="vertOverflow" type="ST_TextVertOverflowType"/>
<xsd:attribute name="horzOverflow" type="ST_TextHorzOverflowType"/>
<xsd:attribute name="vert" type="ST_TextVerticalType"/>
<xsd:attribute name="wrap" type="ST_TextWrappingType"/>
<xsd:attribute name="lIns" type="ST_Coordinate32"/>
<xsd:attribute name="tIns" type="ST_Coordinate32"/>
<xsd:attribute name="rIns" type="ST_Coordinate32"/>
<xsd:attribute name="bIns" type="ST_Coordinate32"/>
<xsd:attribute name="numCol" type="ST_TextColumnCount"/>
<xsd:attribute name="spcCol" type="ST_PositiveCoordinate32"/>
<xsd:attribute name="rtlCol" type="xsd:boolean"/>
<xsd:attribute name="fromWordArt" type="xsd:boolean"/>
<xsd:attribute name="anchor" type="ST_TextAnchoringType"/>
<xsd:attribute name="anchorCtr" type="xsd:boolean"/>
<xsd:attribute name="forceAA" type="xsd:boolean"/>
<xsd:attribute name="upright" type="xsd:boolean" default="false"/>
<xsd:attribute name="compatLnSpc" type="xsd:boolean"/>
</xsd:complexType>
<xsd:complexType name="CT_TextListStyle">
<xsd:sequence>
<xsd:element name="defPPr" type="CT_TextParagraphProperties" minOccurs="0"/>
<xsd:element name="lvl1pPr" type="CT_TextParagraphProperties" minOccurs="0"/>
<xsd:element name="lvl2pPr" type="CT_TextParagraphProperties" minOccurs="0"/>
<xsd:element name="lvl3pPr" type="CT_TextParagraphProperties" minOccurs="0"/>
<xsd:element name="lvl4pPr" type="CT_TextParagraphProperties" minOccurs="0"/>
<xsd:element name="lvl5pPr" type="CT_TextParagraphProperties" minOccurs="0"/>
<xsd:element name="lvl6pPr" type="CT_TextParagraphProperties" minOccurs="0"/>
<xsd:element name="lvl7pPr" type="CT_TextParagraphProperties" minOccurs="0"/>
<xsd:element name="lvl8pPr" type="CT_TextParagraphProperties" minOccurs="0"/>
<xsd:element name="lvl9pPr" type="CT_TextParagraphProperties" minOccurs="0"/>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_TextParagraph">
<xsd:sequence>
(continues on next page)
<xsd:group name="EG_TextRun">
<xsd:choice>
<xsd:element name="r" type="CT_RegularTextRun"/>
<xsd:element name="br" type="CT_TextLineBreak"/>
<xsd:element name="fld" type="CT_TextField"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="CT_RegularTextRun">
<xsd:sequence>
<xsd:element name="rPr" type="CT_TextCharacterProperties" minOccurs="0"/>
<xsd:element name="t" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_TextLineBreak">
<xsd:sequence>
<xsd:element name="rPr" type="CT_TextCharacterProperties" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_TextField">
<xsd:sequence>
<xsd:element name="rPr" type="CT_TextCharacterProperties" minOccurs="0"/>
<xsd:element name="pPr" type="CT_TextParagraphProperties" minOccurs="0"/>
<xsd:element name="t" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="id" type="s:ST_Guid" use="required"/>
<xsd:attribute name="type" type="xsd:string"/>
</xsd:complexType>
Font - Underline
Text in PowerPoint shapes can be formatted with a rich choice of underlining styles. Two choices control the underline
appearance of a font: the underline style and the underline color. There are 18 available underline styles, including
such choices as single line, wavy, and dot-dash.
Candidate Protocol
>>> font.underline
False
>>> font.underline = True
>>> font.underline
SINGLE_LINE (2)
>>> font.underline = MSO_UNDERLINE.WAVY_DOUBLE_LINE
>>> font.underline
(continues on next page)
XML specimens
<xsd:complexType name="CT_TextCharacterProperties">
<xsd:sequence>
<xsd:element name="ln" type="CT_LineProperties" minOccurs="0"/>
<xsd:group ref="EG_FillProperties" minOccurs="0"/>
<xsd:group ref="EG_EffectProperties" minOccurs="0"/>
<xsd:element name="highlight" type="CT_Color" minOccurs="0"/>
<xsd:group ref="EG_TextUnderlineLine" minOccurs="0"/>
<xsd:group ref="EG_TextUnderlineFill" minOccurs="0"/>
<xsd:element name="latin" type="CT_TextFont" minOccurs="0"/>
<xsd:element name="ea" type="CT_TextFont" minOccurs="0"/>
<xsd:element name="cs" type="CT_TextFont" minOccurs="0"/>
<xsd:element name="sym" type="CT_TextFont" minOccurs="0"/>
<xsd:element name="hlinkClick" type="CT_Hyperlink" minOccurs="0"/>
<xsd:element name="hlinkMouseOver" type="CT_Hyperlink" minOccurs="0"/>
<xsd:element name="rtl" type="CT_Boolean" minOccurs="0"/>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"
˓→/>
</xsd:sequence>
<xsd:attribute name="kumimoji" type="xsd:boolean"/>
<xsd:attribute name="lang" type="s:ST_Lang"/>
<xsd:attribute name="altLang" type="s:ST_Lang"/>
<xsd:attribute name="sz" type="ST_TextFontSize"/>
<xsd:attribute name="b" type="xsd:boolean"/>
<xsd:attribute name="i" type="xsd:boolean"/>
<xsd:attribute name="u" type="ST_TextUnderlineType"/>
<xsd:attribute name="strike" type="ST_TextStrikeType"/>
<xsd:attribute name="kern" type="ST_TextNonNegativePoint"/>
<xsd:attribute name="cap" type="ST_TextCapsType"/>
<xsd:attribute name="spc" type="ST_TextPoint"/>
<xsd:attribute name="normalizeH" type="xsd:boolean"/>
<xsd:attribute name="baseline" type="ST_Percentage"/>
<xsd:attribute name="noProof" type="xsd:boolean"/>
<xsd:attribute name="dirty" type="xsd:boolean" default="true"/>
<xsd:attribute name="err" type="xsd:boolean" default="false"/>
(continues on next page)
<xsd:simpleType name="ST_TextUnderlineType">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="none"/>
<xsd:enumeration value="words"/>
<xsd:enumeration value="sng"/>
<xsd:enumeration value="dbl"/>
<xsd:enumeration value="heavy"/>
<xsd:enumeration value="dotted"/>
<xsd:enumeration value="dottedHeavy"/>
<xsd:enumeration value="dash"/>
<xsd:enumeration value="dashHeavy"/>
<xsd:enumeration value="dashLong"/>
<xsd:enumeration value="dashLongHeavy"/>
<xsd:enumeration value="dotDash"/>
<xsd:enumeration value="dotDashHeavy"/>
<xsd:enumeration value="dotDotDash"/>
<xsd:enumeration value="dotDotDashHeavy"/>
<xsd:enumeration value="wavy"/>
<xsd:enumeration value="wavyHeavy"/>
<xsd:enumeration value="wavyDbl"/>
</xsd:restriction>
<xsd:group name="EG_TextUnderlineLine">
<xsd:choice>
<xsd:element name="uLnTx" type="CT_TextUnderlineLineFollowText"/>
<xsd:element name="uLn" type="CT_LineProperties" minOccurs="0"/>
</xsd:choice>
</xsd:group>
<xsd:group name="EG_TextUnderlineFill">
<xsd:choice>
<xsd:element name="uFillTx" type="CT_TextUnderlineFillFollowText"/>
<xsd:element name="uFill" type="CT_TextUnderlineFillGroupWrapper"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="CT_TextUnderlineLineFollowText"/>
<xsd:complexType name="CT_TextUnderlineFillFollowText"/>
<xsd:complexType name="CT_TextUnderlineFillGroupWrapper">
<xsd:group ref="EG_FillProperties"/>
</xsd:complexType>
Font Color
Overview
Font color is a particular case of the broader topic of fill, the case of solid fill, in which a drawing element is filled with
a single color. Other possible fill types are gradient, picture, pattern, and background (transparent).
Any drawing element that can have a fill can have a solid fill, or color. Elements that can have a fill include shape,
line, text, table, table cell, and slide background.
Scope
This analysis focuses on font color, although much of it is general to solid fills. The focus is simply to enable getting
to feature implementation as quickly as possible, just not before its clear I understand how it works in general.
Candidate API
New members:
• Font.color
• ColorFormat(fillable_elm)
• ColorFormat.type
• ColorFormat.rgb
• ColorFormat.theme_color
• ColorFormat.brightness
• RGBColor(r, g, b)
• RGBColor.__str__
• RGBColor.from_str(rgb_str)
Enumerations:
• MSO_COLOR_TYPE_INDEX
• MSO_THEME_COLOR_INDEX
Protocol:
XML specimens
Here is a representative sample of the various font color cases as they appear in the XML, as produced by PowerPoint.
Some inoperative attributes have been removed for clarity.
Baseline run:
<a:r>
<a:rPr/>
<a:t>test text</a:t>
</a:r>
set to a specific RGB color, using color wheel; HSB sliders yield the same:
<a:rPr>
<a:solidFill>
<a:srgbClr val="748E1D"/>
</a:solidFill>
</a:rPr>
<a:rPr>
<a:solidFill>
<a:schemeClr val="tx2"/>
</a:solidFill>
</a:rPr>
<a:rPr>
<a:solidFill>
<a:schemeClr val="accent2">
<a:lumMod val="20000"/>
<a:lumOff val="80000"/>
</a:schemeClr>
</a:solidFill>
</a:rPr>
PowerPoint API
Changing the color of text in the PowerPoint API is accomplished with something like this:
Debug.Print font.Color.RGB
> 3678732
The ColorFormat object is the first interesting object here, the type of object returned by TextRange.Font.Color.
It includes the following properties that will likely have counterparts in python-pptx:
Brightness Returns or sets the brightness of the specified object. The value for this property must be a number from
-1.0 (darker) to 1.0 (lighter), with 0 corresponding to no brightness adjustment. Read/write Single. Note: this
corresponds to selecting an adjusted theme color from the PowerPoint ribbon color picker, like ‘Accent 1, 40%
Lighter’.
ObjectThemeColor Returns or sets the theme color of the specified ColorFormat object. Read/Write. Accepts and
returns values from the enumeration MsoThemeColorIndex.
RGB Returns or sets the red-green-blue (RGB) value of the specified color. Read/write.
Type Represents the type of color. Read-only.
Legacy properties
Resources
Behaviors
The API method Brightness corresponds to the UI action of selecting an auto-generated tint or shade of a theme
color from the PowerPoint ribbon color picker:
Setting font color to Accent 1 from the UI produces:
<a:rPr>
<a:solidFill>
<a:schemeClr val="accent1"/>
</a:solidFill>
</a:rPr>
fnt.Color.ObjectThemeColor = msoThemeColorAccent1
Setting font color to Accent 1, Lighter 40% (40% tint) from the PowerPoint UI produces this XML:
<a:rPr>
<a:solidFill>
<a:schemeClr val="accent1">
<a:lumMod val="60000"/>
<a:lumOff val="40000"/>
</a:schemeClr>
</a:solidFill>
</a:rPr>
fnt.Color.Brightness = 0.4
Setting font color to Accent 1, Darker 25% (25% shade) from the UI results in the following XML. Note that no
<a:lumOff> element is used.:
<a:rPr>
<a:solidFill>
<a:schemeClr val="accent1">
<a:lumMod val="75000"/>
</a:schemeClr>
</a:solidFill>
</a:rPr>
fnt.Color.Brightness = -0.25
Calling TintAndShade with a positive value (between 0 and 1) causes a tint element to be inserted, but I’m not at
all sure why and when one would want to use it rather than the Brightness property.:
fnt.Color.TintAndShade = 0.75
<a:rPr>
<a:solidFill>
<a:schemeClr val="accent1">
<a:tint val="25000"/>
</a:schemeClr>
</a:solidFill>
</a:rPr>
<xsd:complexType name="CT_SolidColorFillProperties">
<xsd:sequence>
<xsd:group ref="EG_ColorChoice" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:group name="EG_ColorChoice">
<xsd:choice>
<xsd:element name="scrgbClr" type="CT_ScRgbColor" minOccurs="1" maxOccurs="1"/>
<xsd:element name="srgbClr" type="CT_SRgbColor" minOccurs="1" maxOccurs="1"/>
<xsd:element name="hslClr" type="CT_HslColor" minOccurs="1" maxOccurs="1"/>
<xsd:element name="sysClr" type="CT_SystemColor" minOccurs="1" maxOccurs="1"/>
<xsd:element name="schemeClr" type="CT_SchemeColor" minOccurs="1" maxOccurs="1"/>
<xsd:element name="prstClr" type="CT_PresetColor" minOccurs="1" maxOccurs="1"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="CT_SRgbColor">
<xsd:sequence>
<xsd:group ref="EG_ColorTransform" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
(continues on next page)
<xsd:complexType name="CT_SchemeColor">
<xsd:sequence>
<xsd:group ref="EG_ColorTransform" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="val" type="ST_SchemeColorVal" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_PresetColor">
<xsd:sequence>
<xsd:group ref="EG_ColorTransform" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="val" type="ST_PresetColorVal" use="required"/>
</xsd:complexType>
<xsd:group name="EG_ColorTransform">
<xsd:choice>
<xsd:element name="tint" type="CT_PositiveFixedPercentage" minOccurs="1"
˓→maxOccurs="1"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="CT_Percentage">
<xsd:attribute name="val" type="ST_Percentage" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ST_Percentage">
<xsd:union memberTypes="s:ST_Percentage"/>
</xsd:simpleType>
<xsd:simpleType name="ST_Percentage">
<xsd:restriction base="xsd:string">
<xsd:pattern value="-?[0-9]+(\.[0-9]+)?%"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_HexColorRGB">
<xsd:restriction base="xsd:hexBinary">
<xsd:length value="3" fixed="true"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_SchemeColorVal">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="bg1"/>
<xsd:enumeration value="tx1"/>
<xsd:enumeration value="bg2"/>
<xsd:enumeration value="tx2"/>
<xsd:enumeration value="accent1"/>
<xsd:enumeration value="accent2"/>
<xsd:enumeration value="accent3"/>
<xsd:enumeration value="accent4"/>
<xsd:enumeration value="accent5"/>
<xsd:enumeration value="accent6"/>
<xsd:enumeration value="hlink"/>
<xsd:enumeration value="folHlink"/>
<xsd:enumeration value="phClr"/>
<xsd:enumeration value="dk1"/>
(continues on next page)
<xsd:group name="EG_FillProperties">
<xsd:choice>
<xsd:element name="noFill" type="CT_NoFillProperties" minOccurs="1"
˓→maxOccurs="1"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="CT_NoFillProperties"/>
<xsd:complexType name="CT_GradientFillProperties">
<xsd:sequence>
<xsd:element name="gsLst" type="CT_GradientStopList" minOccurs="0" maxOccurs="1
˓→"/>
</xsd:sequence>
<xsd:attribute name="flip" type="ST_TileFlipMode" use="optional"/>
<xsd:attribute name="rotWithShape" type="xsd:boolean" use="optional"/>
</xsd:complexType>
Enumerations
MsoColorType
http://msdn.microsoft.com/en-us/library/office/aa432491(v=office.12).aspx
msoColorTypeRGB 1 - Color is determined by values of red, green, and blue.
msoColorTypeScheme 2 - Color is defined by an application-specific scheme.
msoColorTypeCMYK 3 - Color is determined by values of cyan, magenta, yellow, and black.
msoColorTypeCMS 4 - Color Management System color type.
msoColorTypeInk 5 - Not supported.
msoColorTypeMixed -2 - Not supported.
MsoThemeColorIndex
http://msdn.microsoft.com/en-us/library/office/aa432702(v=office.12).aspx
Value Objects
RGB RGBColor would be an immutable value object that could be reused as often as needed and not tied to any part
of the underlying XML tree.
# XML
<a:ln>
<a:solidFill>
<a:srgbClr val="123456"/>
</a:solidFill>
</a:ln>
Font typeface
Overview
PowerPoint allows the font of text elements to be changed from, for example, Verdana to Arial. This aspect of a font
is its typeface, as opposed to its size (e.g. 18 points) or style (e.g. bold, italic).
Related MS API
• Font.Name
• Font.NameAscii
• Font.NameComplexScript
• Font.NameFarEast
• Font.NameOther
Protocol
XML specimens
Here is a representative sample of textbox XML showing the effect of applying a non-default typeface.
Baseline default textbox:
<p:txBody>
<a:bodyPr wrap="none" rtlCol="0">
<a:spAutoFit/>
</a:bodyPr>
<a:lstStyle/>
<a:p>
<a:r>
<a:rPr lang="en-US" dirty="0" smtClean="0"/>
<a:t>Baseline default textbox, no adjustments of any kind</a:t>
</a:r>
<a:endParaRPr lang="en-US" dirty="0"/>
</a:p>
</p:txBody>
<p:txBody>
<a:bodyPr wrap="none" rtlCol="0">
<a:spAutoFit/>
</a:bodyPr>
<a:lstStyle/>
<a:p>
<a:r>
<a:rPr lang="en-US" dirty="0" smtClean="0">
<a:latin typeface="Verdana"/>
<a:cs typeface="Verdana"/>
</a:rPr>
<a:t>A textbox with Verdana typeface applied to shape, not text selection</a:t>
</a:r>
<a:endParaRPr lang="en-US" dirty="0">
<a:latin typeface="Verdana"/>
<a:cs typeface="Verdana"/>
</a:endParaRPr>
</a:p>
</p:txBody>
<p:txBody>
<a:bodyPr wrap="none" rtlCol="0">
<a:spAutoFit/>
</a:bodyPr>
<a:lstStyle/>
<a:p>
<a:pPr algn="ctr"/>
<a:r>
<a:rPr lang="en-US" dirty="0" smtClean="0">
<a:latin typeface="Arial Black"/>
<a:cs typeface="Arial Black"/>
</a:rPr>
<a:t>textbox with multiple runs having typeface</a:t>
</a:r>
<a:br>
<a:rPr lang="en-US" dirty="0" smtClean="0">
<a:latin typeface="Arial Black"/>
<a:cs typeface="Arial Black"/>
</a:rPr>
(continues on next page)
Observations
• PowerPoint UI always applies typeface customization at run level rather than paragraph (defRPr) level, even
when applied to shape rather than a specific selection of text.
• PowerPoint applies the same typeface to the <a:latin> and <a:cs> tag when a typeface is selected from
the font pull-down in the UI.
<xsd:complexType name="CT_TextCharacterProperties">
<xsd:sequence>
<xsd:element name="ln" type="CT_LineProperties" minOccurs="0" maxOccurs="1
˓→"/>
</xsd:sequence>
<xsd:attribute name="kumimoji" type="xsd:boolean" use="optional"/>
<xsd:attribute name="lang" type="s:ST_Lang" use="optional"/>
<xsd:attribute name="altLang" type="s:ST_Lang" use="optional"/>
<xsd:attribute name="sz" type="ST_TextFontSize" use="optional"/>
<xsd:attribute name="b" type="xsd:boolean" use="optional"/>
(continues on next page)
<xsd:complexType name="CT_TextFont">
<xsd:attribute name="typeface" type="ST_TextTypeface" use="required"/>
<xsd:attribute name="panose" type="s:ST_Panose" use="optional"/>
<xsd:attribute name="pitchFamily" type="ST_PitchFamily" use="optional" default="0"/
˓→>
</xsd:complexType>
<xsd:simpleType name="ST_TextTypeface">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
Hyperlinks
Overview
A run or shape can actually have two distinct link behaviors, one for clicking and another for rolling over with the
mouse. These are independent; a run or shape can have one, the other, both, or neither. These are the two hyperlink
types reported by the Hyperlink.type attribute and using enumeration values from MsoHyperlinkType.
Start with Run since that’s the current use case and doesn’t require working out exactly which shapes can be hyper-
linked.
r = p.add_run()
r.text = 'link to python-pptx @ GitHub'
hlink = r.hyperlink
hlink.address = 'https://github.com/scanny/python-pptx'
Roadmap items
Resources
Candidate Protocol
Add a hyperlink:
p = shape.text_frame.paragraphs[0]
r = p.add_run()
r.text = 'link to python-pptx @ GitHub'
hlink = r.hyperlink
hlink.address = 'https://github.com/scanny/python-pptx'
Delete a hyperlink:
r.hyperlink = None
# or -----------
A Hyperlink instance is lazy-created on first reference. The object persists until garbage collected once created. The
link XML is not written until .address is specified. Setting hlink.address to None or ‘’ causes the hlink entry to
be removed if present.
Candidate API
_Run.hyperlink
Shape.hyperlink
Hyperlink
Enumerations
Open questions
• What is the precise scope of shape types that may have a hyperlink applied?
• does leading and trailing space around a hyperlink work as expected?
• not sure what PowerPoint does if you select multiple runs and then insert a hyperlink, like including a stretch of
bold text surrounded by plain text in the selection.
XML specimens
<p:sp>
<p:nvSpPr>
<p:cNvPr id="2" name="Rectangle 1">
<a:hlinkClick r:id="rId2"/>
</p:cNvPr>
<p:cNvSpPr/>
<p:nvPr/>
</p:nvSpPr>
...
<p:sp>
<a:p>
<a:r>
<a:rPr lang="en-US" dirty="0" smtClean="0"/>
<a:t>Code is available at </a:t>
</a:r>
<a:r>
<a:rPr lang="en-US" dirty="0" smtClean="0">
<a:hlinkClick r:id="rId2"/>
</a:rPr>
<a:t>the python-pptx repository on GitHub</a:t>
</a:r>
<a:endParaRPr lang="en-US" dirty="0"/>
</a:p>
<xsd:complexType name="CT_TextCharacterProperties">
<xsd:sequence>
<xsd:element name="ln" type="CT_LineProperties" minOccurs="0"/
˓→>
</xsd:sequence>
... 19 attributes ...
</xsd:complexType>
<xsd:complexType name="CT_Hyperlink">
<xsd:sequence>
<xsd:element name="snd" type="CT_EmbeddedWAVAudioFile" minOccurs="0"/>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute ref="r:id"/> <!-- type="ST_RelationshipId" -->
<xsd:attribute name="invalidUrl" type="xsd:string" default=""/>
<xsd:attribute name="action" type="xsd:string" default=""/>
<xsd:attribute name="tgtFrame" type="xsd:string" default=""/>
<xsd:attribute name="tooltip" type="xsd:string" default=""/>
<xsd:attribute name="history" type="xsd:boolean" default="true"/>
<xsd:attribute name="highlightClick" type="xsd:boolean" default="false"/>
<xsd:attribute name="endSnd" type="xsd:boolean" default="false"/>
</xsd:complexType>
<xsd:simpleType name="ST_RelationshipId">
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
Presentation
Presentation properties
Overview
The presentation object has a few interesting properties. Right now I’m interested in slide size.
Protocol
XML specimens
<p:presentation>
<p:sldMasterIdLst>
<p:sldMasterId id="2147483897" r:id="rId1"/>
</p:sldMasterIdLst>
<p:notesMasterIdLst>
<p:notesMasterId r:id="rId153"/>
</p:notesMasterIdLst>
<p:sldIdLst>
<p:sldId id="772" r:id="rId3"/>
<p:sldId id="1244" r:id="rId4"/>
</p:sldIdLst>
<p:sldSz cx="9144000" cy="6858000" type="screen4x3"/>
<p:notesSz cx="6858000" cy="9296400"/>
<p:defaultTextStyle>
<a:defPPr>
<a:defRPr lang="en-US"/>
</a:defPPr>
<a:lvl1pPr algn="l" rtl="0" fontAlgn="base">
<a:spcBef>
<a:spcPct val="0"/>
</a:spcBef>
<a:spcAft>
<a:spcPct val="0"/>
</a:spcAft>
<a:defRPr kern="1200">
<a:solidFill>
<a:schemeClr val="tx1"/>
</a:solidFill>
<a:latin typeface="Arial" pitchFamily="34" charset="0"/>
<a:ea typeface=" " pitchFamily="34" charset="-128"/>
<a:cs typeface="+mn-cs"/>
(continues on next page)
<xsd:complexType name="CT_Presentation">
<xsd:sequence>
<xsd:element name="sldMasterIdLst" type="CT_SlideMasterIdList" minOccurs="0
˓→"/>
</xsd:sequence>
<xsd:attribute name="serverZoom" type="a:ST_Percentage" default=
˓→"50%"/>
<xsd:complexType name="CT_SlideSize">
<xsd:attribute name="cx" type="ST_SlideSizeCoordinate" use="required"/>
<xsd:attribute name="cy" type="ST_SlideSizeCoordinate" use="required"/>
<xsd:attribute name="type" type="ST_SlideSizeType" default="custom"/>
</xsd:complexType>
<xsd:simpleType name="ST_SlideSizeType">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="screen4x3"/>
<xsd:enumeration value="letter"/>
<xsd:enumeration value="A4"/>
<xsd:enumeration value="35mm"/>
<xsd:enumeration value="overhead"/>
<xsd:enumeration value="banner"/>
<xsd:enumeration value="custom"/>
<xsd:enumeration value="ledger"/>
<xsd:enumeration value="A3"/>
<xsd:enumeration value="B4ISO"/>
<xsd:enumeration value="B5ISO"/>
<xsd:enumeration value="B4JIS"/>
<xsd:enumeration value="B5JIS"/>
<xsd:enumeration value="hagakiCard"/>
<xsd:enumeration value="screen16x9"/>
<xsd:enumeration value="screen16x10"/>
</xsd:restriction>
</xsd:simpleType>
DrawingML
Color
ColorFormat object . . .
<xsd:group name="EG_ColorChoice">
<xsd:choice>
<xsd:element name="scrgbClr" type="CT_ScRgbColor" minOccurs="1" maxOccurs="1"/>
<xsd:element name="srgbClr" type="CT_SRgbColor" minOccurs="1" maxOccurs="1"/>
<xsd:element name="hslClr" type="CT_HslColor" minOccurs="1" maxOccurs="1"/>
<xsd:element name="sysClr" type="CT_SystemColor" minOccurs="1" maxOccurs="1"/>
<xsd:element name="schemeClr" type="CT_SchemeColor" minOccurs="1" maxOccurs="1"/>
(continues on next page)
<xsd:complexType name="CT_ScRgbColor">
<xsd:sequence>
<xsd:group ref="EG_ColorTransform" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="r" type="ST_Percentage" use="required"/>
<xsd:attribute name="g" type="ST_Percentage" use="required"/>
<xsd:attribute name="b" type="ST_Percentage" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_SRgbColor">
<xsd:sequence>
<xsd:group ref="EG_ColorTransform" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="val" type="s:ST_HexColorRGB" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_HslColor">
<xsd:sequence>
<xsd:group ref="EG_ColorTransform" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="hue" type="ST_PositiveFixedAngle" use="required"/>
<xsd:attribute name="sat" type="ST_Percentage" use="required"/>
<xsd:attribute name="lum" type="ST_Percentage" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_SystemColor">
<xsd:sequence>
<xsd:group ref="EG_ColorTransform" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="val" type="ST_SystemColorVal" use="required"/>
<xsd:attribute name="lastClr" type="s:ST_HexColorRGB" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_SchemeColor">
<xsd:sequence>
<xsd:group ref="EG_ColorTransform" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="val" type="ST_SchemeColorVal" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_PresetColor">
<xsd:sequence>
<xsd:group ref="EG_ColorTransform" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="val" type="ST_PresetColorVal" use="required"/>
</xsd:complexType>
<xsd:group name="EG_ColorTransform">
<xsd:choice>
<xsd:element name="tint" type="CT_PositiveFixedPercentage" minOccurs="1"
˓→maxOccurs="1"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="CT_Percentage">
<xsd:attribute name="val" type="ST_Percentage" use="required"/>
(continues on next page)
<xsd:simpleType name="ST_Percentage">
<xsd:union memberTypes="ST_PercentageDecimal s:ST_Percentage"/>
</xsd:simpleType>
<xsd:simpleType name="ST_PercentageDecimal">
<xsd:restriction base="xsd:int"/>
</xsd:simpleType>
<xsd:simpleType name="ST_HexColorRGB">
<xsd:restriction base="xsd:hexBinary">
<xsd:length value="3" fixed="true"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_SchemeColorVal">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="bg1"/>
<xsd:enumeration value="tx1"/>
<xsd:enumeration value="bg2"/>
<xsd:enumeration value="tx2"/>
<xsd:enumeration value="accent1"/>
<xsd:enumeration value="accent2"/>
<xsd:enumeration value="accent3"/>
<xsd:enumeration value="accent4"/>
<xsd:enumeration value="accent5"/>
<xsd:enumeration value="accent6"/>
<xsd:enumeration value="hlink"/>
<xsd:enumeration value="folHlink"/>
<xsd:enumeration value="phClr"/>
<xsd:enumeration value="dk1"/>
<xsd:enumeration value="lt1"/>
<xsd:enumeration value="dk2"/>
<xsd:enumeration value="lt2"/>
</xsd:restriction>
</xsd:simpleType>
Overview
In simple terms, fill is the color of a shape. The term fill is used to distinguish from line, the border around a shape,
which can have a different color. It turns out that a line has a fill all its own, but that’s another topic.
While having a solid color fill is perhaps most common, it is just one of several possible fill types. A shape can have
the following types of fill:
• solid (color)
Scope
This analysis initially focused on solid fill for an autoshape (including text box). Later, pattern fills were added and
then analysis for gradient fills. Picture fills are still outstanding.
• FillFormat.type – MSO_FILL.SOLID or None for a start
• FillFormat.solid() – changes fill type to <a:solidFill>
• FillFormat.patterned() – changes fill type to <a:pattFill>
• FillFormat.fore_color – read/write foreground color
maybe later:
• FillFormat.transparency – adds/changes <a:alpha> or something
Protocol
Accessing fill. A shape object has a .fill property that returns a FillFormat object. The .fill property is idempotent; it
always returns the same FillFormat object for a given shape object:
>>> fill.type
MSO_FILL.SOLID (1)
The fill type may also be None, indicating the shape’s fill is inherited from the style hierarchy (generally the theme
linked to the slide master). This is the default for a new shape:
The fill type partially determines the valid calls on the fill:
>>> fill.solid()
>>> fill.type
1 # MSO_FILL.SOLID
>>> fill.transparency
0.0
>>> fill.transparency = 0.25 # sets opacity to 75%
>>> sp.fill = None # removes any fill, fill is inherited from theme
fill.solid()
fill.fore_color.rgb = RGBColor(0x01, 0x23, 0x45)
fill.fore_color.theme_color = MSO_THEME_COLOR.ACCENT_1
fill.fore_color.brightness = 0.25
fill.transparency = 0.25
shape.fill = None
fill.background() # is almost free once the rest is in place
Pattern Fill.
Enumerations
MsoFillType
http://msdn.microsoft.com/EN-US/library/office/ff861408.aspx
msoFillBackground 5 – Fill is the same as the background.
msoFillGradient 3 – Gradient fill.
msoFillPatterned 2 – Patterned fill.
msoFillPicture 6 – Picture fill.
msoFillSolid 1 – Solid fill.
msoFillTextured 4 – Textured fill.
msoFillMixed -2 – Mixed fill.
XML specimens
Patterned fill:
<a:pattFill prst="ltDnDiag">
<a:fgClr>
<a:schemeClr val="accent1"/>
</a:fgClr>
<a:bgClr>
<a:schemeClr val="accent6"/>
</a:bgClr>
</a:pattFill>
XML semantics
• No ‘prst‘ attribute. When an a:pattFill element contains no prst attribute, the pattern defaults to 5% (dotted).
This is the first one in the pattern gallery in the PowerPoint UI.
• No ‘fgClr‘ or ‘bgClr‘ elements. When an a:pattFill element contains no fgClr or bgClr chile elements, the
colors default to black and white respectively.
<xsd:complexType name="CT_ShapeProperties">
<xsd:sequence>
<xsd:element name="xfrm" type="CT_Transform2D" minOccurs="0"/>
<xsd:group ref="EG_Geometry" minOccurs="0"/>
<xsd:group ref="EG_FillProperties" minOccurs="0"/>
<xsd:element name="ln" type="CT_LineProperties" minOccurs="0"/>
<xsd:group ref="EG_EffectProperties" minOccurs="0"/>
<xsd:element name="scene3d" type="CT_Scene3D" minOccurs="0"/>
<xsd:element name="sp3d" type="CT_Shape3D" minOccurs="0"/>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
(continues on next page)
<xsd:group name="EG_Geometry">
<xsd:choice>
<xsd:element name="custGeom" type="CT_CustomGeometry2D"/>
<xsd:element name="prstGeom" type="CT_PresetGeometry2D"/>
</xsd:choice>
</xsd:group>
<xsd:group name="EG_FillProperties">
<xsd:choice>
<xsd:element name="noFill" type="CT_NoFillProperties"/>
<xsd:element name="solidFill" type="CT_SolidColorFillProperties"/>
<xsd:element name="gradFill" type="CT_GradientFillProperties"/>
<xsd:element name="blipFill" type="CT_BlipFillProperties"/>
<xsd:element name="pattFill" type="CT_PatternFillProperties"/>
<xsd:element name="grpFill" type="CT_GroupFillProperties"/>
</xsd:choice>
</xsd:group>
<xsd:group name="EG_EffectProperties">
<xsd:choice>
<xsd:element name="effectLst" type="CT_EffectList"/>
<xsd:element name="effectDag" type="CT_EffectContainer"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="CT_BlipFillProperties">
<xsd:sequence>
<xsd:element name="blip" type="CT_Blip" minOccurs="0"/>
<xsd:element name="srcRect" type="CT_RelativeRect" minOccurs="0"/>
<xsd:choice minOccurs="0"> <!-- EG_FillModeProperties -->
<xsd:element name="tile" type="CT_TileInfoProperties"/>
<xsd:element name="stretch" type="CT_StretchInfoProperties"/>
</xsd:choice>
</xsd:sequence>
<xsd:attribute name="dpi" type="xsd:unsignedInt"/>
<xsd:attribute name="rotWithShape" type="xsd:boolean"/>
</xsd:complexType>
<xsd:complexType name="CT_GradientFillProperties">
<xsd:sequence>
<xsd:element name="gsLst" type="CT_GradientStopList" minOccurs="0"/>
<xsd:choice minOccurs="0"> <!-- EG_ShadeProperties -->
<xsd:element name="lin" type="CT_LinearShadeProperties"/>
<xsd:element name="path" type="CT_PathShadeProperties"/>
</xsd:choice>
<xsd:element name="tileRect" type="CT_RelativeRect" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="flip" type="ST_TileFlipMode"/>
<xsd:attribute name="rotWithShape" type="xsd:boolean"/>
</xsd:complexType>
<xsd:complexType name="CT_GroupFillProperties"/>
<xsd:complexType name="CT_PatternFillProperties">
<xsd:sequence>
<xsd:element name="fgClr" type="CT_Color" minOccurs="0"/>
<xsd:element name="bgClr" type="CT_Color" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="prst" type="ST_PresetPatternVal"/>
</xsd:complexType>
<xsd:complexType name="CT_Color">
<xsd:sequence>
<xsd:group ref="EG_ColorChoice"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_SolidColorFillProperties">
<xsd:sequence>
<xsd:group ref="EG_ColorChoice" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:group name="EG_ColorChoice">
<xsd:choice>
<xsd:element name="scrgbClr" type="CT_ScRgbColor"/>
<xsd:element name="srgbClr" type="CT_SRgbColor"/>
<xsd:element name="hslClr" type="CT_HslColor"/>
<xsd:element name="sysClr" type="CT_SystemColor"/>
<xsd:element name="schemeClr" type="CT_SchemeColor"/>
<xsd:element name="prstClr" type="CT_PresetColor"/>
</xsd:choice>
</xsd:group>
<xsd:simpleType name="ST_PresetPatternVal">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="pct5"/>
<xsd:enumeration value="pct10"/>
<xsd:enumeration value="pct20"/>
<xsd:enumeration value="pct25"/>
<xsd:enumeration value="pct30"/>
<xsd:enumeration value="pct40"/>
<xsd:enumeration value="pct50"/>
<xsd:enumeration value="pct60"/>
<xsd:enumeration value="pct70"/>
<xsd:enumeration value="pct75"/>
<xsd:enumeration value="pct80"/>
<xsd:enumeration value="pct90"/>
<xsd:enumeration value="horz"/>
<xsd:enumeration value="vert"/>
<xsd:enumeration value="ltHorz"/>
<xsd:enumeration value="ltVert"/>
<xsd:enumeration value="dkHorz"/>
<xsd:enumeration value="dkVert"/>
<xsd:enumeration value="narHorz"/>
<xsd:enumeration value="narVert"/>
<xsd:enumeration value="dashHorz"/>
<xsd:enumeration value="dashVert"/>
(continues on next page)
Gradient Fill
A gradient fill is a smooth gradual transition between two or more colors. A gradient fill can mimic the shading of
real-life objects and allow a graphic to look less “flat”.
Each “anchor” color and its relative location in the overall transition is known as a stop. A gradient definition gathers
these in a sequence known as the stop list, which contains two or more stops (a gradient with only one stop would be
a solid color).
A gradient also has a path, which specifies the direction of the color transition. Perhaps most common is a linear
path, where the transition is along a straight line, perhaps top-left to bottom-right. Other gradients like radial and
rectangular are possible. The initial implementation supports only a linear path.
Protocol
Staring with a newly-created shape A newly created shape has a fill of None, indicating it’s fill is inherited:
>>> shape = shapes.add_shape(...)
>>> fill = shape.fill
(continues on next page)
Apply a gradient fill A gradient fill is applied by calling the .gradient() method on the FillFormat object. This applies
a two-stop linear gradient in the bottom-to-top direction (90-degrees in UI):
>>> fill.gradient()
>>> fill._fill.xml
<a:gradFill rotWithShape="1">
<a:gsLst>
<a:gs pos="0">
<a:schemeClr val="accent1">
<a:tint val="100000"/>
<a:shade val="100000"/>
<a:satMod val="130000"/>
</a:schemeClr>
</a:gs>
<a:gs pos="100000">
<a:schemeClr val="accent1">
<a:tint val="50000"/>
<a:shade val="100000"/>
<a:satMod val="350000"/>
</a:schemeClr>
</a:gs>
</a:gsLst>
<a:lin ang="16200000" scaled="0"/>
</a:gradFill>
>>> fill.gradient_angle
270.0
>>> fill.gradient_angle = 45
>>> fill.gradient_angle
45.0
Access a stop. The GradientStops sequence provides access to an individual gradient stop.:
>>> len(gradient_stops)
3
Manipulate gradient stop color. The .color property of a gradient stop is a ColorFormat object, which may be
manipulated like any other color to achieve the desired effect:
>>> gradient_stop.position
0.8 # ---represents 80%---
>>> gradient_stop.position = 0.5
>>> gradient_stop.position
0.5
>>> gradient_stops[1].remove()
>>> len(gradient_stops)
2
• Gradient dialog enforces a two-stop minimum in the stops list. A stop that is one of only two stops cannot be
deleted.
• Gradient Gallery . . .
• GradientAngle
• GradientColorType
• GradientDegree
• GradientStops
• GradientStyle
• GradientVariant
• OneColorGradient()
• PresetGradient()
• TwoColorGradient()
Enumerations
MsoFillType
http://msdn.microsoft.com/EN-US/library/office/ff861408.aspx
msoFillBackground 5 – Fill is the same as the background.
msoFillGradient 3 – Gradient fill.
msoFillPatterned 2 – Patterned fill.
msoFillPicture 6 – Picture fill.
MsoGradientStyle
https://msdn.microsoft.com/en-us/vba/office-shared-vba/articles/msogradientstyle-enumeration-office
msoGradientDiagonalDown 4 Diagonal gradient moving from a top corner down to the opposite corner.
msoGradientDiagonalUp 3 Diagonal gradient moving from a bottom corner up to the opposite corner.
msoGradientFromCenter 7 Gradient running from the center out to the corners.
msoGradientFromCorner 5 Gradient running from a corner to the other three corners.
msoGradientFromTitle 6 Gradient running from the title outward.
msoGradientHorizontal 1 Gradient running horizontally across the shape.
msoGradientVertical 2 Gradient running vertically down the shape.
msoGradientMixed -2 Gradient is mixed.
MsoPresetGradientType
XML specimens
XML semantics
<xsd:complexType name="CT_ShapeProperties">
<xsd:sequence>
<xsd:element name="xfrm" type="CT_Transform2D" minOccurs="0"/>
<xsd:choice minOccurs="0"> <!--EG_Geometry-->
<xsd:element name="custGeom" type="CT_CustomGeometry2D"/>
<xsd:element name="prstGeom" type="CT_PresetGeometry2D"/>
</xsd:choice>
<xsd:choice minOccurs="0"> <!--EG_FillProperties-->
<xsd:element name="noFill" type="CT_NoFillProperties"/>
<xsd:element name="solidFill" type="CT_SolidColorFillProperties"/>
<xsd:element name="gradFill" type="CT_GradientFillProperties"/>
<xsd:element name="blipFill" type="CT_BlipFillProperties"/>
<xsd:element name="pattFill" type="CT_PatternFillProperties"/>
<xsd:element name="grpFill" type="CT_GroupFillProperties"/>
</xsd:choice>
<xsd:element name="ln" type="CT_LineProperties" minOccurs="0"/>
<xsd:group ref="EG_EffectProperties" minOccurs="0"/>
<xsd:element name="scene3d" type="CT_Scene3D" minOccurs="0"/>
<xsd:element name="sp3d" type="CT_Shape3D" minOccurs="0"/>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="bwMode" type="ST_BlackWhiteMode"/>
</xsd:complexType>
<xsd:complexType name="CT_GradientFillProperties">
<xsd:sequence>
<xsd:element name="gsLst" type="CT_GradientStopList" minOccurs="0"/>
<xsd:choice minOccurs="0"> <!-- EG_ShadeProperties -->
<xsd:element name="lin" type="CT_LinearShadeProperties"/>
<xsd:element name="path" type="CT_PathShadeProperties"/>
</xsd:choice>
<xsd:element name="tileRect" type="CT_RelativeRect" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="flip" type="ST_TileFlipMode"/>
<xsd:attribute name="rotWithShape" type="xsd:boolean"/>
</xsd:complexType>
<xsd:complexType name="CT_GradientStopList">
<xsd:sequence>
(continues on next page)
<xsd:complexType name="CT_GradientStop">
<xsd:sequence>
<xsd:choice> <!-- EG_ColorChoice --->
<xsd:element name="scrgbClr" type="CT_ScRgbColor"/>
<xsd:element name="srgbClr" type="CT_SRgbColor"/>
<xsd:element name="hslClr" type="CT_HslColor"/>
<xsd:element name="sysClr" type="CT_SystemColor"/>
<xsd:element name="schemeClr" type="CT_SchemeColor"/>
<xsd:element name="prstClr" type="CT_PresetColor"/>
</xsd:choice>
</xsd:sequence>
<xsd:attribute name="pos" type="ST_PositiveFixedPercentage" use="required"/>
</xsd:complexType>
<xsd:complexType name="CT_LinearShadeProperties">
<xsd:attribute name="ang" type="ST_PositiveFixedAngle"/>
<xsd:attribute name="scaled" type="xsd:boolean"/>
</xsd:complexType>
<xsd:complexType name="CT_PathShadeProperties">
<xsd:sequence>
<xsd:element name="fillToRect" type="CT_RelativeRect" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="path" type="ST_PathShadeType" use="optional"/>
</xsd:complexType>
<xsd:complexType name="CT_Color">
<xsd:sequence>
<xsd:group ref="EG_ColorChoice"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CT_RelativeRect">
<xsd:attribute name="l" type="ST_Percentage" default="0%"/>
<xsd:attribute name="t" type="ST_Percentage" default="0%"/>
<xsd:attribute name="r" type="ST_Percentage" default="0%"/>
<xsd:attribute name="b" type="ST_Percentage" default="0%"/>
</xsd:complexType>
<xsd:group name="EG_ColorChoice">
<xsd:choice>
<xsd:element name="scrgbClr" type="CT_ScRgbColor"/>
<xsd:element name="srgbClr" type="CT_SRgbColor"/>
<xsd:element name="hslClr" type="CT_HslColor"/>
<xsd:element name="sysClr" type="CT_SystemColor"/>
<xsd:element name="schemeClr" type="CT_SchemeColor"/>
<xsd:element name="prstClr" type="CT_PresetColor"/>
</xsd:choice>
</xsd:group>
<xsd:simpleType name="ST_PathShadeType">
<xsd:restriction base="xsd:token">
(continues on next page)
<xsd:simpleType name="ST_PositiveFixedAngle">
<xsd:restriction base="ST_Angle">
<xsd:minInclusive value="0"/>
<xsd:maxExclusive value="21600000"/>
</xsd:restriction>
<xsd:simpleType name="ST_PositiveFixedPercentage">
<xsd:union memberTypes="
ST_PositiveFixedPercentageDecimal
s:ST_PositiveFixedPercentage
"/>
</xsd:simpleType>
<xsd:simpleType name="ST_PositiveFixedPercentageDecimal">
<xsd:restriction base="ST_PercentageDecimal">
<xsd:minInclusive value="0"/>
<xsd:maxInclusive value="100000"/>
</xsd:restriction>
</xsd:simpleType>
Line format
Intial scope
• Shape.line, Connector.line to follow, then Cell.border(s).line, possibly text underline and font.line (character
outline)
Protocol
>>> shape.line
<pptx.dml.line.LineFormat instance at x123456789>
>>> shape.fore_color
<pptx.dml.line.LineFormat instance at x123456789>
Notes
MS API
• LineFormat
https://msdn.microsoft.com/en-us/vba/powerpoint-vba/articles/lineformat-object-powerpoint
• LineFormat.DashStyle
https://msdn.microsoft.com/en-us/vba/powerpoint-vba/articles/lineformat-dashstyle-property-powerpoint
• MsoLineDashStyle Enumeration
https://msdn.microsoft.com/en-us/library/aa432639(v=office.12).aspx
Specimen XML
<p:spPr>
<a:xfrm>
<a:off x="950964" y="1101493"/>
<a:ext cx="1257921" cy="0"/>
</a:xfrm>
<a:prstGeom prst="line">
<a:avLst/>
</a:prstGeom>
<a:ln w="57150" cap="rnd" cmpd="thickThin">
<a:gradFill flip="none" rotWithShape="1">
<a:gsLst>
<a:gs pos="0">
<a:schemeClr val="accent1"/>
</a:gs>
<a:gs pos="100000">
<a:srgbClr val="FFFFFF"/>
</a:gs>
</a:gsLst>
<a:lin ang="0" scaled="1"/>
<a:tileRect/>
</a:gradFill>
<a:prstDash val="sysDash"/>
<a:bevel/>
<a:headEnd type="oval"/>
<a:tailEnd type="diamond"/>
</a:ln>
</p:spPr>
<xsd:complexType name="CT_ShapeProperties">
<xsd:sequence>
<xsd:element name="xfrm" type="CT_Transform2D" minOccurs="0"/>
<xsd:group ref="EG_Geometry" minOccurs="0"/>
<xsd:group ref="EG_FillProperties" minOccurs="0"/>
<xsd:element name="ln" type="CT_LineProperties" minOccurs="0"/>
<xsd:group ref="EG_EffectProperties" minOccurs="0"/>
<xsd:element name="scene3d" type="CT_Scene3D" minOccurs="0"/>
<xsd:element name="sp3d" type="CT_Shape3D" minOccurs="0"/>
<xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="bwMode" type="ST_BlackWhiteMode" use="optional"/>
</xsd:complexType>
<xsd:group name="EG_LineFillProperties">
<xsd:choice>
<xsd:element name="noFill" type="CT_NoFillProperties"/>
<xsd:element name="solidFill" type="CT_SolidColorFillProperties"/>
<xsd:element name="gradFill" type="CT_GradientFillProperties"/>
<xsd:element name="pattFill" type="CT_PatternFillProperties"/>
</xsd:choice>
</xsd:group>
<xsd:group name="EG_LineDashProperties">
<xsd:choice>
<xsd:element name="prstDash" type="CT_PresetLineDashProperties"/>
<xsd:element name="custDash" type="CT_DashStopList"/>
</xsd:choice>
</xsd:group>
<xsd:complexType name="CT_PresetLineDashProperties">
<xsd:attribute name="val" type="ST_PresetLineDashVal" use="optional"/>
</xsd:complexType>
<xsd:group name="EG_LineJoinProperties">
<xsd:choice>
<xsd:element name="round" type="CT_LineJoinRound"/>
<xsd:element name="bevel" type="CT_LineJoinBevel"/>
<xsd:element name="miter" type="CT_LineJoinMiterProperties"/>
</xsd:choice>
</xsd:group>
<xsd:group name="EG_EffectProperties">
<xsd:choice>
<xsd:element name="effectLst" type="CT_EffectList"/>
<xsd:element name="effectDag" type="CT_EffectContainer"/>
</xsd:choice>
</xsd:group>
<xsd:simpleType name="ST_LineWidth">
<xsd:restriction base="ST_Coordinate32Unqualified">
<xsd:minInclusive value="0"/>
<xsd:maxInclusive value="20116800"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ST_PresetLineDashVal">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="solid"/>
<xsd:enumeration value="dot"/>
<xsd:enumeration value="dash"/>
<xsd:enumeration value="lgDash"/>
<xsd:enumeration value="dashDot"/>
<xsd:enumeration value="lgDashDot"/>
<xsd:enumeration value="lgDashDotDot"/>
<xsd:enumeration value="sysDash"/>
<xsd:enumeration value="sysDot"/>
<xsd:enumeration value="sysDashDot"/>
<xsd:enumeration value="sysDashDotDot"/>
</xsd:restriction>
</xsd:simpleType>
Package
Updated 2013-06-22
Author Steve Canny
Status WORKING DRAFT
Introduction
The ‘Core’ in core document properties refers to Dublin Core, a metadata standard that defines a core set of elements
to describe resources.
ISO/IEC 29500-2 Section 11
API Sketch
Presentation.core_properties
_CoreProperties():
All string values are limited to 255 chars (unicode chars, not bytes)
• title
• subject
• author
• keywords
• comments
• last_modified_by
• revision (integer)
• created (date in format: ‘2013-04-06T06:03:36Z’)
• modified (date in same format)
• category
Status and company (and many others) are custom properties, held in app.xml.
˓→www.w3.org/2001/XMLSchema-instance">
<cp:lastModifiedBy>Steve Canny</cp:lastModifiedBy>
<cp:revision>2</cp:revision>
<dcterms:created xsi:type="dcterms:W3CDTF">2013-04-06T06:03:36Z</dcterms:created>
<dcterms:modified xsi:type="dcterms:W3CDTF">2013-06-15T06:09:18Z</dcterms:modified>
<cp:category>analysis</cp:category>
</cp:coreProperties>
Schema
<xs:schema
targetNamespace="http://schemas.openxmlformats.org/package/2006/metadata/core-
˓→properties"
xmlns="http://schemas.openxmlformats.org/package/2006/metadata/core-properties"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:dcterms="http://purl.org/dc/terms/"
elementFormDefault="qualified"
blockDefault="#all">
<xs:import
namespace="http://purl.org/dc/elements/1.1/"
schemaLocation="http://dublincore.org/schemas/xmls/qdc/2003/04/02/dc.xsd"/>
<xs:import
namespace="http://purl.org/dc/terms/"
schemaLocation="http://dublincore.org/schemas/xmls/qdc/2003/04/02/dcterms.xsd"/>
<xs:import
id="xml"
namespace="http://www.w3.org/XML/1998/namespace"/>
<xs:complexType name="CT_Keyword">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute ref="xml:lang" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:schema>
Enumerations
Overview
A large number of settings in PowerPoint are a selection between a small, finite set of discrete choices. Often, in the
XML, these are represented by a simple type defined as an enumeration of a set of short string values. This page
describes the strategy for providing access to these sets of values in the various parts of the library that require them.
Notes
• The general strategy is to provide a set of classes, one for each enumeration, that serves as the single source for
all reference and behavior for that enumeration.
• These enumerations correspond one-to-one with Microsoft API enumerations.
• The naming is based on the Microsoft enumeration. .. all-caps snake case from the original mixed-case.
Definitions
member What constitutes a member of an enumeration? What attributes do all members have in common?
out-of-band member Is there such a thing? Or is there just an out-of-band value?
get-value . . . value returned to indicate the current state of a property
set-value . . . value passed to indicate the desired state of a property
Feature requirements
Design principle: All required values and mappings are defined in the enumeration class. All required names, data
structures, and methods are generated by the metaclass. They don’t have to be generated manually.
• [X] feature: dotted name access
enumeration values can be accessed from an enumeration class with dotted notation, e.g. MSO_FOO.
BAR_BAZ
• [X] feature: enumeration value behaves as an int
• [X] feature: __str__ value of enum member is the member name and int value
In order to provide the developer with a directly readable name for an enumeration value (rather than
a raw int), each enum values shall have a __str__ method that returns the member name. E.g.:
>>> run.underline
None
>>> run.underline = True
>>> str(run.underline)
'SINGLE'
>>> run.underline = False
>>> str(run.underline)
'NONE'
>>> run.underline = WD_UNDERLINE.DOUBLE
>>> str(run.underline)
'DOUBLE'
Code Sketches
#!/usr/bin/env python
def alias(*aliases):
"""
Decorating a class with @alias('FOO', 'BAR', ..) allows the class to
be referenced by each of the names provided as arguments.
"""
def decorator(cls):
for alias in aliases:
globals()[alias] = cls
return cls
return decorator
@alias('BAR', 'BAZ')
class FOO(object):
BAR = 'Foobarish'
7.6 Resources
Process Steps
Distribution tests
• manual
• easy_install
• pip
Distribution-related files
• setup.py
• MANIFEST.in
• setup.cfg
Roles
• naive end-user
Use Cases
“Just-works” installation
Install as a dependency
Verify installation
Resources
Recent Notes
• The content type for XML parts (only) is strictly determined by the relationship type. Binary media parts may
have multiple allowable content types.
• Each part type has one and only one relationship type.
About Packages
Open XML PowerPoint files are stored in files with the extension .pptx. These .pptx files are zip archives contain-
ing a separate file for each main component of the presentation along with other files which contain metadata about
the overall presentation and relationships between its components.
The overall collection of files is known as a package. Each file within the package represents a package item,
commonly although sometimes ambiguously referred to simply as an item. Package items that represent high-level
presentation components, such as slides, slide masters, and themes, are referred to as parts. All parts are package
items, but not all package items are parts.
Package items that are not parts are primarily relationship items that express relationships between one part and
another. Examples of relationships include a slide having a relationship to the slide layout it is based on and a slide
master’s relationship to an image such as a logo it displays. There is one special relationship item, the package
relationship item (/_rels/.rels) which contains relationships between the package and certain parts rather than
relationships between parts.
The only other package item is the content types item (/[Content_Types].xml) which contains mappings of
the parts to their content types (roughly MIME types).
Strategy 1
The content type item ([Content_Types].xml actually contains references to all the main parts of the package. So one
approach might be:
1. Have passed in a mapping of content types to target classes that each know how to load themselves from the
xml and a list of relationships. These classes are what OpenXML4J calls an unmarshaller. These would each
look something like:
{ 'application/vnd...slide+xml' : Slide
, 'application/vnd...slideLayout+xml' : SlideLayout
, ...
}
2. Have a ContentType class that can load from a content type item and allow lookups by partname. Have it load
the content type item from the package. Lookups on it first look for an explicit override, but then fall back to
defaults. Not sure yet whether it should try to be smart about whether a package part that looks like one that
should have an override will get fed to the xml default or not.
3. Walk the package directory tree, and as each file is encountered:
OR
3. Walk the relationships tree, starting from /_rels/.rels
• look up its content type in the content type manager
• look up the unmarshaller for that content type
• dispatch the part to the specified unmarshaller for loading
• add the resulting part to the package parts collection
• if it’s a rels file, parse it and associate the relationships with the appropriate source part.
If a content type or unmarshaller is not found, throw an exception and exit. Skip the content type item (already
processed), and for now skip the package relationship item. Infer the corresponding part name from part rels
item names. I think the walk can be configured so rels items are encountered only after their part has been
processed.
4. Resolve all part relationship targets to in-memory references.
Principles upheld:
• If there are any stray items in the package (items not referenced in the content type part), they are identified
and can be dealt with appropriately by throwing an exception if it looks like a package part or just writing it to
the log if it’s an extra file. Can set debug during development to throw an exception either way just to give a
sense of what might typically be found in a package or to give notice that a hand-crafted package has an internal
inconsistency.
• Conversely, if there are any parts referenced in the content type part that are not found in the zip archive, that
throws an exception too.
Random thoughts
I’m starting to think that the packaging module could be a useful general-purpose capability that could be applied to
.docx and .xlsx files in addition to .pptx ones.
Also I’m thinking that a generalized loading strategy that walks the zip archive directory tree and loads files based on
combining what it discovers there with what it can look up in it’s spec tables might be an interesting approach.
I can think of the following possible ways to identify the type of package, not sure which one is most reliable or
definitive:
• Check the file extension. Kind of thinking this should do the trick 99.99% of the time.
• Might not hurt to confirm that by finding an expected directory of /ppt, /word, or /xl.
• A little further on that would be to find /ppt/presentation.xml, /word/document.xml, or /xl/workbook.xml.
• Even further would be to find a relationship in the package relationship item to one of those three and not to any
of the others.
• Another confirmation might be finding a content type in [Content_Types].xml of:
– . . . /presentationml.presentation.main+xml for /ppt/presentation.xml
– . . . /spreadsheetml.sheet.main+xml for /xl/workbook.xml (Note that macro-enabled workbooks use a dif-
ferent content type ‘application/vnd.ms-excel.sheet.macroEnabled.main+xml’, I believe there are variants
for PresentationML as well, used for templates and slide shows.
– . . . /wordprocessingml.document.main+xml for /word/document.xml
It’s probably worth consulting ECMA-376 Part 2 to see if there are any hard rules that might help determine what a
definitive test would be.
An Open XML package part can have one or more relationships to other parts in the package. For example, a slide
layout has a relationship to the slide master it inherits properties from. And if the slide layout includes an image, such
as a company logo, it will also have a relationship to the image part corresponding to that logo’s image file.
Conceptually, a part relationship might be stated:
While these relationships are reciprocal in a way of thinking (e.g. part y is also related to part x), in Open XML they
are generally defined in one direction only. For example, a slide may have a relationship to an image it contains, but
an image never has a stated relationships to a slide. One exception to this is slide masters and slide layouts. A slide
layout has a relationship to the slide master it inherits from at the same time the slide master has a relationship to each
of the slide layouts that inherit from it.
In the example above, part x can be referred to as the source part or from-part, part y as the target part or to-part,
and type z as the relationship type. The relationship type essentially ends up being the part type of the target part (e.g.
image, slide master, etc.).
Each relationship is outbound for its source part and inbound for its target part. The outbound relationships of a part
are those found in its part relationship item, commonly referred to as its “rels file”. Only outbound relationships
are recorded in the package. Inbound relationships are purely abstract, although they can be inferred from outbound
relationships if an application had a need for them.
Not all parts can have outbound relationships. For example, image and presentation properties parts never have
outbound relationships. All parts, however, participate in at least one inbound relationship. Any part with no inbound
relationships could be removed from the package without consequence, and probably should be. For example, if upon
saving it was noticed that a particular image had no inbound relationships, that image would be better not written to
the package. (Makes me wonder whether loading a package by walking its relationship graph might be a good idea in
some instances.)
Each relationship is recorded as a relationship element in the rels file belonging to a specific part. (The package
relationship item /_rels/.rels is the only exception, it belongs to the package, not to any part). Each relationship
entry specifies a part-local relationship id (rId) for the relationship, the relationship type (essentially the part type of
the target, e.g. slide, image), and a path the target part file. The source part is not explicitly stated in the relationship
entry, it is implicitly the part the .rels file belongs to.
These can be thought of as external relationship references in that the rels file is a separate package item, external to
the part itself. However, in certain cases, a relationship may be referenced within the XML of the from-part. These
can be thought of as internal relationship references.
As an example of where an internal relationship reference is required, consider a slide containing images of three
different products. Each picture has a corresponding <p:pic> element in the slide’s shape tree, each of which must
specify the particular image file it displays, distinguishing it from the other two image files related to the slide.
The picture elements specify which of the related images to display using the part-local relationship id (rId) matching
the required image, ‘rId2’ in the example below:
<p:blipFill>
<a:blip r:embed="rId2">
...
</a:blip>
</p:blipFill>
Which is an indirect reference to image1.png specified as the target of ‘rId2’ in the slide’s rels file:
This indirection makes sense as a way to limit the coupling of presentation parts to the mechanics of package compo-
sition. For example, when the XML for the slide part in the example above is being composed, the slide can determine
the reference to the image it’s displaying without reference outside its own natural scope. In contrast, determining the
eventual location and filename of that image in any particular package that was saved would require the slide code to
have visibility into the packaging process, which would prevent packaging being delegated to a separate, black-box
module.
There is also a distinction between implicit and explicit relationships which is described in the spec (ECMA-376-1) in
section 9.2. I haven’t encountered those yet in the context of PresentationML (the spec uses an example of footnotes
from WordprocessingML), so I do not discuss them here.
Relationship Mechanics
Relationship life-cycle
A representation of a relationship must operate effectively in two distinct situations, in-package and in-memory. They
must also support lifecycle transitions from in-package to in-memory and from in-memory back to in-package.
Abstract model
How will dynamic parts (like Slide) interact with its relationship list?
? Should it just add items to the relationship list when it creates new things?
? Does it need some sort of lookup capability in order to delete? Or just have a delete relationship method on
_Relationships or something like that.
Need to come up with a plausible set of use cases to think about a design. Right now the only use case is loading a
template into a presentation and saving a presentation.
• Add an image to a slide.
• Change a slide’s slide layout
• comment, notesSlide, tag, image, and slideLayout are the only outbound relationship types for a slide, although
I expect there are some other DrawingML bits I haven’t accounted for yet.
On reflection I’m thinking there’s not too much urgency on noodling this out too far, the present construction should
work fine for now and be able to be extended without disrupting other code too much.
SCRAP
When loaded into memory, each relationship target must be a reference to an active part object (or at least a part key
that can be resolved to a reference, but why do this lookup multiple times?). This is both because those relationships
can change and also because the package path, while it can be calculated at runtime, is not guaranteed to be stable
(e.g. a new slide can be inserted between two existing ones) and is not finally resolved until the presentation is saved.
• Relationships items specify the relationships between parts of the package, although they are not themselves a
part.
• All relationship items are XML documents having a filename with the extension ‘.rels’ located in a directory
named ‘_rels’ located in the same directory as the part.
• The package relationship item has the URI ‘/_rels/.rels’.
• Part relationship items have the same filename as the part whose relationships they describe, with the ‘.rels’
extension appended as a suffix. For example, the relationship item for a part named /ppt/slides/slide1.
xml would have the URI /ppt/slides/_rels/slide1.xml.rels.
ECMA Spec
...
Sphinx Resources
Documentation Guides
• Nice GitHub Project Style Guide (esp. Commit Style Guide) textmate / restructuredtext.tmbundle
• Python Documentation guide Documenting Python Guide
• Google Python Style Guide
• Read The Docs (readthedocs.org)
• OpenComparison documetation on readthedocs.org
• The Hitchhiker’s Guide to Packaging
Other Resources
Python Metaclasses
In the fullness of time, it might make sense to incorporate some AppleScript steps into the acceptance tests, to make
sure that PowerPoint isn’t barfing after changes. I’ve collected some resources here that I discovered during some
preliminary resource discovery.
Resources
Class Hierarchy
pptx
|
+--.packaging
|
+--_PartCollection
| |
| +--ImageParts
| +--SlideLayoutParts
| +--SlideMasterParts
| +--SlideParts
| +--ThemeParts
|
+--Part
|
+--CollectionPart
| |
| +--ImagePart
| +--SlideLayoutPart
| +--SlideMasterPart
| +--ThemePart
|
+--PresentationPart
+--PresPropsPart
+--SlidePart
+--TableStylesPart
+--ViewPropsPart
Exception hierarchy
-------------------
.. literalinclude:: ../../Lib/test/exception_hierarchy.txt
• Analysis
– Use case
– Aspects of the spec and PowerPoint conventions that bear on the feature
• Implementation strategy
• Test Cases
• Documentation
• Implementation
• Commit
• DOC: Reserved Terms, e.g. package, part, item, element, etc. These have special meaning because of the
terminology of Open XML packages and ElementTree XML conventions. Singleton, collection, perhaps tuple.
• DOC: Variable naming conventions. Variables containing XML elements are named the same as the tag name
of the element they hold. For example: sldMaster = etree.parse(‘sldMaster1.xml’)
• DOC: Suitable for server-side document generation, database publishing, taking tedium out of building intricate
slides that have a distinct pattern, etc.
• DOC: Content Types mapping is discussed in ECMA-376-2 10.1.2 Mapping Content Types
• DOC: Explicit vs. Implicit relationships are discussed in section 9.2 of ECMA-376-1. Basically relationships to
whole parts are explicit and relationships to one of the elements within another part (like a footnote) are implicit.
• DOC: [Open XML SDK How To’s (How do I. . . )| http://207.46.22.237/en-us/library/cc850828.aspx]
• DOC: [Good hints on where formatting comes from in template|http://openxmldeveloper.org/discussions/formats/f/15/t/1301.aspx]
• Set work template slide layouts to standard type names for better layout re-mapping on theme/template change
[http://msdn.microsoft.com/en-us/library/office/cc850846.aspx]
• spTree in cSld is a GroupShape (ShapeGroup?) perhaps Shape and ShapeGroup are . . . ? not sure who should
inherit from the other. GroupShapes can include other GroupShapes.
p
pptx.exc, 119
pptx.util, 120
515
python-pptx Documentation, Release 0.6.22
Symbols add_line_segments()
_BaseAxis (class in pptx.chart.axis), 100 (pptx.shapes.freeform.FreeformBuilder
_BasePlot (class in pptx.chart.plot), 103 method), 75
_BaseSeries (class in pptx.chart.series), 106 add_movie() (pptx.shapes.shapetree.SlideShapes
_Cell (class in pptx.table), 93 method), 67
_Column (class in pptx.table), 92 add_ole_object() (pptx.shapes.shapetree.GroupShapes
_Paragraph (class in pptx.text.text), 113 method), 70
_PlaceholderFormat (class in pptx.shapes.base), add_ole_object() (pptx.shapes.shapetree.SlideShapes
91 method), 68
_Row (class in pptx.table), 92 add_paragraph() (pptx.text.text.TextFrame method),
_Run (class in pptx.text.text), 115 111
add_picture() (pptx.shapes.shapetree.GroupShapes
A method), 70
add_picture() (pptx.shapes.shapetree.SlideShapes
action (pptx.action.ActionSetting attribute), 115
method), 68
ActionSetting (class in pptx.action), 115
add_run() (pptx.text.text._Paragraph method), 113
add_category() (pptx.chart.data.Categories
add_series() (pptx.chart.data.BubbleChartData
method), 95
method), 96
add_category() (pptx.chart.data.CategoryChartData
add_series() (pptx.chart.data.CategoryChartData
method), 94
method), 95
add_chart() (pptx.shapes.shapetree.GroupShapes
add_series() (pptx.chart.data.XyChartData
method), 70
method), 96
add_chart() (pptx.shapes.shapetree.SlideShapes
add_shape() (pptx.shapes.shapetree.GroupShapes
method), 67
method), 71
add_connector() (pptx.shapes.shapetree.GroupShapes
add_shape() (pptx.shapes.shapetree.SlideShapes
method), 70
method), 68
add_connector() (pptx.shapes.shapetree.SlideShapes
add_slide() (pptx.slide.Slides method), 63
method), 67
add_sub_category() (pptx.chart.data.Category
add_data_point() (pptx.chart.data.BubbleSeriesData
method), 96
method), 97
add_table() (pptx.shapes.shapetree.SlideShapes
add_data_point() (pptx.chart.data.XySeriesData
method), 68
method), 97
add_textbox() (pptx.shapes.shapetree.GroupShapes
add_group_shape()
method), 71
(pptx.shapes.shapetree.GroupShapes method),
add_textbox() (pptx.shapes.shapetree.SlideShapes
70
method), 69
add_group_shape()
address (pptx.action.Hyperlink attribute), 116
(pptx.shapes.shapetree.SlideShapes method),
Adjustment (class in pptx.shapes.autoshape), 74
67
AdjustmentCollection (class in
add_line_break() (pptx.text.text._Paragraph
pptx.shapes.autoshape), 74
method), 113
adjustments (pptx.shapes.autoshape.Shape at-
517
python-pptx Documentation, Release 0.6.22
518 Index
python-pptx Documentation, Release 0.6.22
Index 519
python-pptx Documentation, Release 0.6.22
520 Index
python-pptx Documentation, Release 0.6.22
Index 521
python-pptx Documentation, Release 0.6.22
last_printed (pptx.opc.coreprops.CoreProperties M
attribute), 63 major_gridlines (pptx.chart.axis._BaseAxis at-
last_row (pptx.table.Table attribute), 92 tribute), 100
LayoutPlaceholder (class in major_tick_mark (pptx.chart.axis._BaseAxis at-
pptx.shapes.placeholder), 82 tribute), 100
leaf_count (pptx.chart.data.Categories attribute), 95 major_unit (pptx.chart.axis.ValueAxis attribute), 102
left (pptx.shapes.base.BaseShape attribute), 72 MajorGridlines (class in pptx.chart.axis), 102
left (pptx.shapes.graphfrm.GraphicFrame attribute), margin_bottom (pptx.table._Cell attribute), 93
78 margin_bottom (pptx.text.text.TextFrame attribute),
left (pptx.shapes.group.GroupShape attribute), 80 111
left (pptx.shapes.picture.Picture attribute), 77 margin_left (pptx.table._Cell attribute), 93
left (pptx.shapes.placeholder.ChartPlaceholder at- margin_left (pptx.text.text.TextFrame attribute), 112
tribute), 83 margin_right (pptx.table._Cell attribute), 93
left (pptx.shapes.placeholder.MasterPlaceholder at- margin_right (pptx.text.text.TextFrame attribute),
tribute), 81 112
left (pptx.shapes.placeholder.PicturePlaceholder at- margin_top (pptx.table._Cell attribute), 93
tribute), 85 margin_top (pptx.text.text.TextFrame attribute), 112
left (pptx.shapes.placeholder.PlaceholderGraphicFrame Marker (class in pptx.chart.marker), 109
attribute), 88 marker (pptx.chart.point.Point attribute), 111
left (pptx.shapes.placeholder.PlaceholderPicture at- marker (pptx.chart.series.BubbleSeries attribute), 108
tribute), 90 marker (pptx.chart.series.LineSeries attribute), 108
left (pptx.shapes.placeholder.TablePlaceholder at- marker (pptx.chart.series.RadarSeries attribute), 110
tribute), 86 marker (pptx.chart.series.XySeries attribute), 110
Legend (class in pptx.chart.chart), 99 MasterPlaceholder (class in
legend (pptx.chart.chart.Chart attribute), 98 pptx.shapes.placeholder), 81
Length (class in pptx.util), 120 maximum_scale (pptx.chart.axis._BaseAxis attribute),
level (pptx.text.text._Paragraph attribute), 114 100
levels (pptx.chart.category.Categories attribute), 104 merge() (pptx.table._Cell method), 93
levels (pptx.chart.data.Categories attribute), 95 minimum_scale (pptx.chart.axis._BaseAxis attribute),
line (pptx.dml.chtfmt.ChartFormat attribute), 116 101
line (pptx.shapes.autoshape.Shape attribute), 73 minor_tick_mark (pptx.chart.axis._BaseAxis at-
line (pptx.shapes.connector.Connector attribute), 75 tribute), 101
line (pptx.shapes.picture.Picture attribute), 77 minor_unit (pptx.chart.axis.ValueAxis attribute), 102
line (pptx.shapes.placeholder.ChartPlaceholder at- Mm (class in pptx.util), 120
tribute), 83 mm (pptx.util.Length attribute), 120
line (pptx.shapes.placeholder.MasterPlaceholder at- modified (pptx.opc.coreprops.CoreProperties at-
tribute), 81 tribute), 63
line (pptx.shapes.placeholder.PicturePlaceholder at- move_to() (pptx.shapes.freeform.FreeformBuilder
tribute), 85 method), 76
line (pptx.shapes.placeholder.PlaceholderPicture at-
tribute), 90 N
line (pptx.shapes.placeholder.TablePlaceholder at- name (pptx.chart.data.BubbleSeriesData attribute), 97
tribute), 87 name (pptx.chart.data.XySeriesData attribute), 97
line_spacing (pptx.text.text._Paragraph attribute), name (pptx.chart.series._BaseSeries attribute), 106
114 name (pptx.chart.series.AreaSeries attribute), 107
LineFormat (class in pptx.dml.line), 117 name (pptx.chart.series.BarSeries attribute), 107
LineSeries (class in pptx.chart.series), 108 name (pptx.chart.series.BubbleSeries attribute), 108
ln (pptx.shapes.placeholder.ChartPlaceholder at- name (pptx.chart.series.LineSeries attribute), 108
tribute), 83 name (pptx.chart.series.PieSeries attribute), 109
ln (pptx.shapes.placeholder.PicturePlaceholder at- name (pptx.chart.series.RadarSeries attribute), 110
tribute), 85 name (pptx.chart.series.XySeries attribute), 110
ln (pptx.shapes.placeholder.TablePlaceholder attribute), name (pptx.shapes.base.BaseShape attribute), 72
87 name (pptx.shapes.graphfrm.GraphicFrame attribute),
78
522 Index
python-pptx Documentation, Release 0.6.22
Index 523
python-pptx Documentation, Release 0.6.22
524 Index
python-pptx Documentation, Release 0.6.22
Index 525
python-pptx Documentation, Release 0.6.22
526 Index