Bug 66284 - Apache POI - Merge deck with different slide layouts
Summary: Apache POI - Merge deck with different slide layouts
Status: NEW
Alias: None
Product: POI
Classification: Unclassified
Component: XSLF (show other bugs)
Version: 5.2.2-FINAL
Hardware: PC All
: P2 critical (vote)
Target Milestone: ---
Assignee: POI Developers List
URL: https://stackoverflow.com/questions/7...
Keywords: APIBug
Depends on:
Reported: 2022-09-29 06:46 UTC by J Khanna
Modified: 2022-10-12 05:49 UTC (History)
1 user (show)


Note You need to log in before you can comment on or make changes to this bug.
Description J Khanna 2022-09-29 06:46:17 UTC
On Using option targetDeck.createSlide(srcSlide.getSlideLayout), the apache POI throws error while writing (mergedDeck.write(outStream)) to a deck -

Rule M2.4 exception : Part '/_rels/.rels' not found - this error should NEVER happen!\nCheck that your code is closing the open resources in the correct order prior to filing a bug report.\nIf you can provide the triggering file, then please raise a bug at https://bz.apache.org/bugzilla/enter_bug.cgi?product=POI and attach the file that triggers it, thanks!

The probable reason for the above -

When slides are created using PackagePart with the same name in this case (SlideLayout from different decks having different), on cleanup it will throw an exception. Find below the trace-
org.apache.poi.openxml4j.opc.internal.ContentTypeManager.getContentType(ContentTypeManager.java:353) at org.apache.poi.openxml4j.opc.internal.ContentTypeManager.removeContentType(ContentTypeManager.java:262) at org.apache.poi.openxml4j.opc.OPCPackage.removePart(OPCPackage.java:998) at org.apache.poi.openxml4j.opc.PackagePart.getOutputStream(PackagePart.java:526) at org.apache.poi.xslf.usermodel.XSLFSheet.commit(XSLFSheet.java:412) at org.apache.poi.ooxml.POIXMLDocumentPart.onSave(POIXMLDocumentPart.java:467) at org.apache.poi.ooxml.POIXMLDocumentPart.onSave(POIXMLDocumentPart.java:472) at org.apache.poi.ooxml.POIXMLDocumentPart.onSave(POIXMLDocumentPart.java:472) at org.apache.poi.ooxml.POIXMLDocument.write(POIXMLDocument.java:221)

More details: https://stackoverflow.com/questions/73727277/apache-poi-merge-multiple-decks-to-single-deck
Comment 1 PJ Fanning 2022-09-29 10:57:10 UTC
Can you provide a full test case? Including a couple of random lines of the code is not enough. This issue and the stackoverflow question are far from clear.
Comment 2 J Khanna 2022-09-29 16:05:20 UTC
Use case: create a single deck by merging all the slides from different decks

Source decks has different slide layouts, sizes.
To load decks source decks, and merge them I'm using Apache POI 5.2.3. 

0) create an empty target deck
1) load decks from input stream
2) iterate over slides on the deck
4) create new slide in the target deck using the layout (each slide can have different layout), contents of the source deck
5) repeat step#1 until all the source decks have been imported to target deck as new slides
6) export the merged deck to file

Each step has inbuilt functions provided by Apache POI which have been mentioned in stackoverflow as well.

Finally, while exporting the target deck using write operation of class:
XMLSlideShow, it throws mentioned exception.

  Note: this exception is only logged if we use slide layouts of the source slides to create target.

  Code for each step has been mentioned in stackoverflow otherwise I can post it here
Comment 3 PJ Fanning 2022-09-29 16:14:00 UTC
That is not what I asked for. I asked for all the code in a runnable form. There is a likely reason that noone has commented or answered on your stackoverflow question: you have not provided a reproducible example.
Comment 4 J Khanna 2022-09-29 16:21:47 UTC

The code is similar to the mentioned reference.

for(XSLFSlide srcSlide : src.getSlides()) {
            //merging the contents

This requires improvement. If you would see the bottom of the reference, would only find content but source layouts
Comment 5 PJ Fanning 2022-09-29 16:28:00 UTC
Fair enough if you don't want to right a test. I don't want to write one for you. Maybe someone else will.
Comment 6 J Khanna 2022-09-29 16:33:08 UTC
I've already shared most of things, I'm not sure what else you are looking for?

Only change in my codebase is source of input stream. Otherwise the simplest possible Java code is available on the reference URL. We can do a google meet if required
Comment 7 J Khanna 2022-10-04 04:54:15 UTC
Please use the reference project - https://github.com/Jatish-Khanna/apache-poi-example.git
Comment 8 PJ Fanning 2022-10-04 22:40:43 UTC
I don't have much time to spend on POI right now. One thing to try yourself is to try out the `importContent` methods on XSLFSlide, XSLFSlideLayout and XSLFSlideMaster. These are the methods used in our tests when copying slides and/or their layouts to other slideshows.

One of the POI unit tests does this.

            XSLFSlide srcSlide = srcPptx.getSlides().get(0);
            XSLFSlide newSlide = newPptx.createSlide();

            XSLFSlideLayout srcSlideLayout = srcSlide.getSlideLayout();
            XSLFSlideLayout newSlideLayout = newSlide.getSlideLayout();

            XSLFSlideMaster srcSlideMaster = srcSlide.getSlideMaster();
            XSLFSlideMaster newSlideMaster = newSlide.getSlideMaster();

Comment 9 J Khanna 2022-10-05 02:43:59 UTC
I've already reverse engineered and tried multiple approaches including the suggested one. Please check the stackoverflow post for additional details.

 - POI doesn't offer extension
 - when trying to create a slide from layout, it overrides instead of adding a new layout
Comment 10 J Khanna 2022-10-12 05:49:59 UTC
Do you need any other information to solve the bug?