我想出了这个问题的解决方案似乎相当劈十岁上下,但据我所知还没有一个更好的办法。问题是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();