我正在从事 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));
}
});
});
}
}
}
}
创建演示文稿后,在删除第一张幻灯片(原始幻灯片)之前,我可以看到已对其进行了有关文本替换的更改。然而,对克隆的幻灯片进行了适当的其他更改。
关于为什么会发生这种情况或如何解决它有什么见解或建议吗?
好的,我解决了我的问题! 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 中处理文本的较新类。