1.简介

处理word的方式有许多种:

  1. 使用Hutool工具类,但是只能处理简单的word,不能处理表格,动态图片,替换文字等
  2. 使用Apache POI,可以处理复杂的Word文档,但是处理过程复杂,word转xml,xml再转ftl才可进行操作,不适合经常处理word
  3. 其他第三方工具
  4. XDocReport +FreeMarker,该技术组合既简单又高效可实现word模板的编辑,只可处理docx文件

本文将实现动态文本替换、动态图片替换、动态表格填充。

2.pom引入

<dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagres.xdocreport.core</artifactId><version>2.0.2</version>
</dependency>
<dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagres.xdocreport.document</artifactId><version>2.0.2</version>
</dependency>
<dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagres.xdocreport.template</artifactId><version>2.0.2</version>
</dependency>
<dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagres.xdocreport.document.docx</artifactId><version>2.0.2</version>
</dependency>
<dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagres.xdocreport.template.freemarker</artifactId><version>2.0.2</version>
</dependency>
<dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.23</version>
</dependency>

3.动态文本替换

比如说我们有个邮件word模板,需要动态的在横线处填入相关信息,然后生成完整的word文档。

我们做以下操作:

  1. 将横线位置替换成域
  2. 给每个要替换的位置取个名字
  3. FreeMarker域格式为—— ${……},具体操作可以查看视频模板添加域示例(下面添加域方法同理)

代码实现

import fr.opensagres.xdocreport.document.IXDocReport;
import fr.opensagres.xdocreport.document.registry.XDocReportRegistry;
import fr.opensagres.xdocreport.template.IContext;
import fr.opensagres.xdocreport.template.TemplateEngineKind;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;/*** @author: YSL* @date: 2022/8/2 17:42*/
public class WordTemplate {private static final Logger logger = LoggerFactory.getLogger(WordTemplate.class);public static void test() {InputStream ins = null;OutputStream out = null;try {//获取Word模板,模板存放路径ins = new FileInputStream("C:\\Users\\she52\\Desktop\\演示.docx");//注册xdocreport实例并加载FreeMarker模板引擎IXDocReport report = XDocReportRegistry.getRegistry().loadReport(ins, TemplateEngineKind.Freemarker);//创建xdocreport上下文对象,用于存放具体数据IContext context = report.createContext();//创建要替换的文本变量context.put("name", "李梅");context.put("sendName", "张三");context.put("year", "2022");context.put("month", "08");context.put("day", "03");//输出到本地目录String filePath = "C:\\Users\\she52\\Desktop\\结果.docx";out = new FileOutputStream(new File(filePath));report.process(context, out);} catch (Exception e) {logger.info("生成word发生异常", e);} finally {try {if (ins != null){ins.close();}if (out != null){out.close();}} catch (IOException e) {logger.info("文件流关闭失败", e);}}}
}

注意,执行代码时要把word模板关掉,否则模板加载不成功,会报错

执行结果:

4.动态表格

如果表格是标准的几行几列的列表,使用以下方法。如果不是标准的,比如说合并单元格,则需要使用上 面文本替换的方法,挨个起名赋值。

我们做以下操作:

  1. 除了标题行,保留一行空白行,删掉其余的空白行(为什么这么做,因为表格填充,本质是列表循环填写,列表大小是不确定的,我们只保留一行,让它自己根据列表大小创建行数)
  2. 起一个列表名,比如上面的示例表是用户信息表,则起名为userInfo
  3. 对用户信息属性挨个起名,姓名name、年龄age、性别sex
  4. 第2和第3步骤,等同于新建一个Java实体类
  5. 添加域,命名规范-----userInfo.name、{userInfo.name}、userInfo.name、{userInfo.age}、${userInfo.sex},自己总结规律
  6. 修改完后记得保存,然后关闭word

代码实现:

import fr.opensagres.xdocreport.document.IXDocReport;
import fr.opensagres.xdocreport.document.registry.XDocReportRegistry;
import fr.opensagres.xdocreport.template.IContext;
import fr.opensagres.xdocreport.template.TemplateEngineKind;
import fr.opensagres.xdocreport.template.formatter.FieldsMetadata;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;/*** @author: YSL* @date: 2022/8/2 17:42*/
public class WordTemplate {private static final Logger logger = LoggerFactory.getLogger(WordTemplate.class);public static void test() {InputStream ins = null;OutputStream out = null;try {//获取Word模板,模板存放路径ins = new FileInputStream("C:\\Users\\she52\\Desktop\\演示.docx");//注册xdocreport实例并加载FreeMarker模板引擎IXDocReport report = XDocReportRegistry.getRegistry().loadReport(ins, TemplateEngineKind.Freemarker);//创建xdocreport上下文对象,用于存放具体数据IContext context = report.createContext();//创建要替换的文本变量List<UserInfo> userInfos = new ArrayList<>();UserInfo userInfo = new UserInfo();userInfo.setName("张三");userInfo.setAge("15");userInfo.setSex("男");userInfos.add(userInfo);UserInfo userInfo1 = new UserInfo();userInfo1.setName("李四");userInfo1.setAge("14");userInfo1.setSex("男");userInfos.add(userInfo1);UserInfo userInfo2 = new UserInfo();userInfo2.setName("李梅");userInfo2.setAge("16");userInfo2.setSex("女");userInfos.add(userInfo2);//此处的userInfo是word中命名的列表名context.put("userInfo", userInfos);//创建字段元数据FieldsMetadata fm = report.createFieldsMetadata();//Word模板中的表格数据对应的集合类型fm.load("userInfo", UserInfo.class, true);//输出到本地目录String filePath = "C:\\Users\\she52\\Desktop\\结果.docx";out = new FileOutputStream(new File(filePath));report.process(context, out);} catch (Exception e) {logger.info("生成word发生异常", e);}finally {try {if (ins != null){ins.close();}if (out != null){out.close();}} catch (IOException e) {logger.info("文件流关闭失败", e);}}}
}@Data
public class UserInfo{private String name;private String age;private String sex;
}

执行结果

注意,代码中创建的UserInfo实体类必须是public公共的,否则赋不到值

5.动态图片

比如说word文档中有,勾选框, 同意则打对勾。我们可以将勾选框变成图片,再令准备一张打好对勾的图片,如果勾选则将其替换,否则不替换,就可以完美解决勾选问题。

做以下操作:

  1. 将勾选的圆圈替换成大小相同的图片,可以让UI帮忙整一个
  2. 给图片添加标签并命名,直接写名字就行,不用加${}

代码实现:

import fr.opensagres.xdocreport.document.IXDocReport;
import fr.opensagres.xdocreport.document.images.ByteArrayImageProvider;
import fr.opensagres.xdocreport.document.registry.XDocReportRegistry;
import fr.opensagres.xdocreport.template.IContext;
import fr.opensagres.xdocreport.template.TemplateEngineKind;
import fr.opensagres.xdocreport.template.formatter.FieldsMetadata;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.*;/*** @author: YSL* @date: 2022/8/2 17:42*/
public class WordTemplate {private static final Logger logger = LoggerFactory.getLogger(WordTemplate.class);public static void test() {InputStream in = null;OutputStream out = null;FileInputStream fins = null;try {//获取Word模板,模板存放路径in = new FileInputStream("C:\\Users\\she52\\Desktop\\演示.docx");//注册xdocreport实例并加载FreeMarker模板引擎IXDocReport report = XDocReportRegistry.getRegistry().loadReport(in, TemplateEngineKind.Freemarker);//创建xdocreport上下文对象,用于存放具体数据IContext context = report.createContext();//图片元数据FieldsMetadata metadata = report.createFieldsMetadata();//读取对勾圆形图片fins = new FileInputStream(new File("C:\Users\she52\Desktop\hookRound.png"));metadata.addFieldAsImage("accept");//只在同意上打对勾,不同意那个图片则不用管context.put("accept", new ByteArrayImageProvider(fins));report.setFieldsMetadata(metadata);//输出到本地目录String filePath = "C:\\Users\\she52\\Desktop\\结果.docx";out = new FileOutputStream(new File(filePath));report.process(context, out);} catch (Exception e) {logger.info("生成word发生异常", e);}finally {try {if (in != null){in.close();}if(fins != null){fins.close();}if(out != null){out.close();}} catch (IOException e) {logger.info("文件流关闭失败",e);}}}
}

运行结果:

注意

  1. 读取图片大多人用IImageProvider image = FileImageProvider(new File(……));但是这种方式,文件流不能关闭,所以用ByteArrayImageProvider(new FileInputStream())可及时关闭InputStream流。

  2. 如果word有多个地方需要不同的动态图片,可以挨个对图片添加书签并命名,然后重复以下代码

fins = new FileInputStream(new File("C:\Users\she52\Desktop\image1.png"));
metadata.addFieldAsImage("image1");
context.put("image1", new ByteArrayImageProvider(fins));

6.总结

如果Word模板文件复杂,则融合上面三种方法,即可满足绝大部分需求,如果满足不了,百度吧__

Java根据word模板生成word文件相关推荐

  1. java 根据word模板生成word文件

    Java可以使用Apache POI库来生成Word文件,并且也可以使用freemarker等模板引擎来实现根据Word模板生成Word文件的功能. 下面是一个简单的示例代码,可以帮助您快速入门. 模 ...

  2. apache poi使用例_使用java Apache poi 根据word模板生成word报表例子

    [实例简介] 使用java Apache poi 根据word模板生成word报表 仅支持docx格式的word文件,大概是word2010及以后版本,doc格式不支持. 使用说明:https://b ...

  3. JAVA实现模板word文档导入,Java依据word模板生成word文档之后台解析和实现及部分代码(一)...

    Java根据word模板生成word文档之后台解析和实现及部分代码(一) 后台主要工作是解析XML定义的标签文件,并获取到数据集,放入到Map中,然后调用Jacob.jar中提供的相关方法来实现替换. ...

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

    使用java Apache poi 根据word模板生成word报表 使用poi读取word模板,替换word中的{text}标签,并根据自定义标签循环生成表格或表格中的行. 代码示例下载:https ...

  5. 根据word模板生成word和PDF

    根据word模板生成word和PDF 需求:有一个固定的合同模板,在vue前台填写指定的信息,替换合同模板指定的内容 我们使用的默认模板内容如图: 我们在前端填写的字段就是合同名称.项目名称和项目金额 ...

  6. word模板生成word报表文档

    主要功能为根据word模板生成word报表文档,注意引用Interop.Word.dll; 首先要生成word程序对象 Word.Application app = new Word.Applicat ...

  7. C#根据word模板生成word表格报表文档

    主要功能为根据word模板生成word报表文档,注意引用Interop.Word.dll; 首先要生成word程序对象 Word.Application app = new Word.Applicat ...

  8. 使用word模板生成word文档的各类方案

    使用word模板生成word文档的各类方案 生成word的各种方案 word另存xml进行后续处理 2003版本word(.doc)的xml处理并生成word 2007版本word(.docx)的xm ...

  9. PHP 使用word模板生成word文档示例

    <?php namespace Home\Controller; use PhpOffice\PhpWord\TemplateProcessor; use Think\Controller; c ...

  10. java手动/按模板生成word与excel

    目录 一.前言 二.生成word 1.使用Apache poi手动生成一个word (1)导入依赖 (2)手动生成一个包含表格的word 2.使用Apache poi 按模板生成一个简单的word ( ...

最新文章

  1. 200万!这所“双一流”也开始高薪抢人了!
  2. RabbitMQ 消费端限流、TTL、死信队列
  3. 【Android 逆向】Android 进程注入工具开发 ( 编译注入工具 | 编译结果文件说明 | 注入过程说明 )
  4. CloudStack无法添加模板和iso
  5. linux搭建web服务器原理,【LINUX】linux搭建web服务器
  6. 【Linux】kali 2019.4 安装中文输入法
  7. 再接再厉!Alphabet将携手更多汽车厂商测试无人驾驶
  8. opencv 调整图像亮度和对比度
  9. panel items 添加指定位置_通过gitlab-ci自动添加prometheus业务监控
  10. macbook加入路由_笔记本怎么安装无线路由器 MacBook安装无线路由器方法【详细步骤】...
  11. VUE实现市、区二级联动
  12. 天猫精灵通过私有云控制WiFi设备
  13. Android 实现远程控制(类似QQ的远程协助)
  14. autoJS 网易公开课app封装函数
  15. ubuntu服务器安装及网络配置
  16. android设备控制机器人,基于Android手机的六足机器人控制方案的设计与实现
  17. 自定义Maven Archetype模板工程
  18. Linux下shell命令:top
  19. python基于django的商品比价平台
  20. 关于SEGGER和Jlink下载的问题

热门文章

  1. 联通鸿蒙卡充值,中国联通“一卡充”实现全业务充值
  2. python爬虫之JS混淆加密、字体反爬
  3. MG513P30 12V直流减速电机编码器电线与杜邦线焊接教程
  4. 妙算2的串口用自己的接线(杜邦线)连接无人机210或者stm32
  5. 手机蓝牙绑定pc,离开电脑自动锁屏
  6. linux虚拟机中如何复制粘贴内容到主机
  7. SCC flex布局
  8. 段地址寄存器、偏移地址寄存器
  9. 简述人工智能的发展历程图_人工智能的历程、现状及未来发展趋势
  10. 算法题目打卡:Ques20201025