I have the code below where I try copying the slides from one ppt to another. I do this because the second ppt already has the logic implemented in another area of the application and now I want to join the slides to the current one to have all the information available if desired.
The real problem that I have is when the second ppt contains more than one slide I will get the error that appeared in the picture when opening the final report.
It is important to mention that for a single slide everything works correctly, the slides having basically the same content, so I don’t think it has to do with lack of information.
public ReportResult ExportEVReportToPowerPointFile(EVReport evReportData, string exportLanguage, string currentRequestUrl, MemoryStream topIssueStream)
{
var folderPath = _folderPathRepository.GetByCode($"EV-Report-{exportLanguage.ToUpperInvariant()}");
var reportTemplatePath = folderPath?.Path;
if (string.IsNullOrEmpty(reportTemplatePath))
{
return null;
}
var reportMS = _generateEVStatusReportService.ExportEVReportToPowerPointFile(evReportData, reportTemplatePath, exportLanguage, currentRequestUrl);
using (var reportPresentation = PresentationDocument.Open(reportMS, true))
using (var topIssuePresentation = PresentationDocument.Open(topIssueStream, true))
{
var reportPresentationPart = reportPresentation.PresentationPart;
var slideIdList = reportPresentationPart.Presentation.SlideIdList;
uint maxSlideId = slideIdList.ChildElements.Cast<SlideId>().Max(s => s.Id.Value);
foreach (var topIssueSlidePart in topIssuePresentation.PresentationPart.SlideParts)
{
// Clone the entire slide
CloneSlide(topIssueSlidePart, reportPresentationPart);
// Add the slide to the SlideIdList
var slideId = slideIdList.AppendChild(new SlideId());
slideId.Id = ++maxSlideId;
slideId.RelationshipId = reportPresentationPart.GetIdOfPart(reportPresentationPart.SlideParts.Last());
}
reportPresentation.Save();
}
var result = new ReportResult
{
RootPath = reportTemplatePath,
FilePath = reportTemplatePath,
Filename = evReportData.IsSnapshot ? $"EV_Snapshot_{DateTime.Now:dd_MM_yyyy}" : $"EV_Status_{DateTime.Now:dd_MM_yyyy}",
Base64EncodedFile = Convert.ToBase64String(reportMS.ToArray(), Base64FormattingOptions.None)
};
return result;
}
private void CloneSlide(SlidePart sourceSlidePart, PresentationPart destinationPresentationPart)
{
// Create a new slide part in the destination presentation
var newSlidePart = destinationPresentationPart.AddNewPart<SlidePart>();
// Copy the slide content
newSlidePart.FeedData(sourceSlidePart.GetStream());
// Copy the slide layout and its dependencies
if (sourceSlidePart.SlideLayoutPart != null)
{
SlideLayoutPart newSlideLayoutPart = GetOrCreateSlideLayoutPart(sourceSlidePart.SlideLayoutPart, destinationPresentationPart);
// Add the slide layout part to the new slide part
newSlidePart.AddPart(newSlideLayoutPart);
}
// Clone other related parts and their relationships
foreach (var part in sourceSlidePart.Parts)
{
if (!(part.OpenXmlPart is SlideLayoutPart))
{
var clonedPart = newSlidePart.AddPart(part.OpenXmlPart, part.RelationshipId);
clonedPart.FeedData(part.OpenXmlPart.GetStream());
}
}
}
private SlideLayoutPart GetOrCreateSlideLayoutPart(SlideLayoutPart sourceSlideLayoutPart, PresentationPart destinationPresentationPart)
{
SlideMasterPart sourceSlideMasterPart = sourceSlideLayoutPart.SlideMasterPart;
SlideMasterPart destinationSlideMasterPart = GetOrCreateSlideMasterPart(sourceSlideMasterPart, destinationPresentationPart);
// Find or create the slide layout part
SlideLayoutPart newSlideLayoutPart = destinationSlideMasterPart.SlideLayoutParts
.FirstOrDefault(slp => slp.Uri == sourceSlideLayoutPart.Uri);
if (newSlideLayoutPart == null)
{
newSlideLayoutPart = destinationSlideMasterPart.AddNewPart<SlideLayoutPart>();
newSlideLayoutPart.FeedData(sourceSlideLayoutPart.GetStream());
// Clone related parts like images, charts, etc.
foreach (var part in sourceSlideLayoutPart.Parts)
{
var clonedPart = newSlideLayoutPart.AddPart(part.OpenXmlPart, part.RelationshipId);
clonedPart.FeedData(part.OpenXmlPart.GetStream());
}
}
return newSlideLayoutPart;
}
private SlideMasterPart GetOrCreateSlideMasterPart(SlideMasterPart sourceSlideMasterPart, PresentationPart destinationPresentationPart)
{
// Find or create the slide master part
SlideMasterPart newSlideMasterPart = destinationPresentationPart.SlideMasterParts
.FirstOrDefault(smp => smp.Uri == sourceSlideMasterPart.Uri);
if (newSlideMasterPart == null)
{
newSlideMasterPart = destinationPresentationPart.AddNewPart<SlideMasterPart>();
newSlideMasterPart.FeedData(sourceSlideMasterPart.GetStream());
// Clone related parts like themes, fonts, etc.
foreach (var part in sourceSlideMasterPart.Parts)
{
var clonedPart = newSlideMasterPart.AddPart(part.OpenXmlPart, part.RelationshipId);
clonedPart.FeedData(part.OpenXmlPart.GetStream());
}
}
return newSlideMasterPart;
}
You can copy slide using ShapeCrawler library:
var sourcePres = new Presentation("source.pptx");
var targetPres = new Presentation("target.pptx");
var copyingSlide = sourcePres.Slide(1);
targetPres.Slides.Add(copyingSlide);
targetPres.SaveAs("result.pptx");
2