POI不同版本替換Word模板時的問題


一、問題描述

  通過POI,把Word中的占位符替換為實際的值,以生成復雜結構的業務報告。

  在POI 3.9上,功能正常。由於某些原因升級到POI 3.10.1后,項目組反饋說Word模板出錯,無法生成Word文件,總是報解析錯誤。

 

二、問題分析

  Word模板功能相關的代碼應該說是比較穩定了,相關代碼很久沒有變動過,而且已經有投產項目在正式使用。現在出了問題,應該是升級POI版本導致的。

  Word模板內容示例:

  本期產品為向${ds:ds001,col:INVESTER_TYPE_NAME}發行的混合類理財產品,本期產品投資期限為${ds:ds001,col:TERM}天,收益率為${ds:ds001,col:YTM_100}%/年,為${ds:ds001,col:INCOME_TYPE_NAME}類產品,到期還本付息。是一款具有投資安全性高、回報率高重點的理財產品。

  分析、調試代碼。發現兩個版本的POI在處理Paragraph.getRuns()有區別:

  3.9版本:一個段落就是一個XWPFRun;

  3.10.1版本:一個段落不知道根據什么規則,胡亂分成了List<XWPFRun>。如上述示例模板,會被切換為長度為14的List;

  這樣就導致獲取、替換段落文本時出錯。

 

三、問題解決

  問題被定位后,就嘗試解決。主要的思路,就是強制把List中的內容合並成一個字符串,替換內容后,把段落中的XWPFRun全部remove掉,然后新建一個含有替換后內容的XPWFRun,並賦給當前段落。

  解決問題的過程中,“對於removeRun方法無法達到本應達成的預期效果的問題”,耗費了不少時間。總結來說:不能從0到size()移除Run,這樣的話Run不會被移除;而應該從size()到0進行移除。

  需要繼續關注表格替換時是否會有問題。

  解決這類第三方軟件引起的問題,幾乎沒有道理可言,如果不想被埋在相關源代碼中,只能靠經驗+運氣。

 

四、附代碼

在3.10.1下有問題的代碼示意:

while (itPara.hasNext()) {

    XWPFParagraph paragraph = (XWPFParagraph) itPara.next();

   int length = paragraph.getRuns().size();

  if (length > 0) {

        String text = paragraph.getText();

        if (text.indexOf(tag) < 0) {

      continue;

        }

        while (length-- > 0) {

      paragraph.removeRun(0);

        }

        XWPFRun newrun = paragraph.insertNewRun(0);

        newrun.setText(text.replace(tag, val));

    }

}

 

修改后的代碼示意:

while (itPara.hasNext()) {

     XWPFParagraph paragraph = (XWPFParagraph) itPara.next();

     int length = paragraph.getRuns().size();

    if (length > 0) {

        String text = StringUtils.join(paragraph.getRuns().toArray());

         if (text.indexOf(tag) < 0) {

    continue;

        }

        for (int i = (length - 1); i >= 0; i--) {

    paragraph.removeRun(i);

        }

        XWPFRun newRun = paragraph.insertNewRun(0);

        text = text.replaceAll(tag, val);

        newRun.setText(text, 0);

    }

}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM