使用POI-tI实现数据导出到word之快速入门
因为POI-ti的不同版本的变动比较明显,所以以下都是使用1.9.1版本,本篇文章只针对快速使用POI-ti实现数据导出功能,而数据导出功能的实现,基本上都是依赖于各种各样的标识符,所以,本片文章旨在搞懂常见标识符的使用。POI-ti的使用总体分为三部分:①自定义文档模板;②编译模板+数据填充;③数据渲染;文档模板中,POI-ti默认的标识符都是以 {{ 开头,并以 }} 结尾的。
注意:以下标签中的var是自定义的,但是必须保证要与数据填充的变量名对应上。
引入依赖
<!--poi-tl-->
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.9.1</version>
</dependency>
<!--hutool工具类-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.18</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>5.8.18</version>
</dependency>
文本标签
标识符:{{var}}
文档模板(保存为docx文件)
模板编译
模板编译的操作首先执行,且只能执行一次,是公用的;
XWPFTemplate template = null;
//方式1:加载模板文件
File file = new File("C:templates\\poi\\模板.docx");
template = XWPFTemplate.compile(file);
//方式2:加载指定路径对应的文件
template = XWPFTemplate.compile("C:templates\\poi\\模板.docx"");
//方式3:加载IO输入流
InputStream is =ResourceUtil.getResourceObj("模板.docx").getStream();
template = XWPFTemplate.compile(is); //加载IO流文件的方式,是从classpass路径开始找;
数据填充
String:直接赋值
//准备参数(普通参数建议使用map装载)
HashMap<String, Object> map = new HashMap<>();
map.put("name", "张三");
map.put("gender", "男");
map.put("age", 18);
map.put("collect", "信息工程学院");
map.put("major", "计算机应用");
map.put("xl", "本科");
map.put("phone", "17788899900");
TextRenderData:可以指定文本的样式
TextRenderData textRenderData = new TextRenderData();
textRenderData.setText("信息工程学院");
Style style = Style.builder()
.buildFontFamily("微软雅黑")
.buildFontSize(10)
.buildColor("7F7F7F")
.build();
textRenderData.setStyle(style);
map.put("collect", textRenderData);
数据渲染
模板编译的操作最后执行,且只能执行一次,是公用的;
template.render(map);
图片标签
标识符:{{@var}}
文档模板
数据填充
//方式1:直接传递图片地址
put("photo", "C:\\logo.png"); //绝对地址
put("photo", "https://img.shields.io/badge/jdk-1.6%2B-orange.svg"); //网络地址
//方式2:使用Pictures构建
put("photo", Pictures.ofLocal("C:\\logo.png").size(120, 120).create()); //绝对路径
put("photo", Pictures
.ofStream(new FileInputStream("C:\\logo.jpeg"), PictureType.JPEG)
.size(100, 120)
.create()
); //IO流
put("photo", Pictures
.ofUrl("http://deepoove.com/images/icecream.png")
.size(100, 100)
.create()
); //网络地址
表格标签
标识符:{{#var}}
文档模板
数据填充
方式1:使用工厂 Tables 、 Rows 和 Cells 构建表格模型
//举例:第0行居中且背景为蓝色的表格
RowRenderData row0 = Rows.of("姓名", "学历").textColor("FFFFFF")
.bgColor("4472C4").center().create();
RowRenderData row1 = Rows.create("李四", "博士");
put("table", Tables.create(row0, row1));
方式2:使用TableRenderData构建
注意:这种方式比较麻烦,在POI-ti1.5的版本时还比较好,使用POI-ti1.9版本时,就变得非常麻烦,这里不做演示
上面三种标签使用的完整代码
注意:这里是将数据输出到word文件并下载的方式
public class Test{
public void test(HttpServletResponse response) {
Resource resource = null;
InputStream is = null;
ServletOutputStream sos = null;
XWPFTemplate template = null;
try {
//1,获取模板文件
resource = ResourceUtil.getResourceObj("templates/模板.docx");
is = resource.getStream();
//2,编译模板
template = XWPFTemplate.compile(is);
//3,准备参数(普通参数建议使用map装载)
HashMap<String, Object> map = new HashMap<>();
map.put("name", "张三");
map.put("gender", "男");
map.put("age", 18);
map.put("collect", "信息工程学院");
map.put("major", "计算机应用");
map.put("xl", "本科");
map.put("phone", "17788899900");
map.put("photo", Pictures.ofUrl("http://deepoove.com/images/icecream.png", PictureType.PNG).size(100, 100).create());
RowRenderData row0 = Rows.of("姓名", "学历").textColor("FFFFFF")
.bgColor("4472C4").center().create();
RowRenderData row1 = Rows.create("李四", "博士");
map.put("table", Tables.create(row0, row1));
//4,数据渲染
template.render(map);
//5,设置响应参数
response.setContentType("application/vnd.ms-word"); //数据类型
response.setCharacterEncoding("utf-8"); //编码格式
//如果响应中带有附件,需要设置下面这行参数
response.setHeader("Content-disposition", "attachment; filename="
//ISO-8859-1适用范围比UTF-8更广泛,但自身无法显示中文,需要配合其他编码集使用,如UTF-8
+ new String(resource.getName().getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1)); //附件名称
sos = response.getOutputStream();
//6,输出
template.writeAndClose(sos); //IO流
// template.writeToFile(""); //输出到文件
} catch (IOException e) {
e.printStackTrace();
}
}
列表标签
标识符:{{*var}}
文档模板
数据填充
put("hobby", Numberings.create("唱","跳","rap"));
区块对
标识符:{{?var}} … {{/var}}
两个标签之间是其他标识符,这种方式的实现情况有很多种,常用的就两种:标签内的其他标签值为空或条件为false时,不会填充该标签;标签内的数据可以是一条也可以是集合;
注意:这种方式必须是使用模板类进行填充,不能使用Map;
文档模板
代码
模板类
public class info {
private String school;
private String addr;
private List<User> users;
//get和set方法...
}
public class User{
private string name;
private Integer age;
private Character gender;
//get和set方法...
}
方法实现
Info data = new Info();
public void test(HttpServletResponse response) {
Resource resource = null;
InputStream is = null;
ServletOutputStream sos = null;
XWPFTemplate template = null;
try {
sos = response.getOutputStream();
//1,获取模板文件
resource = ResourceUtil.getResourceObj("templates/模板.docx");
is = resource.getStream();
//2,编译模板
template = XWPFTemplate.compile(is);
//3,准备参数(普通参数建议使用map装载)
data.setSchool("xx大学");
TextRenderData renderData = new TextRenderData("xx省。。。");
Style style = Style.builder().buildFontSize(10).buildColor("7F7F7F").buildFontFamily("微软雅黑").build();
renderData.setStyle(style);
data.setAddr(renderData.getText());
ArrayList<User> list = new ArrayList<>();
User u1 = new User();
u1.setName("张三");
u1.setAge(20);
u1.setGender('男');
TextRenderData hobby = new TextRenderData("唱,跳,rap");
hobby.setStyle(style);
u1.setHobby(Numberings.of(hobby, hobby, hobby).create());
User u2 = new User();
u2.setName("张三");
u2.setAge(20);
u2.setGender('男');
TextRenderData hobby2 = new TextRenderData("唱,跳,rap");
hobby.setStyle(style);
u2.setHobby(Numberings.of(hobby2, hobby2, hobby2).create());
list.add(u1);
list.add(u2);
list.add(u1);
list.add(u2);
data.setUsers(list);
//4,数据渲染
template.render(data);
//5,设置响应参数
response.setContentType("application/vnd.ms-word"); //数据类型
response.setCharacterEncoding("utf-8"); //编码格式
//如果响应中带有附件,需要设置下面这行参数
response.setHeader("Content-disposition", "attachment; filename="
//ISO-8859-1适用范围比UTF-8更广泛,但自身无法显示中文,需要配合其他编码集使用,如UTF-8
+ new String(resource.getName().getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1)); //附件名称
//6,输出并关闭
template.writeAndClose(sos); //IO流
// template.writeToFile(""); //输出到文件
}
嵌套标签
标识符:{{+var}}
注意:这种标签必须要有两个文档模板,一个是用于数据展示的主模板;一个是数据填充的子模板;
文档模板
主模板
子模板
代码
public void test(HttpServletResponse response) {
Resource resource = null;
InputStream is = null;
ServletOutputStream sos = null;
XWPFTemplate template = null;
try {
sos = response.getOutputStream();
//1,获取模板文件
resource = ResourceUtil.getResourceObj("templates/father.docx");
is = resource.getStream();
//2,编译模板
template = XWPFTemplate.compile(is);
//3,准备参数(普通参数建议使用map装载)
Map<String,Object> map=new HashMap<>();
map.put("school","xx大学");
map.put("addr","xx省。。。");
ArrayList<User> list = new ArrayList<>();
User u1 = new User();
u1.setName("张三");
u1.setAge(20);
u1.setGender('男');
User u2 = new User();
u2.setName("张三");
u2.setAge(20);
u2.setGender('男');
list.add(u1);
list.add(u2);
list.add(u1);
list.add(u2);
InputStream stream = ResourceUtil.getResourceObj("templates/sub.docx").getStream();
map.put("users",Includes.ofStream(stream).setRenderModel(list).create());
//4,数据渲染
template.render(map);
//5,设置响应参数
response.setContentType("application/vnd.ms-word"); //数据类型
response.setCharacterEncoding("utf-8"); //编码格式
//如果响应中带有附件,需要设置下面这行参数
response.setHeader("Content-disposition", "attachment; filename="
//ISO-8859-1适用范围比UTF-8更广泛,但自身无法显示中文,需要配合其他编码集使用,如UTF-8
+ new String(resource.getName().getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1)); //附件名称
//6,输出并关闭
template.writeAndClose(sos); //IO流
// template.writeToFile(""); //输出到文件
}
至此,使用POI-ti导出数据到word的快速入门就结束了。。。