2017-10-07 96 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();