Working with placeholders

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.

Access a placeholder

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:

>>> prs = Presentation()
>>> slide = prs.slides.add_slide(prs.slide_layouts[8])
>>> for shape in slide.placeholders:
...     print('%d %s' % (shape.placeholder_format.idx, shape.name))
...
0  Title 1
1  Picture Placeholder 2
2  Text Placeholder 3

… then, having the known index in hand, to access it directly:

>>> 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.

Identify and Characterize a placeholder

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:

>>> prs = Presentation()
>>> slide = prs.slides.add_slide(prs.slide_layouts[8])
>>> for shape in slide.shapes:
...     print('%s' % shape.shape_type)
...
PLACEHOLDER (14)
PLACEHOLDER (14)
PLACEHOLDER (14)

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:

>>> for shape in slide.shapes:
...     if shape.is_placeholder:
...         phf = shape.placeholder_format
...         print('%d, %s' % (phf.idx, phf.type))
...
0, TITLE (1)
1, PICTURE (18)
2, BODY (2)

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.

Insert content into a placeholder

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()

The picture placeholder has an insert_picture() method:

>>> prs = Presentation()
>>> slide = prs.slides.add_slide(prs.slide_layouts[8])
>>> placeholder = slide.placeholders[1]  # idx key, not position
>>> placeholder.name
'Picture Placeholder 2'
>>> placeholder.placeholder_format.type
PICTURE (18)
>>> picture = placeholder.insert_picture('my-image.png')

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 attempt 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

>>> prs = Presentation('having-chart-placeholder.pptx')
>>> slide = prs.slides.add_slide(prs.slide_layouts[1])

>>> placeholder = slide.placeholders[10]  # idx key, not position
>>> placeholder.name
'Chart Placeholder 9'
>>> placeholder.placeholder_format.type
CHART (12)

>>> chart_data = ChartData()
>>> chart_data.categories = ['Yes', 'No']
>>> chart_data.add_series('Series 1', (42, 24))

>>> graphic_frame = placeholder.insert_chart(XL_CHART_TYPE.PIE, chart_data)
>>> chart = graphic_frame.chart
>>> chart.chart_type
PIE (5)

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 attempt 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.

Setting the slide title

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'