【发布时间】:2023-03-18 07:30:01
【问题描述】:
我有一个最初包含零张幻灯片的 .pptx 文件。其中一种布局被命名为“一个内容”。现在,我只想基于此布局生成一个带有单张幻灯片的新 PPTX 文件。应该是微不足道的,不是吗?不,显然不是。
在 OpenXmlUtils.cs 文件中,我使用以下方法从“模板”文件创建新的 PPTX:
public static void CopyTemplate(string template, string target)
{
string targetPath = Path.GetFullPath(target);
string targetFolder = Path.GetDirectoryName(targetPath);
if (!System.IO.Directory.Exists(targetFolder))
{
System.IO.Directory.CreateDirectory(targetFolder);
}
System.IO.File.Copy(template, targetPath, true);
}
我的 PPTWriter.cs 分解为 MCVE:
public PPTOpenXMLWriter(string templatePath, string presSaveAsPath)
{
if (File.Exists(presSaveAsPath)) { File.Delete(presSaveAsPath); }
OpenXmlUtils.CopyTemplate(templatePath, presSaveAsPath);
_createPresentation(presSaveAsPath);
}
private void _createPresentation(string presSaveAsPath)
{
using (PresentationDocument presentationDocument = PresentationDocument.Open(presSaveAsPath, true))
{
string layoutName = "One content";
_insertNewSlide(presentationDocument.PresentationPart, layoutName);
presentationDocument.Save();
}
}
private void _insertNewSlide(PresentationPart presentationPart, string layoutName)
{
Slide slide = new Slide(new CommonSlideData(new ShapeTree()));
SlidePart slidePart = presentationPart.AddNewPart<SlidePart>();
slide.Save(slidePart);
SlideMasterPart slideMasterPart = presentationPart.SlideMasterParts.FirstOrDefault();
SlideLayoutPart slideLayoutPart = slideMasterPart.SlideLayoutParts.SingleOrDefault
(sl => sl.SlideLayout.CommonSlideData.Name.Value.Equals(layoutName, StringComparison.OrdinalIgnoreCase));
slidePart.AddPart<SlideLayoutPart>(slideLayoutPart);
slidePart.Slide.CommonSlideData = (CommonSlideData)slideLayoutPart.SlideLayout.CommonSlideData.Clone();
SlideIdList slideIdList = null;
if ( presentationPart.Presentation.SlideIdList is null)
{
presentationPart.Presentation.SlideIdList = new SlideIdList();
}
slideIdList = presentationPart.Presentation.SlideIdList;
// find the highest id
uint maxSlideId = 0;
if (slideIdList.ChildElements.Count() > 0)
maxSlideId = slideIdList.ChildElements
.Cast<SlideId>()
.Max(x => x.Id.Value);
// Insert the new slide into the slide list after the previous slide.
SlideId newSlideId = new SlideId();
slideIdList.Append(newSlideId);
newSlideId.Id = maxSlideId;
newSlideId.RelationshipId = presentationPart.GetIdOfPart(slidePart);
// Save the modified presentation.
presentationPart.Presentation.Save();
}
生成的文件已损坏,需要由 PowerPoint“修复”,修复后幻灯片版式不是指定的版式。事实上,这是一个完全不同的布局,具有完全不同的 XML 结构,我所能收集到的只是它以某种方式默认回到主布局(“标题”)中通常的 first 布局,因为它没有知道如何处理通过 OpenXML 实际提供的任何内容。
这似乎应该是一个相当常见的用例,也许我的期望是错误的,但似乎给定一个 已经存在的幻灯片布局,你应该能够(相对轻松)创建一个新的幻灯片基于该布局,它将包含所有相同的占位符形状等。
【问题讨论】:
标签: c# powerpoint openxml openxml-sdk