最近多了一个需求,需要对word模板内容进行替换,一开始用的是word03版的,替换起来比较简单,主要是range对像替换非常方便,而且可以保留替换前的字体样式。

  InputStream is = new FileInputStream(srcFath);
OutputStream os = new FileOutputStream(tempFile);
XWPFDocument doc = new XWPFDocument(is);
Range range = doc.getRange();
range.replaceText("${name}","aaa");
doc.write(os);
is.close();
os.flush();
os.close();

最后看到word里包含了图片,需要同时保存一张png图片,对于jpg的图片是可以的,但是png的显示不出来,改为操作2007的文档,07版的没有了Range,使用XWPFParagraph和XWPFRun来操作。XWPFParagraph表示段落,有的word里有表格内容,需要使用XWPFTable来处理,与段落区分开来处理。

 private  void replaceText(XWPFDocument doc, Map<String, Object> params) {
Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator();
XWPFParagraph para;
while (iterator.hasNext()) {
para = iterator.next();
this.replaceInPara(para, params);
}
}
private void replaceText(XWPFParagraph para, Map<String, Object> params) {
List<XWPFRun> runs;
Matcher matcher;
if (matcher(para.getParagraphText()).find()) {
runs = para.getRuns();
for (int i=0; i<runs.size(); i++) {
XWPFRun run = runs.get(i);
String runText = run.toString();
matcher = matcher(runText);
if (matcher.find()) {
while ((matcher = matcher(runText)).find()) {
runText = matcher.replaceFirst(String.valueOf(params.get(matcher.group(1))));
}
para.removeRun(i);
//重新插入run里内容格式可能与原来模板的格式不一致
para.insertNewRun(i).setText(runText);
}
}
}
}
    

  private Matcher matcher(String str) {
    Pattern pattern = Pattern.compile("\\$\\{(.+?)\\}", Pattern.CASE_INSENSITIVE);
    Matcher matcher = pattern.matcher(str);
    return matcher;
  }

 

再次处理替换内容的格式问题,通过一个临时文件先保存替换模板变量后的文件,在与之前模板文档一起通过正则匹配出变量位置,由于替换变量时先删除再插入,所以位置是一致的。

private  void setStyle(XWPFDocument doc,XWPFDocument tempdoc, Map<String, Object> params) {
Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator();
Iterator<XWPFParagraph> iterator2 = tempdoc.getParagraphsIterator();
XWPFParagraph para ;
XWPFParagraph para2;
while (iterator.hasNext()) {
para = iterator.next();
para2 = iterator2.next();
this.styleInPara(para,para2, params);
}
}
private void setStyle(XWPFParagraph para, XWPFParagraph para2,Map<String, Object> params) {
List<XWPFRun> runs;
List<XWPFRun> runs2;
Matcher matcher;
if (matcher(para.getParagraphText()).find()) {
runs = para.getRuns();
runs2 = para2.getRuns();
for (int i=0; i<runs.size(); i++) {
XWPFRun run = runs.get(i);
XWPFRun run2 = runs2.get(i);
String runText = run.toString();
matcher = matcher(runText);
if (matcher.find()) {
//按模板文件格式设置格式
run2.getCTR().setRPr(run.getCTR().getRPr());
}
}
}
}

按照原模板格式设置好替换后格式后显示正常。

ps:XWPFRun表示有相同属性的一段文本,所以模板里变量内容需要从左到右的顺序写,${userName},如果先写${},再添加内容,会拆分成几部分,不能正常使用

poi 针对word模板内容替换的更多相关文章

  1. 使用java Apache poi 根据word模板生成word报表

    项目开发过程中,客户提出一堆导出报表的需求,需要导出word格式,页眉还需要加上客户公司的logo,试了几种方案,最后选择了用 Apache poi 加上自定义标签的方式实现. 目前功能还比较简单,一 ...

  2. 利用POI 技术动态替换word模板内容

    项目中需要实现一个功能,动态替换给定模板里面的内容,生成word文档提供下载功能. 中间解决了问题有: 1.页眉的文档logo图片解决,刚开始的时候,HWPFDocument 对象无法读取图片对象(已 ...

  3. poi导出word模板项目实例(一个文件)

    在页面上填写值,然后导出到word模板中,并把页面上的值带到模板中,也就是导出word文档,提前有word 的模板形式, 1.jsp 页面   <table class="formTa ...

  4. POI往word模板中写入数据

    转: POI往word模板中写入数据 2018年03月24日 16:00:22 乄阿斗同學 阅读数:2977  版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn ...

  5. C# 操作word 模板 值 替换

    1.引用 aspose.words   dll 2.word 使用doc 3.给word 模板中添加要替换位置的 书签 .引用 aspose.words dll .word 使用doc .给word ...

  6. poi读写word模板 / java生成word文档

    有一word文档表格 形如: 姓名 ${name} 电话 ${tel} 从数据库读取记录替换上述变量 import java.io.FileOutputStream; import java.util ...

  7. ConterReplaceBehavior.class.php模板内容替换,如__PUBLIC__

    ConterReplaceBehavior.class.php查找 __PUBLIC__ protected function templateContentReplace($content) { / ...

  8. .NET使用NPOI读取Word模板并替换关键字并下载

    NPOI 是 POI 项目的 .NET 版本.POI是一个开源的Java读写Excel.WORD等微软OLE2组件文档的项目. 使用 NPOI 你就可以在没有安装 Office 或者相应环境的机器上对 ...

  9. poi读取word的内容

    pache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能. 1.读取word 2003及word 2007需要的 ...

随机推荐

  1. MutationObserver 监听 DOM 树变化

    MutationObserver 是用于代替 MutationEvents 作为观察 DOM 树结构发生变化时,做出相应处理的 API .为什么要使用 MutationObserver 去代替 Mut ...

  2. 替换input单选框的样式

    实现效果:. css的input单选框的样式很丑,有时候不想使用原生的样式,如上照片,可以使用下面的方法. 思路是,给inpu加visibility:hidden隐藏,然后使用不同的图片绝对定位覆盖在 ...

  3. Windows 10 MSDN官方原版ISO镜像(简体中文)下载

    http://www.heu8.com/2800.html 硬件要求如下:处理器:1 GHz 或更快的处理器或 SoC RAM:1 GB(32 位)或 2 GB(64 位) 硬盘空间:16 GB(32 ...

  4. C++课程设计,12306模拟写起来就是这么粗暴

    这篇文章很详细,也很多希望可以好好看看!看完C++稳过! 一.12306应该具备那些功能 1.查询(一个月以内的): 1.查车票:出发地+目的地+出发时间->显示经过两站车票信息 (余票,车次信 ...

  5. js世家委托详解

    事件原理 通过div0.addElementListener来调用:用法:div0.addElementListener(事件类型,事件回调函数,是否捕获时执行){}.1.事件类型(type):必须是 ...

  6. jmeter正则表达式提取多个数据/一组数据时,应该怎么做——debug sampler的使用

    背景:今天有个接口需要借助前面接口产生的一组ids数据,来作为入参使用,但是之前都是提取单个接口,所以到底怎么提取接口,遇到了很大的问题,按照多方查取资料都没有成功,最终在一个不相关帖子的最后一句话被 ...

  7. 大富翁 线段树+二分 +dfs

    https://csustacm.fun/problem/2033 这个题目还是比较简单的,但是比赛的时候没有像清楚,用了一个不太熟悉的数据结构主席树, 所以出现了bug,主席树的bug是真的难找. ...

  8. C. Coffee Break 贪心 思维 有点难 有意思

    C. Coffee Break 这个贪心之前好像写过,还是感觉挺难的,有点不会写. 这个题目大意是:给你一个数列n个元素,然后给你一天的时间,给你一个间隔时间d, 问你最少要用多少天可以把这个数列的所 ...

  9. Spark离线日志分析,连接Spark出现报错

    首先,我的代码是这样的 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} object ...

  10. Mybatis学习笔记汇总(包括源码和jar包)

    博客整理 Mybatis学习笔记(一)--对原生jdbc中问题的总结 Mybatis学习笔记(二)--Mybatis框架 Mybatis学习笔记(三)--入门程序 MyBatis学习笔记(四)--入门 ...