1. 程式人生 > 實用技巧 >通過POI操作Word模版文件

通過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)));
    }
}