java 使用 POI 为 word 文档自动生成书签

poi 版本:4.1.0

XML 复制代码
<properties>
	<java.version>1.8</java.version>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
	<maven.compiler.source>1.8</maven.compiler.source>
	<maven.compiler.target>1.8</maven.compiler.target>
	<poi.version>4.1.0</poi.version>
</properties>

<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi</artifactId>
	<version>${poi.version}</version>
	<scope>compile</scope>
	<optional>false</optional>
</dependency>
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi-ooxml</artifactId>
	<version>${poi.version}</version>
</dependency>
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi-ooxml-schemas</artifactId>
	<version>${poi.version}</version>
</dependency>

代码示例中是为类似如下所示的接口文档自动生成书签:

XML 复制代码
			人员接口文档
1.新增人员
	1.1.请求url:http://127.0.0.1/addUser
	1.2.请求方式:POST
	1.3.请求参数说明:xxxxxxxxxxxxxxxxxxxxxxxxxxx
					Xxxxxxxxxxxxxxxxxxxxxxxxxxx
					Xxxxxxxxxxxxxxxxxxxxxxxxx
	1.4.响应参数说明:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
					Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
					Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
2.删除人员
	2.1.请求url:http://127.0.0.1/removeUser
	2.2.请求方式:POST
	2.3.请求参数说明:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
					Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
					xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
	2.4.响应参数说明:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
					Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
					xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
3.查看人员详情
	3.1.请求url:http://127.0.0.1/userDetail
	3.2.请求方式:POST
	3.3.请求参数说明:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
					Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
					Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
	3.4.响应参数说明:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
					Xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
					xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

即读取文档的每一行内容,检测到该行文本以 "http://127.0.0.1" 开头则将其上一行设置为书签,请结合文档具体内容以及需求自行修改使用

例如原始文档如下所示:

输出文档如下所示:

java 复制代码
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.math.BigInteger;

public class WordBookmarkCreater {

    public static void main(String[] args) throws Exception {
        String inputFilePath = "D:\\xxx\\input.docx";
        String outputFilePath = "D:\\xxx\\output.docx";
        XWPFDocument doc = new XWPFDocument(new FileInputStream(inputFilePath));

        // 删除原本书签
        deleteAllBookmarks( doc );

        // 重新生成书签
        markHeadings(doc);

        // 保存文档
        FileOutputStream out = new FileOutputStream(outputFilePath);
        doc.write(out);
        out.close();
    }

    // 删除文档中的书签
    private static void deleteAllBookmarks(XWPFDocument doc) {
        // 普通段落
        for (XWPFParagraph p : doc.getParagraphs()) {
            clearBookmarks(p.getCTP());
        }

        // 表格中的段落
        for (XWPFTable table : doc.getTables()) {
            for (XWPFTableRow row : table.getRows()) {
                for (XWPFTableCell cell : row.getTableCells()) {
                    for (XWPFParagraph p : cell.getParagraphs()) {
                        clearBookmarks(p.getCTP());
                    }
                }
            }
        }
    }

    private static void clearBookmarks(CTP ctp) {
        ctp.getBookmarkStartList().clear();
        ctp.getBookmarkEndList().clear();
    }


    private static void markHeadings(XWPFDocument doc) {
        XWPFParagraph paragraph_prev = null;
        int num = 1;
        for (XWPFParagraph paragraph : doc.getParagraphs()) {
            String text = paragraph.getText();
            if( text.toLowerCase().contains( "请求" ) &&
                text.toLowerCase().contains( "url" ) &&
                text.toLowerCase().contains( "http://127.0.0.1" )){
                System.out.println( text );
                if( paragraph_prev == null ){
                    // 可选:添加书签锚点
                    addBookmark( paragraph, num + ". " + text );
                }else {
                    // 可选:添加书签锚点
                    addBookmark( paragraph_prev, num + ". " + paragraph_prev.getText() );
                }
                num++;
            }
            paragraph_prev = paragraph;
        }
    }

    private static void addBookmark(XWPFParagraph paragraph,String bookmarkName) {
        CTP ctp = paragraph.getCTP();
        CTBookmark bookmark = ctp.addNewBookmarkStart();
        bookmark.setId(BigInteger.valueOf( ctp.sizeOfBookmarkStartArray() ));
        bookmark.setName(bookmarkName);
        ctp.addNewBookmarkEnd().setId(bookmark.getId());
    }
}
相关推荐
v***913044 分钟前
Spring boot创建时常用的依赖
java·spring boot·后端
代码or搬砖3 小时前
MyBatisPlus讲解(二)
java·mybatis
lcu1113 小时前
Java 学习42:抽象
java
Mr.朱鹏4 小时前
RocketMQ安装与部署指南
java·数据库·spring·oracle·maven·rocketmq·seata
雨中飘荡的记忆4 小时前
Spring表达式详解:SpEL从入门到实战
java·spring
Coder-coco4 小时前
个人健康管理|基于springboot+vue+个人健康管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·mysql·论文
5***26224 小时前
Spring Boot问题总结
java·spring boot·后端
xkroy4 小时前
Spring Boot日志
java·spring boot·后端
n***F8754 小时前
【Spring Boot】SpringBoot自动装配-Import
java·spring boot·后端
〝七夜5694 小时前
JVM内存结构
java·开发语言·jvm