java Apache poi 操作word生成word目录(根据word模板生成word文件)_poi word生成目录_404技术社区

在项目需求中,需要对于一个word模板文档生成相对应的word文件,而此word模板是多页的并且需要在最终文件中生成相应的目录,由于项目环境是Linux,所以舍弃了jacob(windows环境)。然后主要是研究了Apache poi 进行word操作以及如何生成目录。
主要分两个部分介绍:

  • Apache poi 操作word:主要是通过XWPFDocument对象进行操作,api 地址:

    
    //读取word文件
    InputStream is = new FileInputStream(path);  
    XWPFDocument doc = new XWPFDocument(is);  
    List<IBodyElement> elements=  doc.getBodyElements();//获取所有元素(段落和表格)
    int pIndex =0;
    int tIndex =0;
    for(int i=0 ; i< elements.size(); i++) {
    IBodyElement e = elements.get(i);
    //判断元素类型:段落/ 表格
    if(BodyElementType.PARAGRAPH.equals(e.getElementType())) {
        XWPFParagraph pa = e.getBody().getParagraphArray(pIndex); //获取段落
        List<XWPFRun> runs = paragraph.getRuns(); //获取段落文本
                for (XWPFRun run : runs) {
                      ...替换文本
                }
    }
    else if(BodyElementType.TABLE.equals(e.getElementType())){//表格
               XWPFTable ta = e.getBody().getTableArray(tIndex);
               List<XWPFTableRow> rows = ta.getRows(); //获取所有行
               for (XWPFTableRow row : rows) { 遍历每行
            List<XWPFTableCell> cells = row.getTableCells(); //获取每行单元格
            for (XWPFTableCell cell : cells) { //遍历单元格
                List<XWPFParagraph> paragraphs = cell.getParagraphs(); //获取单元格段落
                for (XWPFParagraph paragraph : paragraphs) {
                    List<XWPFRun> runs = paragraph.getRuns();//获取单元格文本
                    for (XWPFRun run : runs) {
                        ...替换文本
                    }
                }
            }
        }
        }
    }

    Bash

    Copy

操作word方面还是很方便,可以参考一些更详细的:<br> [https://blog.csdn.net/eye9093/article/details/77368703](https://blog.csdn.net/eye9093/article/details/77368703)<br> [https://blog.csdn.net/u012775558/article/details/79678701](https://blog.csdn.net/u012775558/article/details/79678701)  
主要是介绍一下目录如何生成<br> 2. .Apache poi 生成word目录: 需要了解ooxml(Office Open XML)的大体结构,参考:[http://www.datypic.com/sc/ooxml/s-wml.xsd.html](http://www.datypic.com/sc/ooxml/s-wml.xsd.html),主要是通过xml标签进行识别分页。  
之前在网上也查阅了很多,发现目录的页数问题始终没有一个好的解决方案,之前看的可以通过转成pdf计算页数,但是这个耗时太长,特别是对于我们项目word页数较多的时候转换再重写消耗的时间很长。所以选择再去研究一下word对应的xml文件是否有思路去解决这一问题。<br> 我们选择的是xxx.docx 文件,通过word另存为xml<br> ![描述](https://static.404bugs.com/jishushequ/2023-02-24/03f7eb4a283485b3fead8cf1f39c14e6.png)  

获取到此word文件的xml文件,xml文件结构如下:<br> ![描述](https://static.404bugs.com/jishushequ/2023-02-24/767fc3821e375674c19b174ff364945a.png)  
<br> 其实大体看一下可以大致理清xml的结构,而我们主要是关注这一个标签<br> ![描述](https://static.404bugs.com/jishushequ/2023-02-24/13de785255795a65f563f755a80dd54e.png)  
<br> 这个标签就是分页之后产生的标签(经测试插入空白页不会产生这个标签,如果是遇到表格处于分页那么分页后的表格的第一个单元格必须有文本,不然也不会产生这个标签,而且文档必须有页码),而通过获取这个标签就可以计算出页数,可以看出这个标签位置是<w:p>下的<w:r>下,可以通过poi判断这个标签是否存在:<br> ![描述](https://static.404bugs.com/jishushequ/2023-02-24/5fcb22655499d1b2840c6eab099f8bd3.png)  

主要代码如下:  

.//承接上面的获取的段落
int num =1;//页数
XWPFParagraph pa = e.getBody().getParagraphArray(pIndex); //获取段落
List<CTR> ctrlist = pa.getCTP().getRList();//获取<w:p>标签下的<w:r>list
for(int j=0; j < ctrlist.size(); j++) { .//遍历r

CTR r = ctrlist.get(j); 
    List<CTEmpty> breaklist = r.getLastRenderedPageBreakList();//判断是否存在此标签
    if(breaklist.size() > 0) {
        num++; //页数添加
    }

}


由此可以高效率的获取到页码,生成目录的代码可以参考:[https://www.jianshu.com/p/0a32d8bd6878](https://www.jianshu.com/p/0a32d8bd6878)  
所以大体功能实现思路如下:

*   POI读取word模板文件(模板必须有页码并且目录位置先用标签标记),然后进行模板内容替换。
*   内容替换完毕后,再整体遍历所有段落和表格,在添加目录项时将对应的目录标题和页码作为参数传入,生成目录。
*   全部生成完毕后,将文档输出到目标文件。

---------------------------------------------------

原网址: [访问](https://www.404bugs.com/index.php/details/1078824995089338368)
创建于: 2023-05-08 11:16:58
目录: default

请先后发表评论
  • 最新评论
  • 总共0条评论