Apache POI PPT(Java) - 更新TextShape,保持文本格式/形状格式

时间:2017-10-03 10:25:44

标签: java apache-poi powerpoint

我正在尝试根据不同的输入/为我创建的同一个PPTX模板上的不同用户生成多个报告(即N PPTX文件)。

我在PPTX模板上有几个预先格式化的XSLFTextShape,它包含已经格式化的单个XSLFTextParagraph(即形状和文本)。每个形状都包含一个特定的占位符,我需要用dynimic值替换它。我在Map(占位符,newValue)中有这个值。我使用以下方法成功使用新值更新占位符:

textShape.clearText();
XSLFTextRun run = paragraph.addNewTextRun();
run.setText(newText);

因此,当我在输出中生成PPTX时,文本会更新,但字体颜色,字体格式,字体大小与我在模板中定义的相比会发生变化。如何保持相同的格式?

任何解决方案只需在保留原始格式的同时更改文字?

提前致谢!

2 个答案:

答案 0 :(得分:1)

对于将来可能对此主题感兴趣的每个人 - 我发布解决方案(如果一个TextBox有一个段落,则工作)。此解决方案在所有文本框上循环,如果其中一个包含Placeholder-> newValue映射中指定的其中一个值,则会更新它以保持格式。

    public static void updateTextBoxesWithDesiredValues(XMLSlideShow ppt, Map<String, String> placeHolderDefinedValue) {
    logger.info("ElapsedTime: " + tM.getTimeElapsedReadableFormat() + " ########## Updating single text box content...");
    List<XSLFSlide> allSlides = ppt.getSlides();
    int updatedElements = 0;
    for (XSLFSlide currentSlide : allSlides) {
        for (XSLFShape shape : currentSlide.getShapes()) {
            if (shape instanceof XSLFTextShape) {
                XSLFTextShape textBox = (XSLFTextShape) shape;
                String elementTextContent = textBox.getText();
                for (Object key : placeHolderDefinedValue.keySet()) {
                    if (elementTextContent.equals(key)) {
                        List<XSLFTextParagraph> textBoxParagraphs = textBox.getTextParagraphs();
                        List<XSLFTextRun> textBoxParagraphTextRuns = textBoxParagraphs.get(0).getTextRuns();
                        //System.out.println("########################## check paragraph number in textbox: " + textBoxParagraphs.size() + " - TextRuns: " + textBoxParagraphs.get(0).getTextRuns().size());
                        logger.info("ElapsedTime: " + tM.getTimeElapsedReadableFormat() + updatedElements + ") Updating: " + textBox.getText() + " --> " + placeHolderDefinedValue.get(key));
                        for (XSLFTextRun r : textBoxParagraphTextRuns) {
                            r.setText(placeHolderDefinedValue.get(key));
                        }
                        updatedElements++;
                        //break;
                    }
                }
            }

        }
    }
    logger.info("ElapsedTime: " + tM.getTimeElapsedReadableFormat() + " Total Text Element Content Updated: " + updatedElements + " #########################");
}

答案 1 :(得分:0)

这太可怕了-但是,是有原因的,他们称其为“ POI”。

这是我现有的XSLFTextShape(必须至少预先设置一些文本!)的“仅重置文本”方法:

    textShape.getTextParagraphs().get(0).getTextRuns().get(0).setText(text);

    for (int i = 1; i < textShape.getTextParagraphs().get(0).getTextRuns().size(); i++) {
        textShape.getTextParagraphs().get(0).getTextRuns().get(i).setText("");
    }
    for (int i = 1; i < textShape.getTextParagraphs().size(); i++) {
        textShape.getTextParagraphs().get(i).getTextRuns().stream().filter(tr -> !tr.getRawText().equals("\n")).forEach(tr -> tr.setText(""));
    }

它将用“空”文本替换所有现有文本(段落/行),但是由于某些原因无法替换换行符。因此,这可能会让您留下一些尾随线-因为它们通常(!)是透明的,所以并不会造成太大伤害。

.clearText /删除段落对我来说是不完整的格式,或者不起作用。尝试重置样式(fontColor,fontFamily,fontSize,isBold,isItalit等)并没有得到令人满意的结果:(