使用Poi-tl word模板的爬坑日记

举报
多米诺的古牌 发表于 2022/01/17 09:21:39 2022/01/17
【摘要】 1.简介POI-TL官网poi-tl即poi template language的简称,是一款Word模板的处理引擎,由于现在根据模板导出对应word的需求,要求越来越高,比如各种表格格式,比如列表、图片、表格、自定义表格内容等等,poi-tl大多数功能都有实现,有些需要个性化的配置一下比如复选框(都是泪。。。)。2.使用2.1 引入全部相关的依赖2.1.1 多地方导入不同版本的依赖,造成的...

1.简介

POI-TL官网

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-tl导出word文件的几个技巧

参考八:使用POI导出Word(含表格)的实现方式及操作Word的工具类

参考九:表格合并的参考

参考十:poi-tl的使用

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。