SpringBoot 动态导出word文档

导入jar包

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

<dependency>
  	<groupId>org.apache.poi</groupId>
	<artifactId>poi</artifactId>
   	<version>4.1.2</version>  	
</dependency>

<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>commons-io</groupId>
  	<artifactId>commons-io</artifactId>
 	<version>2.7</version>
</dependency>

准备模板

流程:制作模板->提供数据->渲染模板->下载word
注意:需要填充的数据需要使用{{}}来表示。
在这里插入图片描述
模板保存为docx格式,存放在resource目录下
在这里插入图片描述

提供数据

我这用的是我自己程序中的数据,map的key键必须与word模板中{{}}里的字段匹配

    private Map<String, Object> assertMap(String rq, QualityWorkableFeedback qualityWorkableFeedback) {
        Map<String, Object> params = new HashMap<>();
        QualityProjectPlan projectPlan = new QualityProjectPlan();
        Map<String, List<QualityProjectPlan>> map = projectPlanService.selectQualityProjectPlanList(projectPlan);
        if (StringUtils.isNotNull(map)) {
            List<QualityProjectPlan> qualityProjectPlans1 = map.get("one");
            params.put("yf1", "1月");
            params.put("zcxm1_1", qualityProjectPlans1.get(0).getAPXM());
            params.put("zcxm1_2", qualityProjectPlans1.get(1).getAPXM());
            params.put("zcxm1_3", qualityProjectPlans1.get(2).getAPXM());
            params.put("zcxm1_4", qualityProjectPlans1.get(3).getAPXM())
        }
        return params;
    }   

工具方法

以下是在接口中用到的工具类

    /**
     * 将项目中的模板文件拷贝到根目录下
     *
     * @return
     */
    private String copyTempFile(String templeFilePath) {
        InputStream inputStream = getClass().getClassLoader().getResourceAsStream(templeFilePath);
        String tempFileName = System.getProperty("user.home") + "/" + "科室质量目标管理落实反馈表模板.docx";
        File tempFile = new File(tempFileName);
        try {
            FileUtils.copyInputStreamToFile(inputStream, tempFile);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return tempFile.getPath();
    }

    private void down(HttpServletResponse response, String filePath, String realFileName) {
        String percentEncodedFileName = null;
        try {
            percentEncodedFileName = percentEncode(realFileName);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        StringBuilder contentDispositionValue = new StringBuilder();
        contentDispositionValue.append("attachment; filename=").append(percentEncodedFileName).append(";").append("filename*=").append("utf-8''").append(percentEncodedFileName);
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
        response.setHeader("Content-disposition", contentDispositionValue.toString());
        response.setHeader("download-filename", percentEncodedFileName);
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
             // 输出流
             BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());) {
            byte[] buff = new byte[1024];
            int len = 0;
            while ((len = bis.read(buff)) > 0) {
                bos.write(buff, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 百分号编码工具方法
     *
     * @param s 需要百分号编码的字符串
     * @return 百分号编码后的字符串
     */
    public static String percentEncode(String s) throws UnsupportedEncodingException {
        String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
        return encode.replaceAll("\\+", "%20");
    }

编写接口

    /**
     * 导出word
     * QualityWorkableFeedback 自定义的实体类
     */
    @RequestMapping("/export")
    public String export(HttpServletResponse response, QualityWorkableFeedback qualityWorkableFeedback) throws IOException {
        //1.组装数据
        Map<String, Object> params = assertMap(qualityWorkableFeedback.getFKSJ(), qualityWorkableFeedback);
        //2.获取根目录,创建模板文件
        String path = copyTempFile("word/科室质量目标管理落实反馈表模板.docx");
        String fileName = System.currentTimeMillis() + ".docx";
        String tmpPath = EmergencyConfig.getProfile()+ "/" + fileName;
        try {
            //3.将模板文件写入到根目录
            //4.编译模板,渲染数据
            XWPFTemplate template = XWPFTemplate.compile(path).render(params);
            //5.写入到指定目录位置
            FileOutputStream fos = new FileOutputStream(tmpPath);
            template.write(fos);
            fos.flush();
            fos.close();
            template.close();
            //6.提供前端下载
            down(response, tmpPath, fileName);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //7.删除临时文件
            File file = new File(tmpPath);
            file.delete();
            File copyFile = new File(path);
            copyFile.delete();
        }
        return tmpPath;
    }

对于图片的格式,POI-TI也有几种方法可用

//指定图片路径
put("image", "img.png");
//svg
put("svg", "http://xxxx.svg");
//设置图片宽高
put("image", Pictures.ofLocal("img.png").size(100, 100).create());
//图片流
put("streamImg", Pictures.ofStream(new FileInputStream("img.jpeg"), PictureType.JPEG).size(100, 100).create);
//网路图片
put("urlImg", Pictures.ofUrl("http://xxxx.png").size(100, 100).create);
//Java图片
put("image", Pictures.ofBufferedImage(bufferImage, PictureType.PNG).size(100, 100).create);

前端接口

我这前端直接用的框架中自带的下载功能

    getFkExpert() {
      let obj = {
        FKSJ: this.year
      }
      this.$confirm('是否确认导出数据项?', '警告', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(() => {
          this.download('/workable/feedback/export', {
            ...obj
          }, this.year.substring(0, 4) + `科室质量目标管理落实反馈表.docx`)
        })
        .catch(() => {
        })
    },

以下为补充内容,网上搜索的资料

导出表格内容不固定的word文档

表格动态内容填充,POI-TL提供了3种方式。

  • 表格行循环
  • 表格列循环
  • 动态表格。

LoopRowTableRenderPolicy 是一个特定场景的插件,根据集合数据循环表格行。

注意:
模板中有两个list,这两个list需要置于循环行的上一行。
循环行设置要循环的标签和内容,注意此时的标签应该使用[ ]
本次使用的是表格行循环
在这里插入图片描述
接口

	@RequestMapping("dynamicTable")
    public void dynamicTable(HttpServletResponse response) {
        //1.组装数据
        StudentTable table = assertMap();
        //2.获取根目录,创建模板文件
        String path = copyTempFile("word/2.docx");
        //3.获取临时文件
        String fileName = System.currentTimeMillis() + ".docx";
        String tmpPath = EmergencyConfig.getProfile()+ "/" + fileName;
        try {
            //4.编译模板,渲染数据
            LoopRowTableRenderPolicy hackLoopTableRenderPolicy = new LoopRowTableRenderPolicy();
            Configure config =
                    Configure.builder().bind("dataList", hackLoopTableRenderPolicy.build();
            XWPFTemplate template = XWPFTemplate.compile(path, config).render(table);
            //5.写入到指定目录位置
            FileOutputStream fos = new FileOutputStream(tmpPath);
            template.write(fos);
            fos.flush();
            fos.close();
            template.close();
            //6.提供下载
            down(response, tmpPath, fileName);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //7.删除临时文件
            File file = new File(tmpPath);
            file.delete();
            File copyFile = new File(path);
            copyFile.delete();
        }
    }
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值