最近在做项目的时候遇到需要生成word文档,两眼一抹黑,之前只做过生成Excel的,对于word没有遇到,所以有点抓瞎,在网上也查找了很多,看着说的挺好,但是一用就不行,总是有问题,下面介绍一下我用的这种方式:
1、什么是poi-tl(poi-template-language)
poi-tl是一种 "logic-less" 模板引擎,没有复杂的控制结构和变量赋值,只有标签,一些标签可以被替换为文本、图片、表格等,一些标签会隐藏某些文档内容,而另一些标签则会将一系列文档内容循环渲染。
Apache POI不仅在上层封装了易用的文档API(文本、图片、表格、页眉、页脚、图表等),也可以在底层直接操作文档XML结构,poi-tl正是一个基于Apache POI的Word模板引擎,并且拥有着让人喜悦的特性。poi-tl是一个免费开源的Java类库。
2、引入poi-tl
- 首先说一下使用poi-tl的要求:
- Apache POI 4.1.1+
- JDK 1.8+
- 下面引入依赖:
--Maven
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.8.0</version>
</dependency>
--Gradle
compile group: 'com.deepoove', name: 'poi-tl', version: '1.8.0'
3、快速开始
// 简单的示例
public void exportWord(){
Map<String, Object> data = new HashMap<String, Object>();
data.put("name", "H早起的鸟");
data.put("sex", "男");
data.put("job", "IT");
// 图片,photoPath本地图片的路径
data.put("photo", new PictureRenderData(127, 185, photoPath));
try {
//获取模板的绝对路径
ClassPathResource template = new ClassPathResource("word/template.docx");
String templatePath = template.getFile().getPath();
//核心API采用了极简设计,只需要一行代码
// out_template_path是生成word文件的路径
XWPFTemplate.compile(templatePath).render(data).writeToFile(out_template_path);
} catch (Exception e) {
log.info("文件生成失败:"+e.getMessage());
throw new DataNotFoundException("文件生成失败:"+e.getMessage());
}
}
--图片支持多种方式
--在PictureRenderData 图片渲染类里边
/**
* 根据本地路径构建图片数据源
*
* @param width
* 宽度
* @param height
* 高度
* @param path
* 本地图片路径
*/
public PictureRenderData(int width, int height, String path) {
this.width = width;
this.height = height;
this.path = path;
}
/**
* 根据File文件构建图片数据源
*
* @param width
* @param height
* @param picture
*/
public PictureRenderData(int width, int height, File picture) {
this(width, height, picture.getPath(), ByteUtils.getLocalByteArray(picture));
}
/**
* 根据流构建图片数据源
*
* @param width
* @param height
* @param picture
*/
public PictureRenderData(int width, int height, String format, InputStream input) {
this(width, height, format, ByteUtils.toByteArray(input));
}
/**
* 根据BufferedImage构建图片数据源
*
* @param width
* @param height
* @param format
* @param image
*/
public PictureRenderData(int width, int height, String format, BufferedImage image) {
this(width, height, format, BytePictureUtils.getBufferByteArray(image, format));
}
/**
* 根据字节数组构建图片数据源
*
* @param width
* 宽度
* @param height
* 高度
* @param format
* 标识图片后缀,如.png、.jpg等
* @param data
* 图片byte[]数据,可以通过工具类{@link BytePictureUtils}生成
*/
public PictureRenderData(int width, int height, String format, byte[] data) {
this.width = width;
this.height = height;
this.path = format;
this.data = data;
}
4、模板中标签的使用
- 文本标签是Word模板中最基本的标签类型,
{{name}}
会被数据模型中key为name
的值替换,如果找不到默认会清空标签,可以配置是保留还是抛出异常。 - 图片标签以
@
开始,如{{@logo}}
会在数据中寻找key为logo
的值,然后将标签替换成图片。由于Word文档中图片不是由字符串表示(在文本型模板中,比如HTML网页图片是由字符串<img src="" />
表示),所以图片标签对应的数据有一定的结构要求,这些结构都会有相应的Java类对应 - 表格标签以
#
开始,如{{#table}}
,它会被渲染成N行N列的Word表格,N的值取决于table
标签的值。 - 列表标签对应Word的符号列表或者编号列表,以
*
开始,如{{*number}}
。 - 区块对由前后两个标签组成,开始标签以
?
标识,结束标签以/
标识,如{{?sections}}
作为sections区块的起始标签,{{/sections}}
为结束标签,sections是这个区块对的名称。 - 嵌套是在Word模板中引入另一个Word模板,可以理解为import、include或者word文档合并,以
+
标识,如{{+nested}}
。
5、官方文档
poi-tl:http://deepoove.com/poi-tl/
Apache POI Word快速入门:http://deepoove.com/poi-tl/apache-poi-guide.html