使用deepoove根据模板导出word文档,包括文本、表格、图表、图片,使用WordConvertPdf可将word文档转换为pdf导出
模板样例:
导出结果:
一、引入相关依赖
<!-- 工具类--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.16</version></dependency><!-- poi--><dependency><groupId>com.deepoove</groupId><artifactId>poi-tl</artifactId><version>1.11.1</version></dependency><!-- word转pdf--><dependency><groupId>WordConvertPdf</groupId><artifactId>WordConvertPdf</artifactId><version>1.0</version></dependency>
二、创建导出数据实体类
@AllArgsConstructor
@NoArgsConstructor
@Data
@ApiModel(value = "ExportVO", description = "导出VO")
public class ExportVO {@ApiModelProperty(value = "标题")private String title;@ApiModelProperty(value = "名称")private String name;@ApiModelProperty(value = "数量")private Integer num;@ApiModelProperty(value = "集合数据")private List<ExportListVO> list;@ApiModelProperty(value = "表格")private List<ExportListVO> table;@ApiModelProperty(value = "柱状图")private ChartMultiSeriesRenderData barChart;@ApiModelProperty(value = "饼图")private ChartSingleSeriesRenderData pieChart;@ApiModelProperty(value = "折线图")private ChartMultiSeriesRenderData lineChart;@ApiModelProperty(value = "图片")private PictureRenderData img;}
@AllArgsConstructor
@NoArgsConstructor
@Data
@ApiModel(value = "ExportListVO", description = "导出集合VO")
public class ExportListVO {@ApiModelProperty(value = "类型")private String type;@ApiModelProperty(value = "数量")private Integer num;}
三、业务代码
/*** 文档导出** @param fileType 导出文件类型:1-docx,2-pdf* @param response 响应流*/@Overridepublic void exportFile(Integer fileType, HttpServletResponse response) throws IOException {//模板地址,存放在resources目录下String filePath = "templates/word/test.docx";//使用poi-tl进行模板处理ConfigureBuilder builder = Configure.builder();builder.useSpringEL(true);//执行循环策略LoopRowTableRenderPolicy strategy = new LoopRowTableRenderPolicy();//绑定集合对象builder.bind("list", strategy);builder.bind("table", strategy);//获取模板文件流InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(filePath);assert inputStream != null;//组装数据ExportVO data = this.createData();XWPFTemplate render = XWPFTemplate.compile(inputStream, builder.build()).render(data);// 设置强制下载不打开response.setContentType("application/force-download");response.addHeader("Access-Control-Expose-Headers", " Content-Disposition");if (fileType.equals(1)) {//如果需要导出为wordresponse.addHeader("Content-Disposition", "attachment; fileName=" + new String(("导出模板.docx").getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));render.write(response.getOutputStream());} else if (fileType.equals(2)) {//如果需要导出为pdfresponse.addHeader("Content-Disposition", "attachment; fileName=" + new String(("导出模板.pdf").getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));BufferedOutputStream outputStream = new BufferedOutputStream(response.getOutputStream());//设置临时文件的地址String tempPath = UUID.randomUUID() + ".docx";//根据模板生成临时文件render.writeToFile(tempPath);//将docx流转换为pdf流FileInputStream fileInputStream = new FileInputStream(tempPath);WordConvertPdf.getPdfStreamByWordStream(fileInputStream, outputStream);outputStream.flush();outputStream.close();fileInputStream.close();//删除临时文件File tempFile = new File(tempPath);Files.delete(tempFile.toPath());log.debug("删除临时word文件:{}", tempPath);}}
需要注意的时,文档中需要循环的数必须绑定biulder
四、组装数据,createData方法
private ExportVO createData() {ExportVO data = new ExportVO();//普通文本data.setTitle("食品统计");data.setName("蔬菜统计");data.setNum(60);//集合数据List<ExportListVO> list = new ArrayList<>();list.add(new ExportListVO("黄瓜", 10));list.add(new ExportListVO("茄子", 20));list.add(new ExportListVO("番茄", 30));//添加循环文本数据data.setList(list);//添加表格数据data.setTable(list);//添加柱状图数据ChartMultiSeriesRenderData barChart = new ChartMultiSeriesRenderData();barChart.setChartTitle("蔬菜统计柱状图");barChart.setCategories(list.stream().map(ExportListVO::getType).toArray(String[]::new));List<SeriesRenderData> barChartSeriesData = new ArrayList<>();barChartSeriesData.add(new SeriesRenderData("箱", list.stream().map(ExportListVO::getNum).toArray(Integer[]::new)));barChart.setSeriesDatas(barChartSeriesData);data.setBarChart(barChart);//添加饼图数据ChartSingleSeriesRenderData pieChart = new ChartSingleSeriesRenderData();pieChart.setChartTitle("蔬菜统计饼图");pieChart.setCategories(list.stream().map(ExportListVO::getType).toArray(String[]::new));pieChart.setSeriesData(new SeriesRenderData("箱", list.stream().map(ExportListVO::getNum).toArray(Integer[]::new)));data.setPieChart(pieChart);//添加折现图ChartMultiSeriesRenderData lineChart = new ChartMultiSeriesRenderData();lineChart.setChartTitle("蔬菜统计折线图");lineChart.setCategories(list.stream().map(ExportListVO::getType).toArray(String[]::new));List<SeriesRenderData> lineChartSeriesData = new ArrayList<>();lineChartSeriesData.add(new SeriesRenderData("箱", list.stream().map(ExportListVO::getNum).toArray(Integer[]::new)));lineChart.setSeriesDatas(lineChartSeriesData);data.setLineChart(lineChart);//添加图片PictureRenderData img = new PictureRenderData(800, 200, "D:\\files\\img\\test.jpg");data.setImg(img);return data;}