通过POI操作Word模版文档
1.添加Maven依赖
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency>
2.Word文档模版中以${xxx}为替换字符,例如:
3.处理代码
import org.apache.poi.xwpf.usermodel.*; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; public class CreateWordUtil { /** * 替换文档中的的变量 * @param doc * @param params */ public void replaceInDoc(XWPFDocument doc, Map<String, Object> params) { Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator(); XWPFParagraph para; while (iterator.hasNext()) { para = iterator.next(); this.replaceInPara(para, params,"0"); } } /** * 替换表格里面的变量 * @param doc * @param params */ public void replaceInTable(XWPFDocument doc, Map<String, Object> params) { Iterator<XWPFTable> iterator = doc.getTablesIterator(); XWPFTable table; List<XWPFTableRow> rows; List<XWPFTableCell> cells; List<XWPFParagraph> paras; while (iterator.hasNext()) { table = iterator.next(); rows = table.getRows(); for (XWPFTableRow row : rows) { cells = row.getTableCells(); for (XWPFTableCell cell : cells) { paras = cell.getParagraphs(); for (XWPFParagraph para : paras) { this.replaceInPara(para, params, "0"); } } } } } /** * 替换页眉 * @param doc * @param params */ public void replaceInHeader(XWPFDocument doc, Map<String, Object> params) { List<XWPFHeader> xwpfHeaderList = doc.getHeaderList(); Iterator iterator = xwpfHeaderList.iterator(); XWPFParagraph para; XWPFHeader xwpfHeader; while (iterator.hasNext()) { xwpfHeader = (XWPFHeader) iterator.next(); List<XWPFParagraph> xwpfParagraphList = xwpfHeader.getParagraphs(); Iterator iteratorPara = xwpfParagraphList.iterator(); while (iteratorPara.hasNext()){ para = (XWPFParagraph) iteratorPara.next(); this.replaceInPara(para, params, "1"); } } } /** * 替换段落里面的变量 * @param para * @param params * @param type */ private void replaceInPara(XWPFParagraph para, Map<String, Object> params, String type) { List<XWPFRun> runs; if (this.matcher(para.getParagraphText()).find()) { runs = para.getRuns(); int start = -1; int end = -1; String str = ""; for (int i = 0; i < runs.size(); i++) { XWPFRun run = runs.get(i); String runText = run.toString(); System.out.println("runText==>"+runText); if(runText.length()>1){ if ('$' == runText.charAt(0) && '{' == runText.charAt(1) ) { start = i; } }else{ if ('$' == runText.charAt(0)){//解决页眉问题 start = i; } } if ((start != -1)) { str += runText; } if ('}' == runText.charAt(runText.length() - 1)) { if (start != -1) { end = i; break; } } } for (int i = start; i <= end; i++) { para.removeRun(i); i--; end--; } for (String key : params.keySet()) { if (str.equals(key)) { String text = ""+params.get(key); XWPFRun run = para.createRun(); if(type.equals("1")){//表示页眉 run.setFontSize(10); }else{ run.setFontSize(14); } run.setFontFamily("宋体"); if(text.indexOf("\r\n") >0 ){ String [] texts = text.split("\r\n"); for(int k=0; k<texts.length; k++){ if(k > 0 ){ //run.addCarriageReturn();//硬回车 // 换行 run.addBreak(); } run.setText(text); } }else{ run.setText(text); } break; } } } } private Matcher matcher(String str) { Pattern pattern = Pattern.compile("\\$\\{(.+?)\\}", Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(str); return matcher; } }
4.测试
import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.springframework.beans.factory.annotation.Autowired; 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 org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Map; @Controller @RestController @RequestMapping(value = "/word/") public class WordServer { @Autowired HttpServletRequest request; @GetMapping("/test") public ResponseEntity<?> test(){ Map<String, Object> params = new HashMap<String, Object>(); params.put("${ywbh}", "YW202011290005"); params.put("${xmmc}", "项目名称"); params.put("${sxkh}", "授信客户"); params.put("${jwgys}", "境外供应商"); params.put("${myzt}", "贸易主体"); params.put("${wlfw}", "物流服务"); params.put("${sjht}", "涉及合同"); params.put("${ywbj}", "\t对象识别的应用范围比较广,例如人脸识别,车牌识别,自动驾驶等等都用到了对象识别的技术。对象识别是当今机器学习领域的一个前沿,2017 年研发出来的 Mask-RCNN 模型还可以检测对象的轮廓。"); params.put("${ywms}", "\t如果图片包含了多个物体,我们想识别有哪些物体,各个物体在什么位置,那么只用 CNN 模型是无法实现的。\r\n我们需要可以找出图片哪些区域包含物体并且判断每个区域包含什么物体的模型,这样的模型称为对象识别模型 (Object Detection Model),最早期的对象识别模型是 RCNN 模型,后来又发展出 Fast-RCNN (SPPnet),Faster-RCNN ,和 YOLO 等模型。因为对象识别需要处理的数据量多,速度会比较慢 (例如 RCNN 检测单张图片包含的物体可能需要几十秒),而对象识别通常又要求实时性 (例如来源是摄像头提供的视频),所以如何提升对象识别的速度是一个主要的命题,后面发展出的 Faster-RCNN 与 YOLO 都可以在一秒钟检测几十张图片。"); CreateWordUtil createWordUtil = new CreateWordUtil(); XWPFDocument doc = null; String fileNameInResource = "审批单-模版.docx"; InputStream is = getClass().getClassLoader().getResourceAsStream(fileNameInResource); HttpHeaders headers = new HttpHeaders(); headers.add("Cache-Control", "no-cache, no-store, must-revalidate"); headers.add("Pragma", "no-cache"); headers.add("Expires", "0"); String fileName = System.currentTimeMillis()+".docx"; //String fileName = System.currentTimeMillis()+".pdf"; ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte [] result = null; try { doc = new XWPFDocument(is); //替换页眉 createWordUtil.replaceInHeader(doc, params); //替换文档中的段落 //createWordUtil.replaceInDoc(doc, params); //替换文档中的表格 createWordUtil.replaceInTable(doc, params); doc.write(baos); result = baos.toByteArray(); } catch (IOException e) { e.printStackTrace(); } finally { try { baos.close(); } catch (IOException e) { e.printStackTrace(); }finally { if(null != doc){ try { doc.close(); } catch (IOException e) { e.printStackTrace(); } } } } headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"", fileName)); //将生成的Word文档转换为PDF // InputStream fileInput = new ByteArrayInputStream(result); // byte [] outputBytes = null; // // try { // outputBytes = WordToPdfUtil.convert(fileInput); // } catch (Exception e) { // e.printStackTrace(); // } return ResponseEntity .ok() .headers(headers) .contentType(MediaType.parseMediaType("application/octet-stream")) .body(new InputStreamResource(new ByteArrayInputStream(result))); } }