图示
work文档 大概是这种样子的 然后用${}标注的 都是需要填充的 包括下面的表格数据
提前说明
我看网上有很多方法 当然都很不错 不过有种 word 正常pdf是商业的 当然也可以破解,但是如果公司使用的话 总归是不保险的 所以就没有选用
其实生成word 的方法 相对简单 网上也有很多的方法 以及还有对应的框架
但是我都没有选用 而且是用 最普通的方法吧 就当学习了 吧
hutool 主要准对的是 excel 对简单的 word 转成 pdf 其实没啥 可以不用 我引入这个是 解决生成excel的问题的
重要
window环境没有问题
linux 环境 要特别注意 没有中文字体 需要root账户的权限添加中文字体 记住是系统的字体 而不是JDK下的 front 文件 当然网上都有相关的教程
开始正文
pom文件
先下载对应的POM文件 这里面 我走了很多坑 比如 hutool 的版本问题 等
<!-- poi架包 说明 3.x 可以正常支持xdocreport 高版本会存在问题 --><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.17</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.17</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId><version>3.17</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>ooxml-schemas</artifactId><version>1.3</version></dependency><!--word转pdf方法--><dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagres.poi.xwpf.converter.pdf-gae</artifactId><version>2.0.1</version></dependency><!-- 4.x 配合 poi 3.17 以上 不然excel 会出问题--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>4.6.12</version></dependency><!-- poi架包 -->
业务代码
因为可能存在公司代码 所以做了处理 核心内容不变
importfr.opensagres.poi.xwpf.converter.pdf.PdfConverter; importfr.opensagres.poi.xwpf.converter.pdf.PdfOptions; importlombok.extern.slf4j.Slf4j; importorg.apache.poi.xwpf.usermodel.*; importorg.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc; importorg.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr; importorg.openxmlformats.schemas.wordprocessingml.x2006.main.STJc; importorg.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.stereotype.Component; importorg.springframework.util.StopWatch; publicStringgenerateWordToPdf(List<OrgExMngYlwlCollectDay>list,Stringtitle){ StopWatchstopWatch=newStopWatch(); StringylwlTitleNo=orgExMngYlwlCache.getYlwlTitleNo(); //参数Map<String, String>map=newHashMap<String, String>(); map.put("${day}", String.valueOf(LocalDate.now().getYear())); map.put("${hao}",ylwlTitleNo); map.put("${row}",LocalDate.now().format(DateTimeFormatter.ofPattern("MMdd"))); map.put("${datetime}",LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日"))); ByteArrayOutputStreamoutPDF=null; InputStreamstreamSafe=null; // 读取word模板try { //模板log.info("加载模板数据"); stopWatch.start("load word task"); //模板的位置 就是图示中展示的 work文档 ResourceUtil 这个是一个工具类 获取文件资源 你可以用hutool工具类的ResourceUtil streamSafe=ResourceUtil.getStream("template/ylwlTemplate.docx"); stopWatch.stop(); stopWatch.start("word task"); log.info("开始word模板填充"); XWPFDocumentdoc=newXWPFDocument(streamSafe); //处理段落List<XWPFParagraph>paragraphList=doc.getParagraphs(); processParagraph(paragraphList,map); //第一个表格 计算出那一个表格 进入表格的数据填充 主要字体XWPFTablexwpfTable=doc.getTables().get(0); XWPFTableRowsourceRow=xwpfTable.getRow(1); introwIndex=2; for (OrgExMngYlwlCollectDaybean : list) { //新增行 填充数据copyRow(xwpfTable,sourceRow,rowIndex); XWPFTableRowrow=xwpfTable.getRow(rowIndex); XWPFRunxwpfRun=row.getCell(0).addParagraph().createRun(); xwpfRun.setText(bean.getCheckData()); xwpfRun.setFontFamily("微软雅黑"); XWPFRunxwpfRun1=row.getCell(1).addParagraph().createRun(); xwpfRun1.setText(bean.getInterceptOrgCode()); xwpfRun1.setFontFamily("微软雅黑"); XWPFRunxwpfRun2=row.getCell(2).addParagraph().createRun(); xwpfRun2.setText(bean.getInterceptOrgName()); xwpfRun2.setFontFamily("微软雅黑"); XWPFRunxwpfRun3=row.getCell(3).addParagraph().createRun(); xwpfRun3.setText(String.valueOf(bean.getInterceptFailedSum())); xwpfRun3.setFontFamily("微软雅黑"); rowIndex++; } //对表格中的参数 进行匹配XWPFTableCellcell=xwpfTable.getRow(0).getCell(0); processParagraph(cell.getParagraphs(),map); //尾部的参数XWPFTablelastTable=doc.getTables().get(1); XWPFTableCelllastCell=lastTable.getRow(0).getCell(1); processParagraph(lastCell.getParagraphs(),map); log.info("word模板填充完毕..."); stopWatch.stop(); //填充结束//这里是个大坑 如果直接进行 word转pdf的操作 则会发现表格中新增行的数据缺少 因此只能先把上面生成wrod文件 下载后 再进行pdf转化 //因数据填充问题 先下载 再转pdf FileOutputStreamfileOutputStream=newFileOutputStream("ylwlGenereWord.docx"); doc.write(fileOutputStream); doc.close(); FileInputStreaminputStream=newFileInputStream("ylwlGenereWord.docx"); XWPFDocumentxwpfDocument=newXWPFDocument(inputStream); //生成PDFlog.info("准备生成pdf"); stopWatch.start("pdf task"); PdfOptionsoptions=PdfOptions.create(); outPDF=newByteArrayOutputStream(); PdfConverter.getInstance().convert(xwpfDocument, outPDF, options); stopWatch.stop(); fileOutputStream.close(); inputStream.close(); xwpfDocument.close(); log.info("生成pdf成功...."); stopWatch.start("upload file task"); // FileResult fileResult = xxxx.uploadFile(new ByteArrayInputStream(outPDF.toByteArray()), title);stopWatch.stop(); log.info("上传至文件服务器 文件名为{}, 响应信息为{}",title,fileResult); log.info(stopWatch.prettyPrint()); if (fileResult.success()) { returnfileResult.getFilePath(); } else { log.error("上传文件服务器失败 文件名为{}, 响应信息为{}",title,fileResult); thrownewFastDFSException(); } } catch (IOExceptione) { e.printStackTrace(); thrownewFileException(); }finally { IoUtil.close(streamSafe); IoUtil.close(outPDF); } } //这里就算把原来的 ${} 替换成 具体的内容publicstaticvoidprocessParagraph(List<XWPFParagraph>paragraphList,Map<String, String>param){ if(paragraphList!=null&¶graphList.size() >0){ for(XWPFParagraphparagraph:paragraphList){ List<XWPFRun>runs=paragraph.getRuns(); for (XWPFRunrun : runs) { Stringtext=run.getText(0); if(text!=null){ booleanisSetText=false; for (Map.Entry<String, String>entry : param.entrySet()) { Stringkey=entry.getKey(); if(text.contains(key)){ isSetText=true; Objectvalue=entry.getValue(); if (value!=null) {//文本替换text=text.replace(key, value.toString()); } else{ text=text.replace(key, ""); } } } if(isSetText){ run.setText(text,0); } } } } } }