我有一个简单的场景,我使用OpenXML SDK2.5和c#以编程方式创建了一个带有幻灯片的演示文稿。幻灯片上有两个形状,以及连接这两个形状的连接器。
当我在PowerPoint中打开演示文稿时,显示了形状和连接符,但连接符在形状之间的位置不正确。当我拖动幻灯片上的一个形状时,PowerPoint会立即刷新连接器并将其放到正确的位置。
我的问题是:有没有可能创建一个openxml PowerPoint幻灯片,在打开文件时自动刷新连接器位置?
谢谢
发布于 2018-02-15 22:17:28
我为这个问题想出的解决方案可能看起来有点像黑客,但据我所知,没有更好的方法。问题是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互操作运行宏的C#代码。关闭并重新打开作为Windows进程的文件允许垃圾回收器清理Interop拥有的任何句柄。在测试中,finalizer可能需要几秒钟的时间才能运行,因此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();https://stackoverflow.com/questions/46624441
复制相似问题