Java使用poi获取不到docx表格中书签的问题及解决

 更新时间:2024年06月17日 10:37:27   作者:编程经验分享  
这篇文章主要介绍了Java使用poi获取不到docx表格中书签的问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

问题

实际项目中遇到个需求,需要替换 docx 中书签的内容。

使用 poi 读取 docx 的书签,直接获取文档中的段落(paragraph)的书签然后进行替换内容,处理完后发现文档中表格里的书签并没有被替换

如何解决

文档中每个单元格里的内容也是段落(paragraph),将表格中的书签做单独处理,先获取所有表格(table)所有单元格(cell),再获取段落进行书签替换即可

代码

替换书签方法

public class WordUtil {

    /**
     * 处理表格中的书签 每个单元格里的内容都可以看作一个段落
     * 
     * @param xwpfDocument 文档对象
     * @param dataMap 书签内容
     */
    public static void dealBookmarkOfDocx(XWPFDocument xwpfDocument, Map<String, String> dataMap) throws IOException {
        //处理表格中的书签
        List<XWPFTable> tableList = xwpfDocument.getTables();
        for (XWPFTable table : tableList) {
            int rowCount = table.getNumberOfRows();//获取table的行数
            for (int i = 0; i < rowCount; i++) {
                XWPFTableRow row = table.getRow(i);
                List<XWPFTableCell> cells = row.getTableCells();
                for (XWPFTableCell cell : cells) {
                    dealParagraphBookmark(cell.getParagraphs(), dataMap);
                }
            }
        }
        //处理段落里的书签
        List<XWPFParagraph> paragraphs = xwpfDocument.getParagraphs();
        dealParagraphBookmark(paragraphs, dataMap);
    }

    /**
     * 替换每个段落中的书签
     *
     * @param paragraphList 段落list
     * @param dataMap 书签内容
     */
    private static void dealParagraphBookmark(List<XWPFParagraph> paragraphList, Map<String, String> dataMap) {
        for (XWPFParagraph paragraph : paragraphList) {
            CTP ctp = paragraph.getCTP();
            for (int i = 0; i < ctp.sizeOfBookmarkEndArray(); i++) {
                CTBookmark bookmark = ctp.getBookmarkStartArray(i);
                String bookmarkName = bookmark.getName();
                if (dataMap.containsKey(bookmarkName)) {
                    XWPFRun xwpfRun = paragraph.createRun();
                    xwpfRun.setText(dataMap.get(bookmarkName));

                    Node firstNode = bookmark.getDomNode();
                    Node nextNode = firstNode.getNextSibling();
                    while (nextNode != null) {
                        String nodeName = nextNode.getNodeName();
                        if (nodeName.equalsIgnoreCase("w:bookmarkEnd")) {
                            break;
                        }
                        Node delNode = nextNode;
                        nextNode = nextNode.getNextSibling();
                        ctp.getDomNode().removeChild(delNode);
                    }
                    if (nextNode == null) {
                        //找不到结束标识,在书签前面加
                        ctp.getDomNode().insertBefore(xwpfRun.getCTR().getDomNode(), firstNode);
                    } else {
                        //找到结束符,将新内容添加到结束符之前,即内容写入bookmark中间
                        ctp.getDomNode().insertBefore(xwpfRun.getCTR().getDomNode(), nextNode);
                    }
                }
            }
        }
    }
}

测试

class WordUtilTest {

    @Test
    void dealBookmarkOfDocx() {
        String docxPath = "C:\\Users\\XXX\\Desktop\\myDoc.docx";

        Map<String, String> dataMap = new HashMap<>();
        dataMap.put("bookmark1", "1234567");

        try (InputStream inputStream = Files.newInputStream(Paths.get(docxPath));
             XWPFDocument xDoc = new XWPFDocument(inputStream)) {

            WordUtil.dealBookmarkOfDocx(xDoc, dataMap);

            xDoc.write(Files.newOutputStream(Paths.get(docxPath)));

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • SpringBoot 接口开发教程(httpclient客户端)

    SpringBoot 接口开发教程(httpclient客户端)

    这篇文章主要介绍了SpringBoot 接口开发教程(httpclient客户端),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • SpringCloud微服务之Config知识总结

    SpringCloud微服务之Config知识总结

    今天带大家学习SpringCloud微服务中的Config的相关知识,文中有非常详细的介绍,对正在学习SpringCloud微服务的小伙伴们有很好地帮助,需要的朋友可以参考下
    2021-05-05
  • Java之操作Redis案例讲解

    Java之操作Redis案例讲解

    这篇文章主要介绍了Java之操作Redis案例讲解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • Java 汉字获取拼音或首字母工具类代码分析

    Java 汉字获取拼音或首字母工具类代码分析

    在本篇内容里小编给大家分享的是一篇关于Java 汉字获取拼音或首字母工具类知识点内容,有需要的朋友们可以学习参考下。
    2021-06-06
  • 浅谈Java向下转型的意义

    浅谈Java向下转型的意义

    这篇文章主要介绍了浅谈Java向下转型的意义,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • Mybatis 在 insert 插入操作后返回主键 id的操作方法

    Mybatis 在 insert 插入操作后返回主键 id的操作方法

    这篇文章主要介绍了Mybatis 在 insert 插入操作后返回主键 id的操作方法,本文结合示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-12-12
  • SpringBoot+thymeleaf+Echarts+Mysql 实现数据可视化读取的示例

    SpringBoot+thymeleaf+Echarts+Mysql 实现数据可视化读取的示例

    本文主要介绍了SpringBoot+thymeleaf+Echarts+Mysql 实现数据可视化读取的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • Java Class 解析器实现方法示例

    Java Class 解析器实现方法示例

    这篇文章主要通过对class文件的分析,介绍了Java Class 解析器实现方法示例,具有一定参考价值,需要的朋友可以了解下。
    2017-09-09
  • Java字符串分解技术substring、tokenizing和trimming方法的使用

    Java字符串分解技术substring、tokenizing和trimming方法的使用

    这篇文章主要介绍了Java字符串分解技术substring、tokenizing和trimming方法的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-05-05
  • 解决Java执行Cmd命令出现的死锁问题

    解决Java执行Cmd命令出现的死锁问题

    这篇文章主要介绍了关于Java执行Cmd命令出现的死锁问题解决,解决方法就是在waitfor()方法之前读出窗口的标准输出、输出、错误缓冲区中的内容,本文给大家介绍的非常详细,需要的朋友可以参考下
    2022-07-07

最新评论