Mendix 中的 Apache POI 问题:对克隆幻灯片的更改反映在原始幻灯片上

问题描述 投票:0回答:1

我正在从事 Mendix 项目,并面临 Apache POI 的特殊问题。我有一个旨在修改克隆的 PowerPoint 幻灯片的函数,但它似乎修改了原始幻灯片。我很惊讶,因为添加表格和更改图像的其他功能运行良好,反映了预期位置的变化。就好像 Apache POI 忽略了我传递的幻灯片并在原始幻灯片上进行操作。

这是代码:

public IMendixObject executeAction() throws Exception {
    // Fetching presentation Slides from the Slides_ConfigurationBios relationship
    IMendixObject slidesObj = Core.retrieveByPath(getContext(), this.ConfigurationBios.getMendixObject(), "Exporter.Slides_ConfigurationBios").get(0);
    InputStream originalContentStream = Core.getFileDocumentContent(getContext(), slidesObj);
    XMLSlideShow mainPpt = new XMLSlideShow(originalContentStream);
    XSLFSlide templateSlide = mainPpt.getSlides().get(0);

    // Retrieving list of PersonsToExport associated with ConfigurationBios
    List<IMendixObject> personsToExportList = Core.retrieveByPath(getContext(), this.ConfigurationBios.getMendixObject(), "Exporter.PersonsToExport_ConfigurationBios");

    // Iterating through the list of PersonsToExport
    for (IMendixObject personToExport : personsToExportList) {
        // Retrieving list of Person associated with PersonsToExport
        List<IMendixObject> personList = Core.retrieveByPath(getContext(), personToExport, "Exporter.PersonsToExport_Person");
        for (IMendixObject person : personList) {
            // Fetching the PersonImage object associated with the Person object
            IMendixObject personImageObj = Core.retrieveByPath(getContext(), person, "Persons.PersonImage_Person").get(0);
            persons.proxies.PersonImage PersonImage = personImageObj == null ? null : persons.proxies.PersonImage.initialize(getContext(), personImageObj);

            // Cloning the template slide
            XSLFSlide clonedSlide = mainPpt.createSlide().importContent(templateSlide);

            // Calling functions to modify the cloned slide
            Map<String, String> replacements = generateReplacementsMap(clonedSlide, person);
            replaceTextInSlide(clonedSlide, replacements);

            if (PersonImage != null && PersonImage.getMendixObject() != null) {
                replaceImageInSlide(clonedSlide, PersonImage);
            }

            // [Other functions which seem to work fine]
        }
    }

    // Removing the original template slide
    mainPpt.removeSlide(0);

    // Saving the modified presentation to the Slides object
    ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
    mainPpt.write(byteOutput);
    Core.storeFileDocumentContent(getContext(), slidesObj, new ByteArrayInputStream(byteOutput.toByteArray()));

    return slidesObj;
}

private Map<String, String> generateReplacementsMap(XSLFSlide slide, IMendixObject person) {
    Map<String, String> replacements = new HashMap<>();
    // Search for text on the slide contained between "[#" and "#]"
    for (XSLFShape shape : slide.getShapes()) {
        if (shape instanceof XSLFTextShape) {
            XSLFTextShape textShape = (XSLFTextShape) shape;
            for (XSLFTextParagraph paragraph : textShape.getTextParagraphs()) {
                for (XSLFTextRun run : paragraph.getTextRuns()) {
                    String text = run.getRawText();
                    if (text.contains("[#") && text.contains("#]")) {
                        String attributeName = text.substring(text.indexOf("[#") + 2, text.indexOf("#]"));
                        IMendixObjectMember<?> member = person.getMember(getContext(), attributeName);
                        if (member != null) {
                            String replacementValue = member.getValue(getContext()) != null ? member.getValue(getContext()).toString() : "[!FIELD MISSING!]";
                            replacements.put("[#" + attributeName + "#]", replacementValue);
                        } else {
                            replacements.put("[#" + attributeName + "#]", "[!FIELD MISSING!]");
                        }
                    }
                }
            }
        }
    }
    return replacements;
}

private void replaceTextInSlide(XSLFSlide slide, Map<String, String> replacements) {
    for (XSLFShape shape : slide.getShapes()) {
        if (shape instanceof XSLFTextShape) {
            XSLFTextShape textShape = (XSLFTextShape) shape;
            for (Map.Entry<String, String> entry : replacements.entrySet()) {
                String find = entry.getKey();
                String replace = entry.getValue();
                textShape.getTextParagraphs().forEach(paragraph -> {
                    paragraph.getTextRuns().forEach(run -> {
                        String text = run.getRawText();
                        if (text.contains(find)) {
                            run.setText(text.replace(find, replace));
                        }
                    });
                });
            }
        }
    }
}

创建演示文稿后,在删除第一张幻灯片(原始幻灯片)之前,我可以看到已对其进行了有关文本替换的更改。然而,对克隆的幻灯片进行了适当的其他更改。

关于为什么会发生这种情况或如何解决它有什么见解或建议吗?

java apache-poi powerpoint clone
1个回答
0
投票

好的,我解决了我的问题! Apache POI 似乎在版本 4 中进行了一些更改,这些更改影响了您在 PPTX 幻灯片中处理文本的方式。我面临的问题是由于这些变化。具体来说,它与 XSLFTextParagraph 和 XSLFTextRun 的使用有关,在较新版本的 POI 中,从其他幻灯片复制形状后,它们使用了不正确的文本正文 (CTTextBody)。

我这样调整了我的代码: 我没有使用 XSLFTextParagraph 和 XSLFTextRun,而是使用了 org.apache.poi.xddf.usermodel.text.XDDFTextParagraph 和 org.apache.poi.xddf.usermodel.text.XDDFTextRun,它们是用于在 Apache POI 中处理文本的较新类。

© www.soinside.com 2019 - 2024. All rights reserved.