POI 替换word文档书签

word按照版本为两种:doc和docx,POI针对这两种操作需要不同的API:

 

doc操作使用HWPFDocument,替换思想就是找到书签的起止位置,对范围内的文本进行替换:

public static void docOperate(InputStream inputStream,OutputStream outputStream,
                                  Map dataMap) throws IOException {

        HWPFDocument document = new HWPFDocument(inputStream);
        Bookmarks bookmarks = document.getBookmarks();
        for(int dwI = 0;dwI < bookmarks.getBookmarksCount();dwI++){
            Bookmark bookmark = bookmarks.getBookmark(dwI);
            if(dataMap.containsKey(bookmark.getName())){
                Range range = new Range(bookmark.getStart(),bookmark.getEnd(),document);
                range.replaceText(dataMap.get(bookmark.getName()),false);
            }
        }
        document.write(outputStream);
    }

docx 操作使用 XWPFDocument,替换思想是根据段落找到书签,然后取书签起止范围内的节点进行操作,目的就是将书签起止范围内的多个文字节点删除,然后添加新的文本内容;此时可将文本插入或替换在书签的前、中、后等位置,因书签原内容已删,效果其实是一样的:

/** docx中定义的部分常量引用  **/
    public static final String RUN_NODE_NAME = "w:r";
    public static final String TEXT_NODE_NAME = "w:t";
    public static final String BOOKMARK_START_TAG = "w:bookmarkStart";
    public static final String BOOKMARK_END_TAG = "w:bookmarkEnd";
    public static final String BOOKMARK_ID_ATTR_NAME = "w:id";
    public static final String STYLE_NODE_NAME = "w:rPr";



public static void docxOperate(InputStream inputStream,OutputStream outputStream,Map dataMap) throws IOException {
        XWPFDocument document = new XWPFDocument(inputStream).getXWPFDocument();
        List paragraphList =  document.getParagraphs();
        for(XWPFParagraph xwpfParagraph:paragraphList){
            CTP ctp = xwpfParagraph.getCTP();

            for(int dwI = 0;dwI < ctp.sizeOfBookmarkStartArray();dwI++){
                CTBookmark bookmark = ctp.getBookmarkStartArray(dwI);
                if(dataMap.containsKey(bookmark.getName())){

                    XWPFRun run = xwpfParagraph.createRun();
                    run.setText(dataMap.get(bookmark.getName()));

                    Node firstNode = bookmark.getDomNode();
                    Node nextNode = firstNode.getNextSibling();
                    while(nextNode != null){
                        // 循环查找结束符
                        String nodeName = nextNode.getNodeName();
                        if(nodeName.equals(BOOKMARK_END_TAG)){
                            break;
                        }

                        // 删除中间的非结束节点,即删除原书签内容
                        Node delNode = nextNode;
                        nextNode = nextNode.getNextSibling();

                        ctp.getDomNode().removeChild(delNode);
                    }

                    if(nextNode == null){
                        // 始终找不到结束标识的,就在书签前面添加
                        ctp.getDomNode().insertBefore(run.getCTR().getDomNode(),firstNode);
                    }else{
                        // 找到结束符,将新内容添加到结束符之前,即内容写入bookmark中间
                        ctp.getDomNode().insertBefore(run.getCTR().getDomNode(),nextNode);
                    }
                }
            }
        }

        document.write(outputStream);
        document.close();
    }

pom需要引入的maven包:


			org.apache.poi
			poi
			3.13
		
		
			org.apache.poi
			poi-scratchpad
			3.13
		
		
			org.apache.poi
			poi-ooxml
			3.13
		

 

 

按照这个方法,普通的文本替换没有问题,但是图片和table等内容无法替换,poi对doc的操作据了解是没有table相关的,docx的table等操作需要自行找到拷贝、替换方案。

 

你可能感兴趣的:(java)