Java模板动态生成word文件的方法步骤
作者:麋途知鹿 发布时间:2023-01-08 15:19:58
最近项目中需要根据模板生成word文档,模板文件也是word文档。当时思考一下想用POI API来做,但是觉得用起来相对复杂。后来又找了一种方式,使用freemarker模板生成word文件,经过尝试觉得还是相对简单易行的。
使用freemarker模板生成word文档主要有这么几个步骤
1、创建word模板:因为我项目中用到的模板本身是word,所以我就直接编辑word文档转成freemarker(.ftl)格式的。
2、将改word文件另存为xml格式,注意使用另存为,不是直接修改扩展名。
3、将xml文件的扩展名改为ftl
4、编写java代码完成导出
使用到的jar:freemarker.jar (2.3.28) ,其中Configuration对象不推荐直接new Configuration(),仔细看Configuration.class文件会发现,推荐的是 Configuration(Version incompatibleImprovements) 这个构造方法,具体这个构造方法里面传的就是Version版本类,而且版本号不能低于2.3.0
闲言碎语不再讲,直接上代码
public static void exportDoc() {
String picturePath = "D:/image.png";
Map<String, Object> dataMap = new HashMap<String, Object>();
dataMap.put("brand", "海尔");
dataMap.put("store_name", "海尔天津");
dataMap.put("user_name", "小明");
//经过编码后的图片路径
String image = getWatermarkImage(picturePath);
dataMap.put("image", image);
//Configuration用于读取ftl文件
Configuration configuration = new Configuration(new Version("2.3.0"));
configuration.setDefaultEncoding("utf-8");
Writer out = null;
try {
//输出文档路径及名称
File outFile = new File("D:/导出优惠证明.doc");
out = new BufferedWriter(new OutputStreamWriter(new
FileOutputStream(new File("outFile")), "utf-8"), 10240);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// 加载文档模板
Template template = null;
try {
//指定路径,例如C:/a.ftl 注意:此处指定ftl文件所在目录的路径,而不是ftl文件的路径
configuration.setDirectoryForTemplateLoading(new File("C:/"));
//以utf-8的编码格式读取文件
template = configuration.getTemplate("导出优惠证明.ftl", "utf-8");
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("文件模板加载失败!", e);
}
// 填充数据
try {
template.process(dataMap, out);
} catch (TemplateException e) {
e.printStackTrace();
throw new RuntimeException("模板数据填充异常!", e);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("模板数据填充异常!", e);
} finally {
if (null != out) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("文件输出流关闭异常!", e);
}
}
}
}
因为很多时候我们根据模板生成文件需要添加水印,也就是插入图片
/***
* 处理图片
* @param watermarkPath 图片路径 D:/image.png
* @return
*/
private String getWatermarkImage(String watermarkPath) {
InputStream in = null;
byte[] data = null;
try {
in = new FileInputStream(watermarkPath);
data = new byte[in.available()];
in.read(data);
in.close();
} catch (Exception e) {
e.printStackTrace();
}
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(data);
}
注意点:
插入图片后的word转化为ftl模板文件(ps:水印图片可以在word上调整到自己想要的大小,然后在执行下面的步骤)
1、先另存为xml
2、将xml扩展名改为ftl
3、打开ftl文件, 搜索w:binData 或者 png可以快速定位图片的位置,图片 已经编码成0-Z的字符串了, 如下:
5、 将上述0-Z的字符串全部删掉,写上${image}(变量名随便写,跟dataMap里的key保持一致)后保存
6、也是创建一个Map, 将数据存到map中,只不过我们要把图片用代码进行编码,将其也编成0-Z的字符串,代码请看上边
至此一个简单的按照模板生成word并插入图片(水印)功能基本完成。
来源:https://www.cnblogs.com/4king/p/11728575.html


猜你喜欢
- Android如何自定义一个view ViewRootImpl绘制流程1、自定义属性在res/values/attrs.xml文件里定义一个
- EntityWrapper的常用方法#WHERE (issue_type = ?) AND (status = ? OR status =
- Android9.0无法通过以下两种方式实现静默安装:1.runtime执行shell cmd2.PackageInstall 反射机制但是
- 前言${} 和 #{} 都是 MyBatis 中用来替换参数的,它们都可以将用户传递过来的参数,替换到 MyBatis 最终生成的
- 模块之间总是存在这一定的接口,从调用方式上看,可以分为三类:同步调用、回调和异步调用。下面着重详解回调机制。1. 概述Java 中的回调机制
- 这是之前软工课设我写的java访问mysql工具类,它经过了多轮的测试,应该能够适应大多数的操作需求。比之前大二写的更鲁棒,更易用。pack
- 使用JPA CriteriaQuery查询的注意事项1.pojo类@Entity@Table(name = "report_wor
- 上文对数据结构与算法,有了一个简单的概述与介绍,这篇文章,我们介绍一中典型数据结构——线性结构。什么是线性结构,线性结构是最简单、最基本、最
- 本文实例为大家分享了ActionBar下拉式导航的实现代码,供大家参考,具体内容如下利用Actionbar同样可以很轻松的实现下拉式的导航方
- 一、deleteById 和 delete为什么要把这两个方法放在一起呢?我们先看源码再说deleteById(Id id)(通过id进行删
- JDK8已发布,写了一个datetime时间函数使用方法的小示例package datetime;import static java.ti
- 问题描述:某天打开项目的activity的java文件界面突然变成下面这样了,但是用Notepad++打开代码什么的都正常,不知道什么原因造
- 本文实例为大家分享了Android实现简单画图画板的具体代码,供大家参考,具体内容如下效果如图:布局文件:<RelativeLayou
- 注释介绍@Cacheable@Cacheable 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存@Cacheable 作用
- 这几天琢磨写一个Android的Runtime用来加速HTML5 Canvas,让GameBuilder+CanTK 不但开发速度快,运行速
- 本文以实例形式分析了C#中Predicate<T>与Func<T, bool>泛型委托的用法,分享给大家供大家参考之
- 日期显示和选择类库,可以用来选择一段连续的和多个不连续的日期,具体的UI完全抽象出来了,可以高度自定义(GITHUB地址)支持的功能:1、选
- 目录前言一、技术介绍1.Minio是什么?二、使用步骤1.引入maven库2.封装Minio3.配置文件4.单元测试总结前言使用Spring
- 1、多个线程对同一个队列进行读写操作,要注意进行读写控制,某个线程在读取的时候,不允许其它线程读、写;某个线程在写的时候,不允许其它线程进行
- 下面通过一段内容有文字说明有代码分析,并附有展示图供大家学习。要解析HTTP报文,需要实现以下操作:读取HTTP报头提供的各种属性分析属性值