Java中如何使用实现PPT模板内容填充(依赖POI)
【摘要】 使用POI按照模板动态填充PPT
在最近的工作中,遇到动态填充PPT内容的需求,记录一下解决方案与实现代码。
需求
因为特殊的工作需要,用户需要生成指定格式的PPT,但是PPT的部分内容是动态生成的,因此,程序需要实现:给定PPT文件模板的情况下,动态地将相关内容填充到指定位置。
比如,模板如下:
期望执行效果如下图:
废话不多说,看代码:(完整代码请直接拉到文章最后,有现成方法)
POI引用包
添加依赖
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.2</version>
</dependency>
关键代码:
- 解构PPT,一个Slideshow就是一个PPT文件。通过传入模板的输入流,创建一个
XMLSlideShow
对象,代表要处理的 PPT 文件。
SlideShow slideShow = new XMLSlideShow(inputStream);
- 遍历每一页PPT:
每页幻灯片通常由各种形状(如文本框、图片、图表等)组成。通过Slide
对象,可以访问和操作幻灯片中的这些元素。
for (Object slideObj : slideShow.getSlides()) {
// 每个slide都是一页元素
Slide slide = (Slide) slideObj;
}
- 遍历每个幻灯片中的各个元素:
// 遍历幻灯片中的所有形状
List<Shape> shapes = slide.getShapes();
// 循环时可能删除,修改循环方式
Iterator<Shape> iterator = shapes.iterator();
while (iterator.hasNext()) {
// Shape是一个抽象类,表示幻灯片中的一个形状对象。
Shape shape = iterator.next();
}
- 获取每个
Shape
中的文字,依次进行替换:
if (shape instanceof TextShape) {
// 文本输入框、形状中的文字内容也会进入这个领域
TextShape textShape = (TextShape) shape;
String text = textShape.getText();
for (Map.Entry<String, Object> entry : replacementMap.entrySet()) {
// 这里是因为replaceAll会按照正则表达式进行匹配,将大括号{进行一下转义
String key = entry.getKey().replace("{{", "\\{\\{");
text = text.replaceAll(key, entry.getValue() != null ? entry.getValue().toString() : "");
}
textShape.setText(text);
} else if (shape instanceof XSLFTable) {
// 表格
XSLFTable table = (XSLFTable)shape;
for (int row = 0; row < table.getNumberOfRows(); row++) {
for (int col = 0; col < table.getNumberOfColumns(); col++) {
XSLFTableCell cell = table.getCell(row, col);
String cellText = cell.getText();
for (Map.Entry<String, Object> entry : replacementMap.entrySet()) {
String key = entry.getKey().replace("{{", "\\{\\{");
cellText = cellText.replaceAll(key, entry.getValue() != null ? entry.getValue().toString() : "");
}
cell.setText(cellText);
}
}
} else {
// 可以依次补充其他元素文字进行补充
}
其中文字替换部分代码为:
// entry.getKey() 形如"{{标题}}", entry.getValue()形式如"真正的标题"
// key 形如"\\{\\{标题}}",这是基于正则表达式转义的需要
// 原text 可能是形式如: "这里的标题是{{标题}}"
// 替换后,text = "这里的标题是真正的标题"
String key = entry.getKey().replace("{{", "\\{\\{");
text = text.replaceAll(key, entry.getValue() != null ? entry.getValue().toString() : "");
- 替换后输出流:
// 保存修改到输出流
slideShow.write(outputStream);
return new ByteArrayInputStream(outputStream.toByteArray());
完整代码:
/**
* @param inputStream 模版ppt的输入流
* @param replacementMap 需要替换的文字,格式为{ "{{标题}}": "真正的标题" }
* @return 替换后的ppt流
*/
public static InputStream replaceTextInPPT(InputStream inputStream, Map<String, Object> replacementMap) {
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
// 创建 SlideShow 对象
SlideShow slideShow = new XMLSlideShow(inputStream);
// 遍历所有幻灯片
for (Object slideObj : slideShow.getSlides()) {
Slide slide = (Slide) slideObj;
// 遍历幻灯片中的所有形状
List<Shape> shapes = slide.getShapes();
// 循环时可能删除,修改循环方式
Iterator<Shape> iterator = shapes.iterator();
while (iterator.hasNext()) {
Shape shape = iterator.next();
if (shape instanceof TextShape) {
// 文本输入框、形状中的文字内容也会进入这个领域
TextShape textShape = (TextShape) shape;
String text = textShape.getText();
for (Map.Entry<String, Object> entry : replacementMap.entrySet()) {
// 这里是因为replaceAll会按照正则表达式进行匹配,将大括号{进行一下转义
String key = entry.getKey().replace("{{", "\\{\\{");
text = text.replaceAll(key, entry.getValue() != null ? entry.getValue().toString() : "");
}
textShape.setText(text);
} else if (shape instanceof XSLFTable) {
XSLFTable table = (XSLFTable)shape;
// 表格
for (int row = 0; row < table.getNumberOfRows(); row++) {
for (int col = 0; col < table.getNumberOfColumns(); col++) {
XSLFTableCell cell = table.getCell(row, col);
String cellText = cell.getText();
for (Map.Entry<String, Object> entry : replacementMap.entrySet()) {
String key = entry.getKey().replace("{{", "\\{\\{");
cellText = cellText.replaceAll(key, entry.getValue() != null ? entry.getValue().toString() : "");
}
cell.setText(cellText);
}
}
} else if (shape instanceof XSLFAutoShape) {
}
}
}
// 保存修改到输出流
slideShow.write(outputStream);
return new ByteArrayInputStream(outputStream.toByteArray());
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)