shape: set z-order of shape in slide
@scanny Any pointers as to where to look in the code for something like this ?
The z-order of shapes on a slide is determined solely by their document order in the slide part (e.g. slide1.xml). So the general gist would be to re-order that sequence of elements. The shapes in a slide are contained in the slide's "shape tree", a <p:spTree> element with the same syntax as the group shape, just the different name. The object I expect you'll want to look at first is pptx.shapes.shapetree.SlideShapeTree and its parent BaseShapeTree, which is what you get from slide.shapes. The _spTree attribute on that object gives you the lxml object for the <p:spTree> element, which would allow you to reorder shapes.
If you see how far you can get with that, feel free to ask more questions about the finer points, as needed :)
Thanks @scanny
We ended up using shapes._spTree.remove and shapes._spTree.insert to swap elements, like you said!
If you can post the operative bit of the code you developed, that would be a help to others who arrive here on search. Glad you got it working :)
An example with a picture:
picture = slide.shapes.add_picture(
image, Cm(left), Cm(top), height=Cm(height)
)
# move picture to background
slide.shapes._spTree.remove(picture._element)
slide.shapes._spTree.insert(2, picture._element) # use the number that does the appropriate job
Awesome, thanks @NotSqrt :)
+1 for this feature request. I tried the example above but it seems to create a slide that crashes powerpoint when opened.
when I try to do this :
shape = shapes.add_shape(MSO_SHAPE.RECTANGLE,left,top,width,height)
slide.shapes._spTree.remove(shape._element)
an error says:
shape object has no attribute ’_Element'
did I make a mistake here?
Looks like a typo. All shapes have the attribute ._element, not ._Element.
It is not a typo actually, I typed shape._element or shape._Element , Error always says:
shape object has no attribute '_Element'
Not a typo
What is the type of the object you get back?
shape = shapes.add_shape(MSO_SHAPE.RECTANGLE, left, top, width, height)
print(shape.__class__) # or perhaps print(shape.__class__.__name__)
And what available attributes to you find when you introspect into shape?
print(dir(shape))
Is there a workaround other than using _spTree.remove and _spTree.insert? It creates corrupted pptx files which generate an alert when opening in MS Powerpoint. Thanks
I don't believe you have to actually remove and insert to change the order. Perhaps counterintuitive to the naming, I believe the .addprevious() and .addnext() lxml methods actually move the XML element in question.
So you could do something like this to move a shape from ninth position to fourth:
# shape will be positioned relative to this one, hence the name "cursor"
cursor_sp = shapes[3]._element
cursor_sp.addprevious(shapes[8]._element)
thanks @scanny! I used the following to move a picture I added using add_picture to the background:
cursor_sp = shapes[0]._element
cursor_sp.addprevious(pic._element)
MS Powerpoint opens the file without complaining
@chrismcmc Glad to hear you got it working :)
Thank you !