1. 程式人生 > >模板生成word文件 By POI+Word書籤功能

模板生成word文件 By POI+Word書籤功能

剛開始接到生成文件的時候,我的內心是拒絕的,腦海裡回想起了苦痛挪位置調畫素的jasper,和不停add各種style的POI。但是這個模組都歸我~~~老子說了算得意趕緊上網搜搜有沒什麼easy way。看到挺多人說起FreeMarker,大略一看So easy啊,只要做好一個word文件,然後~~羨慕 準備馬上學起來。

但是預先設定的方向是用POI,我提出FreeMarker之後,被指出用來後續需要的動態生成會變得複雜。難過

同時,他們給出了一個demo(也是網上找到的,不是我找的所以無法附上鍊接,抱歉啦),可以結合word的書籤功能實現我想要的效果。

不過實驗之後有一個需求[一個單元格內有多段資料]滿足不了。於是新增了一個方法,在此分享一把。應該可以滿足大部分生成文件的需求了~再也不用畫報表了有沒有很開心~

原Demo是這樣的

這個需求第一反應是用public void  replaceBookMark(Map<String,String> indicator)方法來做,但是結果把文件替換的一團亂...

我剛開始想到的思路有三種(嘗試優先順序如下)

1. 研究一下replaceBookMark裡究竟發生了什麼事

    根本搞不懂其中的insertTextAtBookMark怎麼回事,也沒什麼思路,很快就放棄啦╮(╯▽╰)╭

    歡迎有研究精神的小夥伴們告知:)

2.改replaceText 通過查詢子字串 替換之

3.遍歷找出w:t 比較替換

其實最終的解決方法是2和3 的結合體

在replaceText(String bookMarkName, Map<String,String> bookmarkMap)方法中改動替換文字的方法

//獲到改行的所有單元格
                List<XWPFTableCell> cells = row.getTableCells();
                for(XWPFTableCell c : cells){
                    List<XWPFParagraph> paragraphs = c.getParagraphs();
                    for(XWPFParagraph paragraph : paragraphs){
                        for(Entry<String,String> e : bookmarkMap.entrySet()){
//                            if(c.getText().equals(e.getKey())){
//                                
//                                //刪掉單元格內容
//                                c.removeParagraph(0);
//                                
//                                //給單元格賦值
//                                c.setText(e.getValue());
//                            }
//                            else 
                            if(paragraph.getText().contains(e.getKey())){
                                c.replaceParagraphText(paragraphs.indexOf(paragraph), e);
                            }
                        }
                    }
                    
                }

另外在XWPFTableCell中增加一個方法 以獲得<w:t>直接對String操作
public void replaceParagraphText(final int paragraphPos, final Entry<String,String> text) throws IndexOutOfBoundsException {
    	if(this.ctTc.sizeOfPArray() < paragraphPos){
    		throw new IndexOutOfBoundsException();
    	}
        final CTP ctP = this.ctTc.getPArray(paragraphPos);
        final XWPFParagraph par = new XWPFParagraph(ctP, this);
        List<XWPFRun> runs = par.getRuns();
        for(XWPFRun run : runs){
        	for(int i = 0; i < run.getCTR().sizeOfTArray(); i++){
        		if(run.getText(i).equals(text.getKey())){
        			String replaceBy = run.getText(i).replaceAll(text.getKey(), text.getValue());
        			run.setText(replaceBy, i);
        		}
        	}
        }
    }

不過還有一些覺得不可思議的奇怪現象沒搞懂

比如XWPFTableCell的getText... get出來的並不是最後能看到的整個單元格的內容 但是程式碼還沒看出瑕疵 覺得都很有道理啊閉嘴

有不是互不包含的字串組 但竟然全都各歸其位平安的完成了替換

...

同志整理完思路繼續努力去啦 白白