How to duplicate a slide containing a chart using apache POI?

2.8k Views Asked by At

Dear all,

I'm working with Apache POI and I would like to duplicate a slide containing several charts from code.

The code below (inspired by https://poi.apache.org/slideshow/xslf-cookbook.html#Merge) works fine when there is no chart on the slide.

Unfortunately, it seems that the charts are not duplicated with this method: when I try to open the resulting file, Powerpoint detects a problem, tries to repair it, but fails, and I get empty slides.

I've checked the underlying XML files (using Open XML SDK), and it seems that the chart themselves (in the folder /ppt/charts) are not duplicated, and the relationship files (in the folder /ppt/slides/_rels) are not completely updated.

Here is my current code:

// Open slideshow
FileInputStream fileInputStream = new FileInputStream(sourceFilePath);
XMLSlideShow slideShow = new XMLSlideShow(fileInputStream);
fileInputStream.close();

// Duplicate slide
XSLFSlideLayout layout = slide.getSlideLayout();
XSLFSlide newSlide = slideshow.createSlide(layout);
newSlide.importContent(slide);

// Save updated slideshow
FileOutputStream fileOutputStream = new FileOutputStream(outputFilePath);
slideShow.write(fileOutputStream);
fileOutputStream.close();

Do you know how I could clone a slide and its charts ?

Thanks a lot, and best regards!

3

There are 3 best solutions below

0
On

Since Apache POI 4.0.0, the original code from the question will work to duplicate a slide.

0
On

You can't. I tried and tried, the problem is that the duplication does not handle images or charts.

I had to copy files by hand through a script. Here are the steps:

  • Locate the slide file
  • Duplicate it
  • Find the chart object in the XML file, and note the relation Id
  • In the relations file, check which file is designated by the relation Id
  • Duplicate this file
  • You also have to duplicate the relation file for the new slide, and update the name
  • The new slide is not visible, you have to update presentaion.xml
  • Please note: if you want your PPTX to work with Microsoft Powerpoint, you'll also have to duplicate associated Excel workbook (see in the relation file of the chart)
0
On

My problem was really close to yours with version 5.2.2, the chart was indeed correctly duplicated but the reference to the internal workbook of the sheet was copied too, by reference ! (It's actually done here : https://apache.googlesource.com/poi/+/refs/tags/REL_5_2_2/poi-ooxml/src/main/java/org/apache/poi/xslf/usermodel/XSLFGraphicFrame.java#241 )

It means that when I edited the chart values in the duplicated slide I edited both chart values. It makes visually no difference in powerpoint at first but when you right-click>edit data on the chart, it re-renders and the data changes visually.

To avoid that, just re-set the workbook of the chart to null so that it creates (or really load from the relation part) a new one for the duplicated chart

The code to duplicate a slide with a chart should look like this :

        XSLFSlide oldSlide = ppt.getSlides().get(number);
        XSLFSlideLayout layout = oldSlide.getSlideLayout();
        XSLFSlide newSlide = ppt.createSlide(layout);
        newSlide.importContent(oldSlide);
        newSlide.getRelations().stream()
                .filter(r -> r instanceof XSLFChart)
                .forEach(chart->((XSLFChart)chart).setWorkbook(null));
        //to force loading the correct worksheet

I hope it help some people stumbling upon this :)