Repository navigation
feature set: SmartArt support #83
Description
I had a look into what it might take to be able to use placeholders that are within SmartArt elements (as a workaround which may be easier than full support for inserting new SmartArt), but it seems like some extra plumbing is needed - the placeholders are in related parts, and have a different representation (<dgm:prSet phldrT="[Text]" phldr="1"/> vs. the normal p:nvPr/p:ph)
The general approach seems to be a graphicFrame which contains a graphicData:
<a:graphic>
<a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/diagram">
<dgm:relIds xmlns:dgm="http://schemas.openxmlformats.org/drawingml/2006/diagram" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" r:dm="rId2" r:lo="rId3" r:qs="rId4" r:cs="rId5"/>
</a:graphicData>
</a:graphic>The relationships provide the layout of the shape, and the actual content:
<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramLayout" Target="../diagrams/layout1.xml"/>
<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramData" Target="../diagrams/data1.xml"/>
<Relationship Id="rId5" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramColors" Target="../diagrams/colors1.xml"/>
<Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/diagramQuickStyle" Target="../diagrams/quickStyle1.xml"/>The placeholders then look like this (from data1.xml):
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<dgm:dataModel xmlns:dgm="http://schemas.openxmlformats.org/drawingml/2006/diagram" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
<dgm:ptLst>
<dgm:pt modelId="{201DA834-84A2-4476-AFF7-041FCF65859D}" type="doc">
<dgm:prSet loTypeId="urn:microsoft.com/office/officeart/2011/layout/CircleProcess" loCatId="process" qsTypeId="urn:microsoft.com/office/officeart/2005/8/quickstyle/simple1" qsCatId="simple" csTypeId="urn:microsoft.com/office/officeart/2005/8/colors/accent1_2" csCatId="accent1" phldr="0"/>
<dgm:spPr/>
<dgm:t>
<a:bodyPr/>
<a:lstStyle/>
<a:p>
<a:endParaRPr lang="en-GB"/>
</a:p>
</dgm:t>
</dgm:pt>
<dgm:pt modelId="{16AB87A3-ECFD-4530-9FA8-036018B97AE3}">
<dgm:prSet phldrT="[Text]" phldr="1"/>
<dgm:spPr/>
<dgm:t>
<a:bodyPr/>
<a:lstStyle/>
<a:p>
<a:endParaRPr lang="en-GB"/>
</a:p>
</dgm:t>
</dgm:pt>
...I saw that I can find the related part's XML with shape.part.related_parts['rId2']. Possibly I can manipulate that directly.
This is the output of print prs.slides[0].shapes[0].part.blob:
<p:sld xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main"><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:graphicFrame><p:nvGraphicFramePr><p:cNvPr id="4" name="Diagram 3"/><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="533975228"/></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/diagram"><dgm:relIds xmlns:dgm="http://schemas.openxmlformats.org/drawingml/2006/diagram" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" r:dm="rId2" r:lo="rId3" r:qs="rId4" r:cs="rId5"/></a:graphicData></a:graphic></p:graphicFrame></p:spTree><p:extLst><p:ext uri="{BB962C8B-B14F-4D97-AF65-F5344CB8AC3E}"><p14:creationId xmlns:p14="http://schemas.microsoft.com/office/powerpoint/2010/main" val="646705655"/></p:ext></p:extLst></p:cSld><p:clrMapOvr><a:masterClrMapping/></p:clrMapOvr></p:sld>To have something which can generate SmartArt, I thought of putting the SmartArt items I'd like to use into the slide layouts - and then populating the placeholders. This would be a temporary measure until an add_smartart() is created.
Unfortunately for now, it looks like this will take longer than I have to implement, but I wanted to at least create an issue to track and say what I know so far.
Activity
scanny commentedon Feb 13, 2014
Thanks for this Nick. Definitely looks like a serious job to get right. This will be a handy start when the time comes. Let me know if you decide to dig into it later, happy to help you find internal bits that might be useful for injecting templated XML or what have you :)
pipern commentedon Feb 14, 2014
Is there a bit of sample code that would demonstrate changing the XML of
prs.slides[0].shapes[0].part.blobdirectly, and then writing it back out when I save the presentation?scanny commentedon Feb 17, 2014
Hi Piper, I don't have time to test something at the moment, but this should point you in the right direction. Essentially you can read part.blob and write part._element. The former is XML text (probably unicode), the latter is an lxml.objectify tree.
In general you don't have to trace back up to the part from a shape, the slide object itself is the part. So accessing the XML would be:
If you prefer to work directly with the objectify tree (like ElementTree, but can access children mostly with attribute access), you can use
element = slide._element.once you're done, you'll need to put it back in element form. If you've directly manipulated the element tree using the
slide._elementreference, there's nothing to do, everything has been updated in place. If you manipulated the XML text using.blobfor access, you'll need to re-parse it and put it back in._element. This should get that done:Never mind the
_byteson the end,parse_xml_byteslikes unicode just fine.From there you should be able to save normally. Theoretically you should be able to do additional operations on the slide, but I'll bet I'm cacheing some references somewhere, so accessing shapes after reparsing the XML might not work. That might be something worth looking into if the use case is compelling. That and providing built-in hooks for accessing the XML directly.
Let me know how you go :)
[-]SmartArt (http://schemas.openxmlformats.org/drawingml/2006/diagram) support[/-][+]feature set: SmartArt support[/+]hullyang commentedon Apr 26, 2025