1

I'm relatively new to the python-pptx package but I'm finding it very useful.

I've added a slide with the "title and picture and caption" layout.

SLD_LAYOUT_TITLE_AND_PICTURE_AND_CAPTION = 8

prs = Presentation(output_pptx_fp)
slide_layout = prs.slide_layouts[SLD_LAYOUT_TITLE_AND_PICTURE_AND_CAPTION]

slide = prs.slides.add_slide(slide_layout)
shapes = slide.shapes

placeholder_pict = slide.placeholders[1]  # idx key, not position

placeholder_pict.insert_picture(img_path) 

I'm trying to figure out how to reposition the picture placeholder.

By analogy to how I position the title placeholder on the slide, I've tried using:

placeholder_pict.left = Inches(1.96)
placeholder_pict.top = Inches(0.0)

However, this generated an AttributeError.

I've also tried using "left" and "top" arguments to the "insert_picture()" method:

left = Inches(1.96)
top = Inches(0.0)
placeholder_pict.insert_picture(img_path, left, top)

This generated a "TypeError: insert_picture() takes 2 positional arguments but 4 were given"

How do I reposition the picture placeholder on this slide? Did I miss something in the documentation?

UPDATE:

When I try (which is something scanny didn't suggest but I was curious):

picture_left = Inches(1.96)
picture_top = Inches(0.0)
picture = placeholder_pict.insert_picture(img_path, picture_left, picture_top)

I get: "TypeError: insert_picture() takes 2 positional arguments but 4 were given"

When I try (which I believe was scanny's first suggestion):

picture_left = Inches(1.96)
picture_top = Inches(0.0)
shapes.add_picture(img_path, picture_left, picture_top)

the picture is positioned where I want it but it's not in the picture container (which I can live with) and so it's not sized to fit in the picture container (which I can deal with by adding code)

When I try (which I believe was scanny's second suggestion):

picture_left = Inches(0.0)
picture_top = Inches(0.0)
placeholder_pict.left = picture_left
placeholder_pict.top = picture_top
picture = placeholder_pict.insert_picture(img_path)

I get no change. The picture appears on the slide but it's in the same position as when I don't try setting placeholder_pict.left and placeholder_pict.top at all.

When I try (which I believe was scanny's third suggestion):

picture = placeholder_pict.insert_picture(img_path)
picture.left = Inches(0)
picture.top = Inches(0)

I get no picture at all. I've tried zooming out, to see if the picture might have been placed "off the slide" but still no sign of a picture. As far as I can tell, I no longer even have the picture container.

When I try (per scanny's request):

placeholder_pict = slide.placeholders[1]  # idx key, not position
print("placeholder_pict.placeholder_format.type =", placeholder_pict.placeholder_format.type)
print("placeholder_pict.left", placeholder_pict.left, "placeholder_pict.top =", placeholder_pict.top)

I get:
placeholder_pict.placeholder_format.type = PICTURE (18)
placeholder_pict.left 1792288 placeholder_pict.top = 612775

This makes me very puzzled about why I apparently can't successfuly set the placeholder_pict.left and placeholder_pict.top values.

BobInBaltimore
  • 425
  • 5
  • 13

2 Answers2

1

The (initial) location of a placeholder is determined by its location on the slide layout it comes from. So if you want to change the location of a placeholder for all the slides created with that layout, you need to change it on the layout.

This is accomplished by using a starting template PPTX of your own, and editing its layouts to suit by hand, using PowerPoint.

If all you want to do is change the position of a single shape in a particular case, you need to understand that a placeholder is an "empty" shape, or shape container. You need to change the location of the shape that results from the .insert_picture() call:

picture = placeholder_pict.insert_picture(...)
picture.left = Inches(1.96)
picture.top = Inches(0.0)

This is described in the documentation at and around here: http://python-pptx.readthedocs.io/en/latest/user/placeholders-using.html#insert-content-into-a-placeholder

scanny
  • 26,423
  • 5
  • 54
  • 80
  • Thanks! I looked at that section but I obviously missed its significance. I'll go back and re-read it. I also appreciate the clarification about a placeholder being a shape container - that helps as well. – BobInBaltimore Mar 14 '18 at 17:56
  • OK, when I try using "picture.left = Inches(1.96)" and "picture.top = Inches(0.0)", my picture vanishes. It also vanishes for any value of picture.left and picture.top I've tried. Any ideas / suggestions? (Sorry about not using code format. I can't figure out how to do that in a comment.) – BobInBaltimore Mar 14 '18 at 18:27
  • What happens when you just do `shapes.add_picture(left, top)`? The other thing you can try is setting left and top on placeholder *before* inserting picture. You can also try `picture.left = 0; picture.top = 0` which should put it at top-left corner of slide. Hard to say more without seeing resulting .pptx file. Also, are you sure the placeholder you're getting is a picture placeholder? Try `print(placeholder.placeholder_format.type)` and `print(placeholder.left, placeholder.top)` to see what you get. – scanny Mar 14 '18 at 20:47
  • Again, thanks for your help and for developing and supporting an extremely useful Python package. I've responded to your previous comment by updating my original post. – BobInBaltimore Mar 15 '18 at 16:46
1

In light of some additional observations, it appears this case exposes some "quirks" in how PowerPoint works.

The short answer is that you need to set width and height explicitly if you want to change left and top, otherwise they default to 0, which causes the shape to "disappear".

This code should illuminate the situation a bit:

prs = Presentation()
slide_layout = prs.slide_layouts[PICTURE_LAYOUT_IDX]
slide = prs.slides.add_slide(slide_layout)
shapes = slide.shapes

placeholder = slide.placeholders[1]
print(placeholder.left.inches, placeholder.top.inches)

# ---note that all these actions are *before* the image is inserted---

placeholder.left = Inches(3)
print(placeholder.left.inches)

print(placeholder.width)
placeholder.width = Inches(3)
print(placeholder.left.inches)

print(placeholder.height)
placeholder.height = Inches(3)
print(placeholder.height)

Basically what this indicates is that a shape's inheritance of position-and-size from its layout placeholder is all-or-nothing. As soon as you set one of those explicitly, you need to set all of them.

scanny
  • 26,423
  • 5
  • 54
  • 80