1. 程式人生 > >使用POI操作office2007及以上word模板替換變數,變數被分隔成多個XWPFRuns導致替換不了的處理方案

使用POI操作office2007及以上word模板替換變數,變數被分隔成多個XWPFRuns導致替換不了的處理方案

    我的方案可能不是最好的,卻是我經過嘗試覺得可用的方案,分享給大家。程式碼比較拙劣,希望大家指正。剛好在專案中有這個需求,因此我在網上也查了很多blog,大家的處理辦法不外乎下邊兩個,我也是嘗試過的,但都不盡如人意:

    word模板:

    

    1、不要在word中直接輸入引數,通過在文字中寫好複製貼上過來。

        經過實踐證明某些欄位確實可以,但是像我上面的模板中month_fd和month_ld這種還是被分隔到多個runs中,還有其它情況也會被分隔。

    2、將word另存為xml檔案,在編輯器中將變數寫進去,然後存為docx。

        這種方式最終結果是可以實現的。但是在xml中找非常費神且容易改錯,另外如果文件過大,基本上編輯器就被卡死了。

 

經過上面的實踐浪費了我很多時間,而且並解決不了問題,所以我就嘗試自己想辦法處理。方法其實也是非常簡單,既然變數被分隔了,那麼就可以通過程式碼合併,將分隔的內容合併回來,然後重新把變數設定進去。下邊省略了“[”和“]”可能在文件中是普通文字,替換為非常特殊的字元就可以了。

public XWPFDocument generateDoc(String path,Map param){
 //建立文件物件
 XWPFDocument doc = new XWPFDocument(new FileInputstream(new File("filePath")));
 //獲取所有段落
 List<XWPFParagraph> paragraphList = doc.getParagraphs();
 for(XWPFParagraph paragraph:paragraphList){
    //遍歷獲取段落中所有的runs
    List<XWPFRun> runs = paragraph.getRuns();
     //合併邏輯
    for(Integer i = 0; i < runs.size(); i++){
        String text0 = runs.get(i).getText(runs.get(i).getTextPosition());
       if(text0!=null && text0.startsWith("[")){
           //記錄分隔符中間跨越的runs數量,用於字串拼接和替換
          int num=0;
          int j = i+1;
          for(; j < runs.size(); j++){
              String text1 = runs.get(j).getText(runs.get(j).getTextPosition());
              if(text1!=null && text1.endsWith("]")){
                  num=j-i;
                  break;
              }
          }
          if(num!=0) {
              //num!=0說明找到了[]配對,需要替換
              StringBuilder newText = new StringBuilder();
              for (int s = i; s <= i+num; s++) {
                  String text2 = runs.get(s).getText(runs.get(s).getTextPosition());
                  newText.append(text2);
                  runs.get(s).setText(null, 0);
              }
              runs.get(i).setText(newText.toString(),0);

              //重新定義遍歷位置,跳過設定為null的位置
              i=j+1;
          }
       }
    }

    //變數替換邏輯
    for(int i = 0; i < runs.size(); i++){
        XWPFRun run = runs.get(i);
        String text = run.getText(runs.get(i).getTextPosition());
        if(text != null){
            boolean isSetText = false;
            for (Map.Entry<String, Object> entry : param.entrySet()) {
                String key = entry.getKey();
                if(text.indexOf(key) != -1){
                    isSetText = true;
                    Object value = entry.getValue();
                    if (value instanceof String) {//文字替換
                        text = text.replace(key, value.toString());
                    } else if (value instanceof Map) {//圖片替換
                        //從map中獲取圖片的寬、高、位置和描述資訊,編寫圖片定義xml 放入                     
                    }
                }
            }
            if(isSetText){
                run.setText(text,0);
            }
        }
     }
 }
 return doc;
}