⽤poi操作docx⽂档将⽂档内容保留样式、去掉修订同时复制到另⼀个docx模板
⽂章⽬录
需求
做项⽬的时候有这样⼀个需求,我们现在有两个word(docx)⽂档,⼀个⽂档⾥⾯放着正⽂内容,另⼀个⽂档是模板,需求是需要将正⽂内容同时包含样式复制到另⼀个模板⾥,因为正⽂⽂档⾥还开启了修订,要求复制过去以后不带着修订,直接显⽰修订后的内容,完成需求的第⼀个⼯作就是做技术选型,选来选去还是选择poi,因为poi的资料相对来说多⼀些,虽然代码⽐较复杂⼀些,但是类名什么的还是有⼀定规律的容易熟悉。
代码
⾸先我们需要了解⼀些关于docx的知识,才能更好的了解下⾯的代码,根据我对poi的简单的了解,poi操作word应该主要是基于xml的,所以我们需要先了解⼀下docx⽂档的xml结构才能更好的去⽤poi完成需求,我们先打开⼀个docx⽂档然后选择另存为xml如下图:
这是⼀个测试⽂档,带着样式和修订内容
这是模板⽂档,带着"正⽂"两个字作为标记,我们要在模板⾥到正⽂两个字,然后把正⽂两个字删除以后再正⽂这个段落上开始填充内容
⽂件格式选择为word xml⽂档保存以后打开保存的xml⽂档,打开以后百度⼀个xml在线格式化⼯具格式化⼀下以后变成这样,我们搜索⼀下我们标记的内容然后就能看到标签了
其实还有⼀个ins标签。。代表着修订线。。了解了标签下⾯可以直接上代码了。。。代码没有多难。。还是很简单的。。只不过我在做的时候发现这⽅⾯的资料很少,所以就把我的第⼀次博客交给它了。
⾸先我们还需要引三个jar包
<!-- poi jar包 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.13</version>
</dependency>
<!-- mvnrepository/artifact/org.apache.poi/poi-ooxml-schemas -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.13</version>
</dependency>
<!-- mvnrepository/artifact/org.apache.poi/ooxml-schemas -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>1.1</version>
</dependency>
这⾥的三个jar包最主要的应该是ooxml-schemas这个jar包,因为poi-ooxml-schemas这个jar包是精简版的jar,⾥⾯有很多的类都没有,所以我们需要引⼊完全版的ooxml-schemas jar包,这个jar包是需要对应poi版本的,3.13版本的poi对应的是1.1版本的ooxml-schemas
v.sach.cascontent.poi;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import lbeans.XmlCursor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.List;
public class PoiConvertWord {
private byte[] TemplateByte;
public PoiConvertWord() {
try {
FileInputStream redTemplateInputStream = new FileInputStream(new File("/Users/gao/Desktop/测试套红/套红模板.docx"));
this.TemplateByte = new byte[redTemplateInputStream.available()];
} catch (Exception e) {
e.printStackTrace();
}
}
public void extractText() {
try {
FileInputStream fileInputStream = new FileInputStream(new File("/Users/gao/Desktop/测试套红/正⽂.docx"));
XWPFDocument mainDocument = new XWPFDocument(fileInputStream);
List<XWPFParagraph> paragraphs = Paragraphs();//获取读取模板⾥的所有段落对象
this.setRed(paragraphs);
repository文件夹可以删除吗} catch (Exception e) {
e.printStackTrace();
}
}
}
public void setRed(List<XWPFParagraph> paraList) throws Exception {
XWPFDocument xwpfDocument;
int startPoint = 0;
//读取模板
if (TemplateByte.length == 0) {
return;
}
xwpfDocument = new XWPFDocument(new ByteArrayInputStream(TemplateByte));//构建模板⽂档对象
List<XWPFParagraph> paragraphs = Paragraphs();//获取模板⾥的段落对象
for (int i=0;i<paragraphs.size();i++) {//遍历模板中的段落对象到标记位置
XWPFParagraph xwpfParagraph = (i);
List<XWPFRun> runs = Runs();
for (int l=0;l<runs.size();l++) {
XWPFRun run = (l);
if (().equals("正⽂")) {//如果遍历到标记位置退出循环,并记录⼀下标记位置所在段落对象的下标
startPoint = i;
break;//退出遍历run的循环
}
}
if (startPoint!=0) {
break;//退出遍历paragraph的循环
}
}
if (startPoint!=0) {
XWPFParagraph insertNewParagraph = (startPoint);//获取到标记位置的段落对象
XmlCursor xmlCursor = CTP().newCursor();//获取到段落的光标
for (int j=0;j<paraList.size();j++) {
XWPFParagraph oldParagraph = (j);//获得传过来的段落对象
CTPPr oldPPr = CTP().getPPr();//获取段落对象的样式的ppr标签
if (oldPPr!=null) {
CTParaRPr oldPPrRpr = RPr();//获取ppr标签⾥的rpr标签
CTPPrChange oldPPrChange = PPrChange();//获取pprchange标签
CTTrackChange rprIns = null;
CTParaRPrChange oldPraRprChange = null;
if (oldPPrRpr!=null) {
rprIns = Ins();//获取ins标签
oldPraRprChange = RPrChange();//获取ppr标签中的rpr标签⾥的rprchange标签
}
if (oldPPrChange!=null) {//如果有change标签证明是修订内容,设置为取消修订
oldPPr.unsetPPrChange();
}
if (oldPraRprChange!=null) {
oldPPrRpr.unsetRPrChange();
}
if (rprIns!=null) {//ins标签代表着修订线,如果有修订线则取消修订线
oldPPrRpr.unsetIns();
}
}
List<XWPFRun> runs = Runs();//获取run对象
for (int k=0;k<runs.size();k++) {
XWPFRun oldRun = (k);
CTRPr oldRPr = CTR().getRPr();
CTRPrChange oldRPrChange = RPrChange();//run标签⾥也有rprchange标签也需要像上⾯⼀样设置
CTRPrChange oldRPrChange = RPrChange();//run标签⾥也有rprchange标签也需要像上⾯⼀样设置
if (oldRPrChange!=null) {
oldRPr.unsetRPrChange();
}
XWPFRun newRun = ateRun();
newRun.());
insertNewParagraph.addRun(newRun);
}
insertNewParagraph = xwpfDocument.insertNewParagraph(xmlCursor);//在当前光标处插⼊新的段落
xmlCursor = CTP().newCursor();
}
}
FileOutputStream fileOutputStream = new FileOutputStream("/Users/gao/Desktop/测试.docx");
xwpfDocument.write(fileOutputStream);
}
public static void main(String[] args) {
PoiConvertWord poiConvertWord = new PoiConvertWord();
}
}
代码复制过去稍微改⼀改路径就可以⽤了,代码⼤部分样式都能够保留,不保证能完美的保留所有的样式。。。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。