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());
    }
}
相关推荐
0.0~0.03 分钟前
若依框架修改模板,添加通过excel导入数据功能
java·spring boot·vue
代码老y4 分钟前
SpringMVC核心原理与前后端数据交互机制详解
java·mvc·交互
m0_584624507 分钟前
SpringBoot关于文件上传超出大小限制--设置了全局异常但是没有正常捕获的情况+捕获后没有正常响应返给前端
java·spring
@曲终11 分钟前
C++:栈帧、命名空间、引用
java·开发语言·c++·经验分享·笔记
灰小猿12 分钟前
分布式项目保证消息幂等性的常见策略
java·redis·分布式·高并发·springcloud
劲爽小猴头25 分钟前
企业级Spring MVC高级主题与实用技术讲解
java·spring boot·后端·spring·mvc
快乐肚皮35 分钟前
深入解析MySQL日志模块 - Undo Log(回滚日志)与MVCC机制
java·mysql
星辰离彬1 小时前
【线上故障排查】系统缓存雪崩故障排查与解决全流程解析
java·spring boot·后端·程序人生·缓存·面试
黄雪超1 小时前
JVM——回顾:JVM的起源、特性与系统构成
java·开发语言·jvm
我不是程序猿儿1 小时前
【C++】C++面向对象设计的核心思想之一: 接口抽象、解耦和可扩展性
java·开发语言·c++