使用POI操作office2007及以上word模板替換變數,變數被分隔成多個XWPFRuns導致替換不了的處理方案
阿新 • • 發佈:2019-08-01
我的方案可能不是最好的,卻是我經過嘗試覺得可用的方案,分享給大家。程式碼比較拙劣,希望大家指正。剛好在專案中有這個需求,因此我在網上也查了很多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; }