Bug 65473 - when do copy slide operation, text shape's copy is not working, new slide use the old text shape object's reference
Summary: when do copy slide operation, text shape's copy is not working, new slide use...
Status: RESOLVED FIXED
Alias: None
Product: POI
Classification: Unclassified
Component: XSLF (show other bugs)
Version: 5.0.0-FINAL
Hardware: PC All
: P1 major (vote)
Target Milestone: ---
Assignee: POI Developers List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-07-29 08:37 UTC by xdrodger
Modified: 2022-08-19 13:14 UTC (History)
0 users



Attachments
input pptx file (30.57 KB, application/vnd.openxmlformats-officedocument.presentationml.presentation)
2021-07-29 08:37 UTC, xdrodger
Details
output pptx file (29.89 KB, application/vnd.openxmlformats-officedocument.presentationml.presentation)
2021-07-29 08:37 UTC, xdrodger
Details
source code (3.97 KB, text/plain)
2021-07-29 08:38 UTC, xdrodger
Details

Note You need to log in before you can comment on or make changes to this bug.
Description xdrodger 2021-07-29 08:37:05 UTC
Created attachment 37971 [details]
input pptx file

When do copy slide operation, text shape's copy is not working, new slide use the old text shape object's reference. Below is the source code, attachment is input file. Only one attachment is allowed, so no result file is uploaded.


import org.apache.poi.xslf.usermodel.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class CopySlideTest {

    private XMLSlideShow ppt;
    private String dirPath = "D:\\workspace\\practice-demo\\file\\input\\";
    private String fileName = "copy-slide-demo.pptx";
    private String outFileName = "copy-slide-demo-out.pptx";

    @Before
    public void setUp() throws Exception {
        String filePath = dirPath + fileName;
        ppt = new XMLSlideShow(new FileInputStream(filePath));
    }

    @Test
    public void testCopySlide() {
        String shapeName = "title";
        XSLFSlide defaultSlide = getSlideByShapeName(shapeName);
        int slideIndex = defaultSlide.getSlideNumber() - 1;
        List<Integer> slideIndexList = new ArrayList<>();
        for (int i =0; i < 3; i ++) {
            if (i == 0) {
                // pass
            } else {
                XSLFSlide newSlide = copySlide(slideIndex);
                slideIndex = newSlide.getSlideNumber() - 1;
            }
            slideIndexList.add(slideIndex);
        }
        for (Integer index : slideIndexList) {
            XSLFSlide slide = ppt.getSlides().get(index);
            replaceText(slide, shapeName, "this is " + slide.getSlideNumber() + " slide.");
        }
    }

    @After
    public void savePpt() throws Exception {
        String filePath = dirPath + outFileName;
        FileOutputStream out = new FileOutputStream(filePath);
        ppt.write(out);
        out.close();
        ppt.close();
    }

    private void replaceText(XSLFSlide slide, String shapeName, String value) {
        XSLFShape shape = getShape(slide, shapeName);
        if (shape == null) {
            return;
        }
        XSLFTextShape textShape = (XSLFTextShape) shape;
        List<XSLFTextParagraph> textParagraphs = textShape.getTextParagraphs();
        for (XSLFTextParagraph textParagraph : textParagraphs) {
            List<XSLFTextRun> textRuns = textParagraph.getTextRuns();
            for (XSLFTextRun textRun : textRuns) {
                textRun.setText(value);
            }
        }
    }

    private XSLFSlide copySlide(int index) {
        XSLFSlideLayout defaultSlideLayout = null;
        List<XSLFSlideMaster> slideMasters = ppt.getSlideMasters();
        for (XSLFSlideMaster slideMaster : slideMasters) {
            for (XSLFSlideLayout slideLayout : slideMaster.getSlideLayouts()) {
                if (Objects.equals(SlideLayout.TITLE_AND_CONTENT, slideLayout.getType())) {
                    defaultSlideLayout = slideLayout;
                    break;
                }
            }
        }
        XSLFSlide slide = ppt.getSlides().get(index);
        XSLFSlide newSlide = ppt.createSlide(defaultSlideLayout).importContent(slide);
        ppt.setSlideOrder(newSlide, slide.getSlideNumber());
        return newSlide;
    }

    private XSLFSlide getSlideByShapeName(String shapeName) {
        List<XSLFSlide> slides = ppt.getSlides();
        for (XSLFSlide slide : slides) {
            List<XSLFShape> shapes = slide.getShapes();
            for (XSLFShape shape : shapes) {
                if (shape.getShapeName().equals(shapeName)) {
                    return slide;
                }
            }
        }
        throw new InvalidParameterException("shape not exist");
    }

    public XSLFShape getShape(XSLFSlide slide, String shapeName) {
        List<XSLFShape> shapes = slide.getShapes();
        for (XSLFShape shape : shapes) {
            if (shape.getShapeName().equals(shapeName)) {
                return shape;
            }
        }
        throw new InvalidParameterException("shape not exist in slide");
    }
}
Comment 1 xdrodger 2021-07-29 08:37:58 UTC
Created attachment 37972 [details]
output pptx file

output pptx file
Comment 2 xdrodger 2021-07-29 08:38:40 UTC
Created attachment 37973 [details]
source code

source code
Comment 3 PJ Fanning 2022-08-19 00:59:15 UTC
See https://github.com/apache/poi/pull/371
Comment 4 PJ Fanning 2022-08-19 09:24:25 UTC
Github PR 371 is merged if anyone wants to build POI for themselves to try it out.
Comment 5 PJ Fanning 2022-08-19 13:14:23 UTC
added r1903574