说明
在做项目时,遇到了一种情况,需要将一个word文档正文的内容插入到一个word模板的指定位置中。
一、 引入依赖
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>org.apache.poi.xwpf.converter.pdf</artifactId>
<version>1.0.4</version>
</dependency>
<!-- poi jar包 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.14</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.14</version>
</dependency>
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>org.apache.poi.xwpf.converter.pdf</artifactId>
<version>1.0.4</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.14</version>
</dependency>
二、 转换的工具类
package org.camunda.bpm.getstarted.loanapproval.util;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.xmlbeans.XmlCursor;
import org.camunda.bpm.getstarted.loanapproval.controller.TestCamundaController;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import java.io.*;
import java.net.URL;
import java.util.List;
import java.util.UUID;
public class PoiConvertWord {
private byte[] TemplateByte;
public String fileUrl;
public String pdfUrl;
public PoiConvertWord(String templatePath,String textPath) throws IOException {
InputStream inputStream=null;//模板流
InputStream textInputStream=null;//正文文件流
try {
//读取模板word
inputStream=new FileInputStream(new File(templatePath));
this.TemplateByte = new byte[inputStream.available()];
inputStream.read(TemplateByte);
//读取正文word
URL textUrl = new URL(textPath);
textInputStream=textUrl.openStream();
XWPFDocument mainDocument = new XWPFDocument(textInputStream);
List<XWPFParagraph> paragraphs = mainDocument.getParagraphs();//获取读取模板里的所有段落对象
this.setRed(paragraphs);
} catch (Exception e) {
e.printStackTrace();
} finally {
if(textInputStream!=null){
textInputStream.close();
}
if(inputStream!=null){
inputStream.close();
}
}
}
public void setRed(List<XWPFParagraph> paraList){
XWPFDocument xwpfDocument;
int startPoint = 0;
//读取模板
if (TemplateByte.length == 0) {
return;
}
try{
xwpfDocument = new XWPFDocument(new ByteArrayInputStream(TemplateByte));//构建模板文档对象
List<XWPFParagraph> paragraphs = xwpfDocument.getParagraphs();//获取模板里的段落对象
for (int i=0;i<paragraphs.size();i++) {//遍历模板中的段落对象找到标记位置
XWPFParagraph xwpfParagraph = paragraphs.get(i);
List<XWPFRun> runs = xwpfParagraph.getRuns();
for (int l=0;l<runs.size();l++) {
XWPFRun run = runs.get(l);
if (run.text().equals("正文")) {//如果遍历到标记位置退出循环,并记录一下标记位置所在段落对象的下标
xwpfParagraph.removeRun(l);//同时把正文两字移除
startPoint = i;
break;//退出遍历run的循环
}else if(run.text().equals("Evaluation Warning: The document was created with Spire.Doc for JAVA.")){
xwpfParagraph.removeRun(l);
}
}
if (startPoint!=0) {
break;//退出遍历paragraph的循环
}
}
if (startPoint!=0) {
XWPFParagraph insertNewParagraph = paragraphs.get(startPoint);//获取到标记位置的段落对象
XmlCursor xmlCursor = insertNewParagraph.getCTP().newCursor();//获取到段落的光标
for (int j=0;j<paraList.size();j++) {
XWPFParagraph oldParagraph = paraList.get(j);//获得传过来的段落对象
CTPPr oldPPr = oldParagraph.getCTP().getPPr();//获取段落对象的样式的ppr标签
if (oldPPr!=null) {
CTParaRPr oldPPrRpr = oldPPr.getRPr();//获取ppr标签里的rpr标签
CTPPrChange oldPPrChange = oldPPr.getPPrChange();//获取pprchange标签
CTTrackChange rprIns = null;
CTParaRPrChange oldPraRprChange = null;
if (oldPPrRpr!=null) {
rprIns = oldPPrRpr.getIns();//获取ins标签
oldPraRprChange = oldPPrRpr.getRPrChange();//获取ppr标签中的rpr标签里的rprchange标签
}
if (oldPPrChange!=null) {//如果有change标签证明是修订内容,设置为取消修订
oldPPr.unsetPPrChange();
}
if (oldPraRprChange!=null) {
oldPPrRpr.unsetRPrChange();
}
if (rprIns!=null) {//ins标签代表着修订线,如果有修订线则取消修订线
oldPPrRpr.unsetIns();
}
}
insertNewParagraph.getCTP().setPPr(oldPPr);//把传过来的段落中的ppr标签设置到新的段落里
List<XWPFRun> runs = oldParagraph.getRuns();//获取run对象
for (int k=0;k<runs.size();k++) {
XWPFRun oldRun = runs.get(k);
CTRPr oldRPr = oldRun.getCTR().getRPr();
if(oldRPr!=null){
CTRPrChange oldRPrChange = oldRPr.getRPrChange();//run标签里也有rprchange标签也需要像上面一样设置
if (oldRPrChange!=null) {
oldRPr.unsetRPrChange();
}
}
XWPFRun newRun = insertNewParagraph.createRun();
newRun.getCTR().setRPr(oldRPr);
newRun.setText(oldRun.text());
insertNewParagraph.addRun(newRun);
}
xmlCursor.toNextSibling();//下移光标
insertNewParagraph = xwpfDocument.insertNewParagraph(xmlCursor);//在当前光标处插入新的段落
xmlCursor = insertNewParagraph.getCTP().newCursor();
}
}
String docName= UUID.randomUUID().toString().replace("-","");
FileOutputStream fileOutputStream = new FileOutputStream(TestCamundaController.temporary+docName+".docx");
xwpfDocument.write(fileOutputStream);
this.pdfUrl=TestCamundaController.temporary+docName+".pdf";
//转化为pdf
//WordPdfUtil.doc2pdf(TestCamundaController.temporary+docName+".docx",this.pdfUrl);
if(fileOutputStream!=null){
fileOutputStream.close();
}
if(xwpfDocument!=null){
xwpfDocument.close();
}
}catch (Exception ex){
ex.printStackTrace();
}
//上传到服务器
}
public static void main(String[] args) throws Exception {
String templatePath="模板.docx";
String textPath="正文内容.docx";
PoiConvertWord poiConvertWord = new PoiConvertWord(templatePath,textPath);
}
}
注意:只适用于右键docx能解压的文件