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 answers

0
Alain FAGOT BÉAREZ On

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

0
Nicolas Cailloux 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
NeeL 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 :)