【Java】poi-tl 使用Word模板渲染动态表格

前言

poi-tl 是一个基于 Apache POI 和 FreeMarker 的 Java 模板引擎,可以用于动态生成 Word、Excel、PowerPoint 等文档。使用 poi-tl 可以方便地将数据填充到模板中,生成符合要求的文档。
poi-tl官方文档地址:http://deepoove.com/poi-tl/#_%E7%89%88%E6%9C%AC

先附上导出效果图:
在这里插入图片描述

1.创建word模板,并将模板放在resource文件夹下

这步建议手动创建,之前客服提供了一个pdf文件,我把它转成了word,用这个word当模板.结果意外发生了,动态表格数据不会自动分页,所有数据都挤在第一页…改模板,加分页符…都不好用,最后手动新建一个模板就好了…

数据结构:
代码中可以用对象封装,也可以用map.

区块对是 {{?innerList}} {{/innerList}},我想要的样式就是循环这部分内容
{{contestExcelList}} 是动态列表集合

外层out(对象) :date (字符串) innerList(集合)
inner 对象:
title1(字符串)
title2(字符串)
@image(图片)
contestExcelList(集合)-
contestExcel(对象):num(字符串)
projectName(字符串)
score(字符串)

在这里插入图片描述

2.引入依赖

       <dependency>
            <groupId>com.deepoove</groupId>
            <artifactId>poi-tl</artifactId>
            <version>1.10.0</version>
        </dependency>

  <!--word 转pdf 注意依赖是否需要排除,以免冲突-->
<dependency>
            <groupId>org.docx4j</groupId>
            <artifactId>docx4j-JAXB-MOXy</artifactId>
            <version>8.2.9</version>
        </dependency>
 <dependency>
            <groupId>org.docx4j</groupId>
            <artifactId>docx4j-export-fo</artifactId>
            <version>8.2.9</version>
        </dependency>

3.代码实现

public void downLoad(HttpServletRequest request, HttpServletResponse response) throws Exception {
List<Map<String, Object>> innerMapList= new ArrayList<>();   //inner集合
 Map<String, Object> innerMap = new HashMap<>();             //inner对象
 
  List<ContestExcel> contestExcelList= new ArrayList<>();    //自己的动态表格数据
  for (int j = 0; j < 10; j++) {
        ContestExcel contestExcelEntity = new ContestExcel();
             contestExcelEntity.setNum(j+1);
             contestExcelEntity.setProjectName("项目名称");
             contestExcelEntity.setScore("99");
             contestExcelList.add(contestExcelEntity);
  }
  
  innerMap .put("title1", Texts.of("标题1").create());
  innerMap .put("title2", Texts.of("标题2").create());
  innerMap .put("image", Pictures.ofUrl("图片url链接");
  innerMap .put("contestExcelList", contestExcelList);   
  innerMapList.add(innerMap);
  
 Map<String, Object> outMap= new HashMap<>();  //外层out(对象)
 Date date = new Date();
 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
   outMap.put("innerList", innerMapList);
   outMap.put("date", sdf.format(date));

 String name = "打分表";
 String destFilePath = TestFileUtil.getPath();

//动态表格变量可以用[] 对应
 LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
        //这里可以指定一个config类,用来指定一些规则,也可以改变模板中{{}}的这种格式
        Configure config = Configure.builder()
                .bind("contestExcelEntityList", policy).build();


//获取模板
InputStream inputStream = ClassUtils
                .getDefaultClassLoader()
                .getResourceAsStream("wordTemplate.docx");  //将模板放在resource文件夹下
//生成docx文件
XWPFTemplate compile = XWPFTemplate.compile(inputStream, config);
        compile.render(map);
        compile.writeToFile(destFilePath + name + ".docx");
        inputStream.close();

//转成pdf文件并导出
        outputMethod(response, toPdf2(destFilePath, name));

转pdf 和导出方法:


//转pdf方法

    public static String toPdf2(String destFilePath, String zipName) throws Exception {
        String destFilePath2 = "";
        char firstChar = destFilePath.charAt(0);
        if (firstChar == '/') {
            destFilePath2 = destFilePath.substring(1);
        } else {
            destFilePath2 = destFilePath;
        }
//此处代码 参考  https://editor.csdn.net/md/?articleId=133790383
        WordToPdfTest_Docx4j.wordToPdf(destFilePath2 + zipName + ".docx", destFilePath2 + zipName + ".pdf");
        return destFilePath2 + zipName + ".pdf";
    }

}

//导出方法
  public void outputMethod(HttpServletResponse response, String filePath) {

        ServletOutputStream out = null;
//        File file = new File("d:\\test\\result.pdf");
        File file = new File(filePath);
        FileInputStream inputStream = null;
        try {
            out = response.getOutputStream();
            inputStream = new FileInputStream(file);
            if (filePath.contains(".xlsx")) {
                //
                /** 导出excel文件流 */
                response.setHeader("content-Type", "application/vnd.ms-excel");
                response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "inline;filename=" + URLEncoder.encode(file.getName(), "UTF-8"));
                response.setCharacterEncoding("UTF-8");
            } else {

                /** 导出pdf文件流 */
                response.setCharacterEncoding("UTF-8");
                response.setContentType("application/pdf");
                response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=" + URLEncoder.encode(file.getName(), "UTF-8"));
            }


            // 读取文件流
            int len = 0;
            byte[] buffer = new byte[1024 * 10];
            while ((len = inputStream.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                logger.error("输入流关闭失败, {}", e);
            }
            try {
                out.close();
            } catch (IOException e) {
                logger.error("输出流关闭失败, {}", e);
            }
        }
        file.delete();//删除.xlsx  或    pdf文件
        if (filePath.contains(".pdf")) {  //如果是pdf ,还需要删除生成的docx
            File fileDocx = new File(filePath.substring(0, filePath.lastIndexOf(".")) + ".docx");
            fileDocx.delete();
        }

    }

4.前端blob导出参考:

https://editor.csdn.net/md/?articleId=133790129

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
确保您已经在项目的pom.xml文件中添加了poi-tl库的依赖: ```xml <dependency> <groupId>com.deepoove</groupId> <artifactId>poi-tl</artifactId> <version>1.12.0</version> </dependency> ``` 然后,您可以按照以下步骤使用poi-tl库来合并表格并下载Word文档: 1. 创建一个Word模板文件,其中包含您要合并的表格。您可以使用Microsoft Word或其他编辑器创建模板文件,并确保在模板文件中使用`${}`标记来标记需要替换的文本。 2. 创建一个Java类来处理导出请求。例如,创建一个名为WordExportController的类。 ```java import com.deepoove.poi.XWPFTemplate; import com.deepoove.poi.config.Configure; import com.deepoove.poi.data.TableRenderData; import com.deepoove.poi.data.TextRenderData; import org.springframework.core.io.InputStreamResource; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; @Controller public class WordExportController { @GetMapping("/export") public ResponseEntity<InputStreamResource> exportWord() throws IOException { // 加载Word模板文件 XWPFTemplate template = XWPFTemplate.compile("templates/template.docx") .render(getTemplateData()); // 将生成的Word文档转换为字节数组 ByteArrayOutputStream out = new ByteArrayOutputStream(); template.write(out); byte[] documentBytes = out.toByteArray(); // 设置下载响应的头信息 HttpHeaders headers = new HttpHeaders(); headers.setContentDispositionFormData("attachment", "merged_table.docx"); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); // 创建一个包含Word文档字节数组的InputStreamResource InputStreamResource resource = new InputStreamResource(new ByteArrayInputStream(documentBytes)); // 返回响应实体 return ResponseEntity.ok() .headers(headers) .body(resource); } private Map<String, Object> getTemplateData() { Map<String, Object> data = new HashMap<>(); // 创建表格数据 TableRenderData tableData = new TableRenderData(); tableData.setHeader(new TextRenderData("FFFFFF", "Header 1")); tableData.setRow(new TextRenderData("FFFFFF", "Cell 1"), new TextRenderData("FFFFFF", "Cell 2")); // 将表格数据存储到模板数据中 data.put("tableData", tableData); return data; } } ``` 3. 在resources目录下创建一个名为`template.docx`的Word模板文件,并按照您的需求设置表格样式和内容。在模板文件中,您可以使用`${tableData}`来标记需要替换的表格数据。 4. 启动您的Spring Boot应用程序,并访问导出请求的URL(例如:http://localhost:8080/export)。将会自动下载名为`merged_table.docx`的Word文档,其中包含合并表格的内容。 请确保按照您的需求修改代码,并根据模板文件的位置进行相应的调整。 希望对您有所帮助!如果您有任何其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值