When opening a pptx file, it prompts that there is a problem with the content and needs to be repaired.
HanJason opened this issue · comments
Describe the bug
When opening a pptx file, it prompts that there is a problem with the content and needs to be repaired.
To Reproduce
Only insert a slide into the target file.
Steps to reproduce the behavior:
Run the program and open the output file
Observed behavior
PowerPoint found a problem with content in c:..\bin\Debug\net6.0\abc_copy.pptx.
PowerPoint can attempt to repair the presentation.
Expected behavior
A clear and concise description of what you expected to happen.
Desktop (please complete the following information):
- OS: [Windows]
- .NET Target: ( .NET Core NET6.0)
- DocumentFormat.OpenXml Version: (3.0.0)
Additional context
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Presentation;
var pathfile = AppDomain.CurrentDomain.BaseDirectory + "abc.pptx";
var destinationFilePath = AppDomain.CurrentDomain.BaseDirectory + "abc_copy.pptx";
using (PresentationDocument sourcePresentation = PresentationDocument.Open(pathfile, false))
{
using var mStream = new MemoryStream();
PresentationDocument destinationPresentation = PresentationDocument.Create(mStream, PresentationDocumentType.Presentation);
foreach (var part in sourcePresentation.Parts)
{
destinationPresentation.AddPart(part.OpenXmlPart, part.RelationshipId);
}
PresentationPart? presentationPart = destinationPresentation.PresentationPart;
if (presentationPart is not null && presentationPart.Presentation is not null)
{
Presentation presentation = presentationPart.Presentation;
if (presentation.SlideIdList is not null)
{
//presentation.SlideIdList.AppendChild(new SlideId() { Id = (uint)234533, RelationshipId = "r_rid1" });
List<string> titlesList = new List<string>();
var len = presentation.SlideIdList.Elements<SlideId>().Count();
var slideIdList = presentation.SlideIdList.Elements<SlideId>()?.ToList() ?? new List<SlideId>();
for (int i = 0; i < len; i++)
{
var slideId = slideIdList[i];
if (slideId.RelationshipId is null)
{
continue;
}
SlidePart slidePart = (SlidePart)presentationPart.GetPartById(slideId.RelationshipId!);
if (slidePart is null)
{
throw new ArgumentNullException("presentationDocument");
}
//copy slide part
SlidePart newSlidePart = presentationPart.AddNewPart<SlidePart>();
newSlidePart.FeedData(slidePart.GetStream());
newSlidePart.AddPart(slidePart.SlideLayoutPart);
slideId.InsertAfterSelf<SlideId>(new SlideId() { RelationshipId = presentationPart.GetIdOfPart(newSlidePart) });
}
}
}
destinationPresentation.Save();
File.WriteAllBytes(destinationFilePath, mStream.ToArray());
}
@HanJason If your goal is to insert a new slide or even to copy the existing slide, the presentation.xml
part will have to have a unique slide id and relationship id in each of sldIdLst's
children sldId
elements. The diff between your original and the new presentation show:
Original
<p:sldIdLst>
<p:sldId id="260" r:id="rId2"/>
<p:sldId r:id="R4ce3bde4cfff4c72"/>
</p:sldIdLst>
New
<p:sldIdLst>
<p:sldId id="260" r:id="rId2"/>
<p:sldId id="256" r:id="rId3"/>
</p:sldIdLst>
That would be a starting point. Note, the id you use has to be greater than or equal to 256 per ISO 29500-1 19.7.13 ST_SlideId (Slide Identifier).
When I test this by adding the new id (using 256
) PowerPoint is happy.