Closed maspireone closed 10 years ago
Hi maspireone, I would determine what XML is added to the PowerPoint file when you make that call with VBA and see if I could work out from there how to do the same. It might go something like this:
before.pptx
.before.pptx
. Save that file as after.pptx
.$ pip install opc-diag
$ opc diff before.pptx after.pptx
Once you get it narrowed down to a specific set of elements paste it back in here and I can help you further.
Hi Scanny,
Thanks. The following is the result. It's a closed curve shape. Please be noted. How can I create a function for this in python-pptx. Please help to let me know where to start.
<a:chExt cx="0" cy="0"/>
</a:xfrm>
</p:grpSpPr>
<p:sp>
<p:nvSpPr>
<p:cNvPr id="5" name="Freeform 4"/>
<p:cNvSpPr/>
<p:nvPr/>
</p:nvSpPr>
<p:spPr>
<a:xfrm>
<a:off x="2756647" y="1918179"/>
<a:ext cx="3993777" cy="1994915"/>
</a:xfrm>
<a:custGeom>
<a:avLst/>
<a:gdLst>
<a:gd name="connsiteX0" fmla="*/ 0 w 3993777"/>
<a:gd name="connsiteY0" fmla="*/ 1994915 h 1994915"/>
<a:gd name="connsiteX1" fmla="*/ 1707777 w 3993777"/>
<a:gd name="connsiteY1" fmla="*/ 152668 h 1994915"/>
<a:gd name="connsiteX2" fmla="*/ 3993777 w 3993777"/>
<a:gd name="connsiteY2" fmla="*/ 152668 h 1994915"/>
<a:gd name="connsiteX0" fmla="*/ 0 w 3993777"/>
<a:gd name="connsiteY0" fmla="*/ 1994915 h 1994915"/>
<a:gd name="connsiteX1" fmla="*/ 1707777 w 3993777"/>
<a:gd name="connsiteY1" fmla="*/ 152668 h 1994915"/>
<a:gd name="connsiteX2" fmla="*/ 3993777 w 3993777"/>
<a:gd name="connsiteY2" fmla="*/ 152668 h 1994915"/>
<a:gd name="connsiteX3" fmla="*/ 0 w 3993777"/>
<a:gd name="connsiteY3" fmla="*/ 1994915 h 1994915"/>
</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:cxn ang="0">
<a:pos x="connsiteX3" y="connsiteY3"/>
</a:cxn>
</a:cxnLst>
<a:rect l="l" t="t" r="r" b="b"/>
<a:pathLst>
<a:path w="3993777" h="1994915">
<a:moveTo>
<a:pt x="0" y="1994915"/>
</a:moveTo>
<a:cubicBezTo>
<a:pt x="521074" y="1227312"/>
<a:pt x="1042148" y="459709"/>
<a:pt x="1707777" y="152668"/>
</a:cubicBezTo>
<a:cubicBezTo>
<a:pt x="2373407" y="-154373"/>
<a:pt x="3565712" y="85433"/>
<a:pt x="3993777" y="152668"/>
</a:cubicBezTo>
<a:lnTo>
<a:pt x="0" y="1994915"/>
</a:lnTo>
<a:close/>
</a:path>
</a:pathLst>
</a:custGeom>
<a:noFill/>
</p:spPr>
<p:style>
<a:lnRef idx="2">
<a:schemeClr val="accent1">
<a:shade val="50000"/>
</a:schemeClr>
</a:lnRef>
<a:fillRef idx="1">
<a:schemeClr val="accent1"/>
</a:fillRef>
<a:effectRef idx="0">
<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:endParaRPr lang="en-US"/>
</a:p>
</p:txBody>
</p:sp>
</p:spTree>
<p:extLst>
<p:ext uri="{BB962C8B-B14F-4D97-AF65-F5344CB8AC3E}">
I'll need to see the specific VBA call you used to create this. Can you paste it in?
Please see below.
Sub Shape() Set myDocument = ActivePresentation.Slides(1)
With myDocument.Shapes.BuildFreeform(msoSegmentLine, 217.0588, 308) .AddNodes 1, 1, 258.0883, 248, 299.1177, 187, 351.5294, 163 .AddNodes 1, 1, 403.9413, 139, 497.8235, 158, 531.5294, 163 .AddNodes 0, 0, 217.0588, 308 .ConvertToShape End With End Sub
Interesting. I'm sure I never would have come across this one on my own, thanks for asking this one :)
Here are a few insights:
<p:sp>
element is the closed-curve shape as a whole. Swapping this
element in and out will independently make the object appear on the slide.
Your challenge is to generate it with Python rather than VBA.<a:custGeom>
element. All the rest of it is
boilerplate that is already produced in python-pptx for other shapes, and so
probably could be inherited. Let's leave that question aside for the moment.<a:gdLst>
and <a:cxnLst>
appears to be for the sake of
providing connection sites, spots on the shape to which a connector will snap
if dragged to it. If you don't care about those, that stuff can probably go.The main business is happening in <a:pathLst>
, and it looks to correspond
quite closely to the calls you sent. There is a units transformation
happening that somewhat obscures things. The units in VBA are points. The
units in the XML are English Metric Units (EMU), 914400 to the inch. So
you'll need a formula like this to translate between them:
>>> vba_x = 217.0588
>>> xml_x = vba_x / 72.0 * 914400
>>> int(round(xml_x))
2756647
Note that matches the value in <a:off x="2756647" ...>
in line 12 of your diff
above.
I believe the x and y values in the <a:pt x= .. y=>
elements are computed
relative to the bounding box of the shape, so I expect you'll need some additional
arithmetic there.
Unfortunately it looks like PowerPoint is calculating the smooth curve values to bezier curve values internally. So it looks like you'll be on your own for that. Your VBA call has a starting and ending point for each node whereas the XML has two additional points for each node, I expect these determine the shape of the curve.
Hope that helps, let us know how you go :)
Sure. Thanks for the information. I will keep you updated.
Hi there - any progress on this issue?
Hi Scanny,
Can you give me a hint that how can I add function like BuildFreeform Method in VBA to create curve through 4 points. If I would like to create a function like that on top of your code, where should I start. Please help to let me know. Thank you.
The detail of the function is list below. http://msdn.microsoft.com/en-us/library/office/aa212150(v=office.11).aspx