您的位置:首页 > 编程语言 > Java开发

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

2016-10-13 18:42 465 查看
刚开始接到生成文档的时候,我的内心是拒绝的,脑海里回想起了苦痛挪位置调像素的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出来的并不是最后能看到的整个单元格的内容 但是代码还没看出瑕疵 觉得都很有道理啊


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

...

同志整理完思路继续努力去啦 白白
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java word poi word书签