最近多了一个需求,需要对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. 如何创建和部署自己的EOS代币

    本文我们将弄清楚什么是EOS代币以及如何自己创建和部署EOS代币. 与以太坊相反,EOS带有即插即用的代币智能合约.以太坊拥有ERC20智能合约,EOS拥有eosio.token智能合约.Eosio. ...

  2. 《PostgreSQL服务器编程》一一1.3 超越简单函数

    本节书摘来自华章计算机<PostgreSQL服务器编程>一书中的第1章,第1.3节,作者:(美)Hannu Krosing, Jim Mlodgenski, Kirk Roybal 著,更 ...

  3. Android Room SQLite持久层框架

    原文链接 前言 Android中提供了SQLite数据库进行数据的持久化 ,并提供了对应API访问数据库,而Room框架提供了SQLite数据访问抽象层,为高效的数据库访问层带来便捷 APP可以缓存用 ...

  4. linux服务器(CentOS)一键安装express框架

    express框架需要nodejs环境支持,没有安装node.js环境的同学可以参照下面这篇博客 linux服务器安装配置Node.js 好了,言归正传.先使用xshell或者其它软件连接我们的服务器 ...

  5. ACM学习总结 6月11日

    经过这几天没有队友的协助,又是算法题比较多,有点碰触到自己的短板,因为搜索的题目就做了1个,一遇到搜索就跳过,DP也有点忘得差不多了,四边形优化,斜率优化还不会,这是下一阶段努力方向,把之前做过的题, ...

  6. 推荐算法_CIKM-2019-AnalytiCup 冠军源码解读

    最近在帮一初创app写推荐系统,顺便学习一波用户兴趣高速检索的冠军算法. 写总结前贴出冠军代码的git地址:https://github.com/ChuanyuXue/CIKM-2019-Analyt ...

  7. C# 判断文件格式的一些总结

    前提概述: 项目中 经常会有上传图片的地方  有的时候需要对图片类型做一些要求   这个时候就需要一些判断   虽然前段上传的时候可以去做类型的限制  或者后台接受的时候从file的type 中获取图 ...

  8. 【HBase】Java实现过滤器查询

    目录 概述 代码实现 rowKey过滤器RowFilter 列族过滤器FamilyFilter 列过滤器QualifierFilter 列值过滤器ValueFilter 专用过滤器 单列值过滤器 Si ...

  9. 【Hadoop离线基础总结】impala简单介绍及安装部署

    目录 impala的简单介绍 概述 优点 缺点 impala和Hive的关系 impala如何和CDH一起工作 impala的架构及查询计划 impala/hive/spark 对比 impala的安 ...

  10. 这或许是最详细的JUC多线程并发总结

    多线程进阶---JUC并发编程 完整代码传送门,见文章末尾 1.Lock锁(重点) 传统 Synchronizd package com.godfrey.demo01; /** * descripti ...