2017-10-07 98 views
0

我有一个简单的场景,其中编程式地使用OpenXML SDK 2.5和c#创建幻灯片。幻灯片上有两个形状以及连接这两个形状的连接器。OpenXML自动刷新PowerPoint幻灯片上的连接器

当我在PowerPoint中打开演示文稿时,两种形状和连接器都显示出来,但连接器没有正确定位在形状之间。当我拖动幻灯片上的其中一个形状时,PowerPoint会立即刷新连接器并将其放入正确的位置。

我的问题:是否可以创建一个openxml PowerPoint幻灯片,当打开文件时自动刷新连接器的位置?

谢谢

回答

0

我想出了这个问题的解决方案似乎相当劈十岁上下,但据我所知还没有一个更好的办法。问题是PowerPoint在内部控制连接器布局,并且不公开任何刷新它们的方法。在测试中,我惊讶地发现如果有必要,PowerPoint将在刷新期间动态更改连接器类型。

为了让刷新发生,我必须在.pptm文件中编写VBA宏,并从我的C#代码中调用它。我添加了一个模块并将函数放在那里,所以它不会与特定幻灯片关联。

此代码移动幻灯片上的每个形状,以便刷新连接器刷新。它也在组内查找形状。它正在过滤三角形和菱形形状。

我避免在代码中使用ActivePresentation,因为我想在宏运行时隐藏PowerPoint。

Public Sub FixConnectors() 
    Dim mySlide As Slide 
    Dim shps As Shapes 
    Dim shp As Shape 
    Dim subshp As Shape 

    Set mySlide = Application.Presentations(1).Slides(1) 
    Set shps = mySlide.Shapes 

    For Each shp In shps 
     If shp.AutoShapeType = msoShapeIsoscelesTriangle Or shp.AutoshapeType = msoShapeDiamond Then 
      shp.Left = shp.Left + 0.01 - 0.01 
     End If 
     If shp.Type = mso.Group Then 
      For Each subshp In shp.GroupItems 
       If subshp.AutoShapeType = msoShapeIsoscelesTriangle Or subshp.AutoshapeType = msoShapeDiamond Then 
        subshp.Left = subshp.Left + 0.01 - 0.01 
       End If 
      Next subshp 
     End If 
    Next shp 

    Application.Presentations(1).Save 
End Sub 

接下来是使用PowerPoint Interop运行宏的C#代码。将该文件作为Windows进程关闭并重新打开后,垃圾收集器可以清理Interop拥有的任何句柄。在测试中,终结器可能需要几秒钟才能运行,因此在重新打开该文件后发生GC调用,以便应用程序不会挂起。

using System; 
using System.Diagnostics; 
using OC = Microsoft.Office.Core; 
using PP = Microsoft.Office.Interop.PowerPoint; 

string filePath = "C:/Temp/"; 
string fileName = "Template.pptm"; 

// Open PowerPoint in hidden mode, run the macro, and shut PowerPoint down 
var pptApp = new PP.Application(); 
PP.Presentation presentation = pptApp.Presentations.Open(filePath + fileName, OC.MsoTriState.msoFalse, OC.MsoTriState.msoFalse, OC.MsoTriState.msoFalse); 
pptApp.Run(filename + "!.FixConnectors"); 
presentation.Close(); 
presentation = null; 
pptApp.Quit(); 
pptApp = null; 

// Reopen the file through Windows 
Process.Start(filePath + fileName); 

// Clear all references to PowerPoint 
GC.Collect(); 
GC.WaitForPendingFinalizers(); 
GC.Collect(); 
GC.WaitForPendingFinalizers();