使用Poi-tl word模板的爬坑日记
1.简介
poi-tl即poi template language的简称,是一款Word模板的处理引擎,由于现在根据模板导出对应word的需求,要求越来越高,比如各种表格格式,比如列表、图片、表格、自定义表格内容等等,poi-tl大多数功能都有实现,有些需要个性化的配置一下比如复选框(都是泪。。。)。
2.使用
2.1 引入全部相关的依赖
2.1.1 多地方导入不同版本的依赖,造成的循环依赖问题
报错信息:java.lang.NoSuchFieldError: DOUGHNUT
这里就出现了一个坑,因为项目本身集成了poi一个4.1.2的poi-ooxml依赖用于导出操作,但是里面没有包含使用word模板的poi-tl依赖,当时没有发现我引入的是4.1.3的依赖,在启动poi-tl模板解析的时候出现了循环依赖错误,最后将依赖的版本都改为统一的4.1.2后问题得到解决
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.7.3</version>
</dependency>
2.2 编写工具类
这里这种写法无法处理,特别定制的表格,如果需要处理特别定制的表格需要传config过来进行个性化定制,编译的时候加上传过来的个性化的config即可
整体流程是:找到模板位置==》然后compile进行模板解析==》render进行数据加载和编译==》初始化输出流==》将加载了数据编译后的模板进行输出==》但是此时没有文件让我们输出==》根据传入的名称创建文档==》完成写入操作==》关闭各种流==》完毕
XWPFTemplate template = XWPFTemplate.compile((path+"\\"+fileName),config).render(dataMap);
public static void download(HttpServletRequest request, HttpServletResponse response, String newWordName, Map dataMap, String fileName) {
String path = ClassUtils.getDefaultClassLoader().getResource("").getPath();
if(StringUtils.isBlank(fileName)){return;}
XWPFTemplate template = XWPFTemplate.compile(path+"\\"+fileName).render(dataMap);
OutputStream out = null;
try {
out = new FileOutputStream("template.docx");
template.write(out);
out.flush();
out.close();
template.close();
} catch (IOException e) {
e.printStackTrace();
}
InputStream fis = null;
OutputStream toClient = null;
File file = new File("template.docx");
try {
fis = new BufferedInputStream(new FileInputStream(file));
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();
// 清空response
response.reset();
// 设置response的Header
newWordName = URLEncoder.encode(newWordName, "utf-8"); //这里要用URLEncoder转下才能正确显示中文名称
response.addHeader("Content-Disposition", "attachment;filename=" + newWordName+"");
response.addHeader("Content-Length", "" + file.length());
toClient = new BufferedOutputStream(response.getOutputStream());
response.setContentType("application/octet-stream");
toClient.write(buffer);
toClient.flush();
} catch (Exception e) {
e.printStackTrace();
} finally{
try {
if(fis!=null){
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(toClient!=null){
toClient.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//Object转Map
public static Map<String, Object> getObjectToMap(Object obj) throws IllegalAccessException {
Map<String, Object> map = new LinkedHashMap<String, Object>();
Class<?> clazz = obj.getClass();
System.out.println(clazz);
for (Field field : clazz.getDeclaredFields()) {
field.setAccessible(true);
String fieldName = field.getName();
Object value = field.get(obj);
if (value == null) {
value = "";
}
map.put(fieldName, value);
}
return map;
}
2.3网络图片的处理方法
if(dataMap.containsKey("file")){
dataMap.put("file", new PictureRenderData(450, 450, ".png", BytePictureUtils.getUrlByteArray(en.getFile())));
}
2.4 表格输出
2.4.1 方法一
这种方法需要手动调格式,如果没有设置格式,会输出一个默认的表格。
使用RowRenderData的build的创建好表格的框架,比如下图的 创建的 序号列、第一列、第二列、第三列
然后将设置好的表格传入最后处理的map中,并且使用MiniTableRenderData进行表格的初始化,就相当于告诉编译方法这个是个表格,按我这个表格的设置来输出。
int i = 1;
RowRenderData content = RowRenderData.build(String.valueOf(i),第二列字段值,第三列字段值);
list.add(content);
dataMap.put("content",new MiniTableRenderData(list));
2.4.2 方法二
将需要处理的数据list集合,正常的放入需要处理的map中,然后使用Configure进行newBuilder个性化创建,然后将设置好的个性化config传入都工具类中,在模板编译的时候传入进行加入个性化设置的编译,这种方法可以根据原模板的样式进行填充。
dataMap.put("content",content);
HackLoopTableRenderPolicy policy = new HackLoopTableRenderPolicy();
Configure config = Configure.newBuilder().bind("content", policy).build();
2.5 复选框
这种也是无奈的解决办法,还有可以根据值和模板字段进行比对判断的方法,目前还没有研究透彻,由于比较项目着急,所以暂时使用这种粗暴的方法。
if(dataMap.containsKey("复选框")){
if (dataMap.get("复选框").equals("1")){
dataMap.put("复选框", "■值1 □值2");
}else if(dataMap.get("复选框").equals("2")){
dataMap.put("复选框", "□值1 ■值2");
}
}
参考一:Java 使用 Poi-tl word模板导出word
参考二:JAVA使用POI-TL通过Word模板生成Word文件
参考三:POI-Tl表格处理可以看这个
参考四:复选框的实现
参考五:springboot整合poi-tl根据模板导出word
参考六:poi插入word 2007 Wingdings字符,可以插入各种特殊字符
参考八:使用POI导出Word(含表格)的实现方式及操作Word的工具类
参考九:表格合并的参考
参考十:poi-tl的使用
- 点赞
- 收藏
- 关注作者
评论(0)