有时需要把 PowerPoint 中的文字单独提取出来,例如整理培训课件、汇总会议材料,或者将 PPT 内容保存为文本文件,方便后续搜索和处理。
如果只是几页幻灯片,直接复制文字即可。但当 PPT 页数较多,或者只需要提取特定页面和表格中的内容时,通过 Java 处理会更方便。
本文介绍三种操作:提取整个 PPT 的普通文本、提取指定幻灯片中的文字,以及读取 PPT 表格中的文本。
一、添加 Maven 依赖
首先,在 Java 项目的 pom.xml 中添加以下 Maven 仓库和依赖:
xml
<repositories>
<repository>
<id>com.e-iceblue</id>
<name>e-iceblue</name>
<url>https://repo.e-iceblue.cn/repository/maven-public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.presentation</artifactId>
<version>11.9.10</version>
</dependency>
</dependencies>
下面使用一个名为 report.pptx 的 PowerPoint 文件作为示例,假设其中包含标题、正文、项目进度说明和数据表格等内容。
所有示例都使用这个文件作为输入,并将提取的文字保存为 UTF-8 编码的 TXT 文件。
二、提取整个 PowerPoint 中的普通文本
如果需要读取所有幻灯片中的标题和正文,可以遍历幻灯片上的形状对象,找到包含文字的自动形状,然后逐段提取内容。
在 PowerPoint 中,文本框、标题占位符以及部分带文字的图形通常都可以通过 IAutoShape 访问。
ParagraphEx.getText() 方法则用于读取其中某个段落的文本。
完整代码如下:
java
import com.spire.presentation.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
public class ExtractAllPPTText {
public static void main(String[] args) throws Exception {
// 创建 Presentation 对象
Presentation presentation = new Presentation();
try {
// 加载 PPT 文件
presentation.loadFromFile("report.pptx");
// 保存提取结果
StringBuilder result = new StringBuilder();
// 遍历所有幻灯片
for (int i = 0;
i < presentation.getSlides().getCount();
i++) {
ISlide slide = presentation.getSlides().get(i);
// 标记幻灯片编号
result.append("第 ")
.append(i + 1)
.append(" 页")
.append(System.lineSeparator());
// 遍历当前幻灯片中的所有形状
for (Object shape : slide.getShapes()) {
if (shape instanceof IAutoShape) {
IAutoShape autoShape = (IAutoShape) shape;
// 遍历形状中的段落
for (Object item :
autoShape.getTextFrame()
.getParagraphs()) {
ParagraphEx paragraph =
(ParagraphEx) item;
String text = paragraph.getText();
if (text != null &&
!text.trim().isEmpty()) {
result.append(text)
.append(System.lineSeparator());
}
}
}
}
result.append(System.lineSeparator());
}
// 保存为 UTF-8 文本文件
Files.write(
Paths.get("ppt-all-text.txt"),
result.toString()
.getBytes(StandardCharsets.UTF_8));
System.out.println("文本提取完成");
} finally {
// 释放资源
presentation.dispose();
}
}
}
运行后,程序会生成 ppt-all-text.txt。提取结果按照幻灯片顺序排列,并在每页内容前添加页码,方便区分文字来自哪一页。
代码中的主要操作包括:
getSlides():获取演示文稿的幻灯片集合。getShapes():获取幻灯片上的形状对象。getTextFrame().getParagraphs():获取形状中的文本段落。ParagraphEx.getText():读取段落的文字内容。
这里需要注意,提取所有幻灯片的普通文本,并不等于提取 PPT 中所有类型的文字。
上述代码只处理 IAutoShape 中的文本。对于表格单元格、备注、图表标签或图片里的文字,需要根据具体对象类型采用其他处理方式。
另外,文字的提取顺序取决于幻灯片中的形状排列顺序,不一定与人眼看到的阅读顺序完全一致。
三、提取指定幻灯片中的文字
有时只需要提取某一页的内容,例如获取第 3 页的项目进度说明,没有必要遍历整份 PPT。
可以通过 presentation.getSlides().get(index) 获取指定幻灯片,再提取其中的文本。
下面的代码以第 3 页为例:
java
import com.spire.presentation.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
public class ExtractSingleSlideText {
public static void main(String[] args) throws Exception {
Presentation presentation = new Presentation();
try {
// 加载 PPT 文件
presentation.loadFromFile("report.pptx");
// 指定需要提取的页码
int slideNumber = 3;
// 检查页码是否有效
if (slideNumber < 1 ||
slideNumber > presentation.getSlides().getCount()) {
throw new IllegalArgumentException(
"指定的幻灯片不存在");
}
// 获取指定幻灯片
ISlide slide = presentation.getSlides()
.get(slideNumber - 1);
StringBuilder result = new StringBuilder();
// 遍历当前幻灯片中的形状
for (Object shape : slide.getShapes()) {
if (shape instanceof IAutoShape) {
IAutoShape autoShape = (IAutoShape) shape;
// 提取形状中的各个段落
for (Object item :
autoShape.getTextFrame()
.getParagraphs()) {
ParagraphEx paragraph =
(ParagraphEx) item;
String text = paragraph.getText();
if (text != null &&
!text.trim().isEmpty()) {
result.append(text)
.append(System.lineSeparator());
}
}
}
}
// 保存提取结果
Files.write(
Paths.get("slide-3-text.txt"),
result.toString()
.getBytes(StandardCharsets.UTF_8));
System.out.println("第 3 页文本提取完成");
} finally {
presentation.dispose();
}
}
}
这段代码与前面的整体提取方式类似,区别在于只处理一张幻灯片。
需要注意的是,PowerPoint 幻灯片的集合索引从 0 开始。
也就是说:
get(0)对应第 1 页。get(1)对应第 2 页。get(2)对应第 3 页。
因此,代码通过 slideNumber - 1 将实际页码转换为集合索引。
示例还检查了指定页码是否有效,避免在 PPT 页数不足时访问不存在的幻灯片。
如果需要提取多个指定页面,可以准备一个页码数组,逐个获取对应的幻灯片,而不必处理其他页面。
四、提取 PPT 表格中的文字
PowerPoint 幻灯片除了标题和正文,还可能包含表格。例如项目进度表、费用清单或数据对比表。
表格中的文字存储在单元格中,因此不能只依靠前面针对 IAutoShape 的遍历方式获取。
可以先判断形状是否为 ITable,然后遍历表格中的行和列,通过单元格的 getTextFrame().getText() 方法读取文字。
下面的示例会遍历 PPT 中的所有幻灯片,查找其中的表格,并将表格内容保存为制表符分隔的文本文件。
java
import com.spire.presentation.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
public class ExtractPPTTableText {
public static void main(String[] args) throws Exception {
Presentation presentation = new Presentation();
try {
// 加载 PPT 文件
presentation.loadFromFile("report.pptx");
StringBuilder result = new StringBuilder();
// 遍历所有幻灯片
for (int i = 0;
i < presentation.getSlides().getCount();
i++) {
ISlide slide = presentation.getSlides().get(i);
// 遍历幻灯片中的形状
for (Object shape : slide.getShapes()) {
if (shape instanceof ITable) {
ITable table = (ITable) shape;
result.append("第 ")
.append(i + 1)
.append(" 页中的表格")
.append(System.lineSeparator());
// 获取表格行数和列数
int rowCount =
table.getTableRows().getCount();
int columnCount =
table.getColumnsList().getCount();
// 遍历表格中的每个单元格
for (int row = 0; row < rowCount; row++) {
for (int col = 0;
col < columnCount;
col++) {
// 读取单元格文字
String text = table.get(col, row)
.getTextFrame()
.getText();
if (text != null) {
// 避免单元格中的换行破坏文本结构
text = text.replace("\r", " ")
.replace("\n", " ")
.replace("\t", " ");
result.append(text);
}
// 使用制表符分隔不同列
if (col < columnCount - 1) {
result.append("\t");
}
}
result.append(System.lineSeparator());
}
result.append(System.lineSeparator());
}
}
}
// 保存文本文件
Files.write(
Paths.get("ppt-table-text.txt"),
result.toString()
.getBytes(StandardCharsets.UTF_8));
System.out.println("PPT 表格文字提取完成");
} finally {
presentation.dispose();
}
}
}
这里有三个关键方法:
getTableRows().getCount() 用于获取表格的行数。
getColumnsList().getCount() 用于获取表格的列数。
table.get(col, row) 用于获取指定单元格。注意这个方法接收的参数顺序是列索引在前、行索引在后,两个索引都从 0 开始。
获取单元格后,使用 getTextFrame().getText() 读取其中的文字。
假设 PPT 中有这样一张表格:
| 项目 | 负责人 | 进度 |
|---|---|---|
| 模块 A | 张三 | 已完成 |
| 模块 B | 李四 | 进行中 |
提取后的文本大致如下:
css
第 2 页中的表格
项目 负责人 进度
模块 A 张三 已完成
模块 B 李四 进行中
不同列之间使用制表符分隔,因此将结果导入其他表格处理程序时,也比较容易区分各列。
需要注意,如果原表格包含合并单元格,直接按行列遍历可能产生空白或重复位置。这个示例适合普通规则表格,对于包含大量合并单元格的情况,需要根据实际结构进一步处理。
五、提取 PPT 文字时需要注意的问题
1. 图片中的文字不能直接提取
如果 PPT 中的文字实际上是一张图片,例如截图、扫描件或嵌入的流程图图片,那么 getText() 无法直接识别其中的文字。
这类内容需要通过 OCR 技术识别,不能和普通文本提取混为一谈。
2. 普通形状、表格和备注属于不同对象
本文前两个示例处理的是文本框等自动形状中的文字,第三个示例则专门读取表格单元格。
演讲者备注、图表中的数据标签、组合形状内部的文字等可能需要额外处理。因此,如果需要提取 PPT 的全部可见文字,应根据实际文件结构检查是否存在遗漏。
3. 提取结果不会保留原始排版
TXT 文件主要保存文字内容,不包含 PowerPoint 原有的字体、字号、颜色或页面布局。
如果需要保留标题层级、表格结构等信息,可以在提取时增加相应的标记,或者改用更适合保存结构化内容的输出格式。
4. 中文文本建议使用 UTF-8 编码
本文使用 StandardCharsets.UTF_8 保存文本文件,主要是为了避免中文内容在不同操作系统之间传递时出现编码问题。
如果使用 Java 的 FileWriter,也需要留意运行环境的默认字符编码,尤其是在不同版本的 JDK 和操作系统上运行时。
六、总结
使用 Java 提取 PowerPoint 中的文字,关键在于根据文本所在的对象选择处理方式。
实际处理时,建议先确认 PPT 中的文字属于普通文本、表格还是图片,再选择相应的提取方式,避免遗漏内容。