一、前言
由于POI组件,在doc格式文档和docx格式文档读写处理上,API设计差异较大。目前,关于Apache POI组件在Office Word文档的读、写操作上,只有纯文本提取可以使用同一套程序来处理的。
也就是说,如果要对文档进行更加细致的解析和操作,需要分开2套程序代码来完成。
本章节,我们讲下关于doc格式文档的文本替换处理。
二、关于文本替换符
一般来说,如果要对文档中的部分内容进行替换,那么我们需要知道它的具体位置。所以,我们一般会用到一些特殊的符号来标记。如下图所示:

图中,“{{teacherName}}”是一个替换符。它由开始符号“{{”,替换变量名“teacherName”,以及结束符号“}}” 3部分组成。当文档中这些替换符满足变量替换规则,则会被替换为需要展示的内容。
注意:
1、替换符并非固定格式,可以自己设计,越独特越好。因为很多时候,常见的符号容易与正文内容冲突,造成替换错误。
2、生成结果样例展示如下:

三、doc格式文档的结构
其实,相比于docx格式的文档,doc文档的结构相对来说较为简单。在网络上找到一段关于文档的描述,大家可以参考看看:
Apache POI的HWPF模块是专门用来对Word doc文件进行读写操作的。在HWPF里面我们使用HWPFDocument来表示一个word doc文档。在HWPFDocument里面有这么几个概念:
l Range:它表示一个范围,这个范围可以是整个文档,也可以是里面的某一小节(Section),也可以是某一个段落(Paragraph),还可以是拥有共同属性的一段文本(CharacterRun)。
l Section:word文档的一个小节,一个word文档可以由多个小节构成。
l Paragraph:word文档的一个段落,一个小节可以由多个段落构成。
l CharacterRun:具有相同属性的一段文本,一个段落可以由多个CharacterRun组成。
l Table:一个表格。
n TableRow:表格对应的行。
n TableCell:表格对应的单元格。
Section、Paragraph、CharacterRun和Table都继承自Range。
四、替换处理
对于doc格式的文档,我们的解析是相对简单的。根据上面第三节的内容,我们可以把doc文档看作一个Range对象。并且,Range对象自带了替换字符串的方法(replaceText)。如下图:

这里,我们需要用到的方法如下:

替换方法包含2个参数,第一个是pPlaceHolder,要替换的字符串占位符;第二个是pValue,将要填充的内容。程序中,我们处理的代码如下:

到这里,我们就把模板文件的文本替换处理介绍完毕了。接下来,我们讲下,关于HWPFDocument文档对象的其它处理方法。
五、其它对象的操作解析操作样例
前面第三节中,我们介绍了几个对象。现在,我们就把文档按照段落(Paragraph)解析,并分段输出看看:
public static void main(String[] args) throws Exception {
//操作系统用户主目录
String userDir = System.getProperties().getProperty("user.home");
//文件所在文件夹
String fileDir = userDir+File.separator+"examproj";
//word文档路径1
String templateFilePath1 = fileDir+File.separator+"请假单模板(旧).doc";
//创建 doc 文档对象
HWPFDocument doc = new HWPFDocument(new FileInputStream(templateFilePath1));
//获取范围对象
Range range = doc.getRange();
//获取段落数量
int numPr = range.numParagraphs();
//分段输出内容信息
if(numPr>0) {
for(int i=0;i<numPr;i++) {
Paragraph p = range.getParagraph(i);
String content = p.text();
if(content!=null) {
System.out.println("段落"+(i+1)+":"+content.replaceAll("\\s+", " "));
}else {
System.out.println("段落"+(i+1)+":无内容");
}
}
}else {
System.out.println("文档获取不到段落信息。");
}
//资源回收,这里是测试程序,随便吧
doc.close();
}执行结果如下:

本章完结