模板生成word文档 By POI+Word书签功能

刚开始接到生成文档的时候,我的内心是拒绝的,脑海里回想起了苦痛挪位置调像素的jasper,和不停add各种style的POI。但是这个模块都归我~~~老子说了算赶紧上网搜搜有没什么easy way。看到挺多人说起FreeMarker,大略一看So easy啊,只要做好一个word文档,然后~~ 准备马上学起来。


但是预先设定的方向是用POI,我提出FreeMarker之后,被指出用来后续需要的动态生成会变得复杂。

同时,他们给出了一个demo(也是网上找到的,不是我找的所以无法附上链接,抱歉啦),可以结合word的书签功能实现我想要的效果。

不过实验之后有一个需求[一个单元格内有多段数据]满足不了。于是新增了一个方法,在此分享一把。应该可以满足大部分生成文档的需求了~再也不用画报表了有没有很开心~


原Demo是这样的


这个需求第一反应是用public void  replaceBookMark(Map indicator)方法来做,但是结果把文档替换的一团乱...


我刚开始想到的思路有三种(尝试优先级如下)

1. 研究一下replaceBookMark里究竟发生了什么事

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

    欢迎有研究精神的小伙伴们告知:)


2.改replaceText 通过查找子字符串 替换之

3.遍历找出w:t 比较替换


其实最终的解决方法是2和3 的结合体

在replaceText(String bookMarkName, Map bookmarkMap)方法中改动替换文本的方法

//获到改行的所有单元格
                List cells = row.getTableCells();
                for(XWPFTableCell c : cells){
                    List paragraphs = c.getParagraphs();
                    for(XWPFParagraph paragraph : paragraphs){
                        for(Entry 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中增加一个方法 以获得直接对String操作

public void replaceParagraphText(final int paragraphPos, final Entry 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 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出来的并不是最后能看到的整个单元格的内容 但是代码还没看出瑕疵 觉得都很有道理啊

有不是互不包含的字符串组 但竟然全都各归其位平安的完成了替换

...


同志整理完思路继续努力去啦 白白






你可能感兴趣的:(遇到的问题和解决方法,Java,word,poi,word书签)