Java 拆分 Word 文档教程:按页、分页符和分节符拆分

在文档处理场景中,将一个 Word 文件拆分成多个独立文档是一项常见需求。例如,生成单独的章节文件、提取指定页面内容,或将大型报告按结构拆分保存,都需要对原始文档进行精准分割。

Java 提供了多种方式处理 Word 文档拆分操作,可以根据不同需求选择合适的拆分依据:按页拆分能够保留文档的页面布局,按分页符拆分适用于人工设置的内容分隔,而按分节符拆分则更适合处理具有章节结构的复杂文档。

本文将介绍如何使用 Java 实现 Word 文档的按页拆分、按分页符拆分以及按分节符拆分,帮助开发者根据实际业务需求灵活处理 Word 文件。

环境设置

要运行下面的代码示例,需要先在 Java 项目 中添加 Word 文档处理所需的依赖。

如果使用 Maven,可以在 ​​pom.xml​​ 中加入:

xml 复制代码
<repositories>
    <repository>
        <id>com.e-iceblue</id>
        <name>e-iceblue</name>
        <url>https://repo.e-iceblue.cn/repository/maven-public/</url>
    </repository>
</repositories>

<dependencies>
    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.doc</artifactId>
        <version>14.8.4</version>
    </dependency>
</dependencies>

1. 将 Word 文档的每一页拆分为单独文件

如果需要按照 Word 实际排版后的页面进行拆分,可以使用 ​​Document.extractPages()​​ 方法从原文档中提取页面,并生成新的 ​​Document​​ 对象。

下面的示例获取 Word 文档的总页数,然后逐页提取并保存为独立的 DOCX 文件:

typescript 复制代码
import com.spire.doc.Document;
import com.spire.doc.FileFormat;

public class SplitWordByPage {
    public static void main(String[] args) {

        // Load the Word document
        Document document = new Document();
        document.loadFromFile("Sample.docx");

        // Get the total number of pages
        int pageCount = document.getPageCount();

        // Extract each page to a separate document
        for (int i = 0; i < pageCount; i++) {

            Document pageDocument = document.extractPages(i, 1);

            pageDocument.saveToFile(
                    "output/Page-" + (i + 1) + ".docx",
                    FileFormat.Docx
            );

            pageDocument.close();
        }

        document.close();
    }
}

例如,一个包含 5 页的 Word 文档会被拆分为:

复制代码
Page-1.docx
Page-2.docx
Page-3.docx
Page-4.docx
Page-5.docx

​extractPages()​​ 的第一个参数表示起始页面索引,从 ​​0​​ 开始;第二个参数表示需要提取的页面数量。因此:

css 复制代码
document.extractPages(i, 1);

表示从索引 ​​i​​ 开始提取 1 页。

2. 提取 Word 文档中的指定页码范围

​extractPages()​​ 也可以一次提取连续的多个页面。

例如,需要将原文档的第 3 页到第 6 页保存为一个新的 Word 文档,可以使用下面的代码:

typescript 复制代码
import com.spire.doc.Document;
import com.spire.doc.FileFormat;

public class ExtractWordPageRange {
    public static void main(String[] args) {

        // Load the Word document
        Document document = new Document();
        document.loadFromFile("Sample.docx");

        int startPage = 3;
        int endPage = 6;

        // Validate the page range
        if (startPage < 1
                || endPage < startPage
                || endPage > document.getPageCount()) {
            throw new IllegalArgumentException("Invalid page range.");
        }

        // Convert the page number to a zero-based index
        int startIndex = startPage - 1;

        // Calculate the number of pages to extract
        int pageCount = endPage - startPage + 1;

        // Extract the specified pages
        Document extractedDocument =
                document.extractPages(startIndex, pageCount);

        extractedDocument.saveToFile(
                "output/Pages-3-6.docx",
                FileFormat.Docx
        );

        extractedDocument.close();
        document.close();
    }
}

需要注意的是,​​extractPages()​​ 使用从 ​​0​​ 开始的页面索引,而且第二个参数是提取页数,不是结束页码。

因此,提取第 3 页到第 6 页时实际调用的是:

ini 复制代码
document.extractPages(2, 4);

3. 按分页符拆分 Word 文档

分页符通常用于强制后续内容从新的一页开始。在 Word 中通过 Ctrl + Enter 插入的分页符属于显式分页符。

如果希望根据这些分页符拆分文档,可以遍历段落中的 ​​Break​​ 对象,并通过 ​​BreakType.Page_Break​​ 判断是否遇到了分页符。

下面的示例在检测到分页符时结束当前文档,并将后续内容写入新的 Word 文件:

scss 复制代码
import com.spire.doc.*;
import com.spire.doc.documents.*;

public class SplitWordByPageBreak {

    public static void main(String[] args) {

        // Load the source document
        Document source = new Document();
        source.loadFromFile("Sample.docx");

        // Create the first output document
        Document partDocument = createDocument(source);
        Section targetSection = partDocument.getSections().get(0);

        int fileIndex = 1;

        // Traverse all sections
        for (int s = 0; s < source.getSections().getCount(); s++) {

            Section sourceSection = source.getSections().get(s);

            // Copy section properties
            sourceSection.cloneSectionPropertiesTo(targetSection);

            // Traverse paragraphs and tables
            for (int i = 0;
                 i < sourceSection.getBody().getChildObjects().getCount();
                 i++) {

                DocumentObject object =
                        sourceSection.getBody()
                                .getChildObjects()
                                .get(i);

                if (object instanceof Table) {

                    targetSection.getBody()
                            .getChildObjects()
                            .add(object.deepClone());

                } else if (object instanceof Paragraph) {

                    Paragraph paragraph = (Paragraph) object;

                    targetSection.getBody()
                            .getChildObjects()
                            .add(paragraph.deepClone());

                    // Check for page breaks
                    for (int j = 0;
                         j < paragraph.getChildObjects().getCount();
                         j++) {

                        DocumentObject child =
                                paragraph.getChildObjects().get(j);

                        if (child instanceof Break
                                && ((Break) child).getBreakType()
                                .equals(BreakType.Page_Break)) {

                            int breakIndex =
                                    paragraph.getChildObjects()
                                            .indexOf(child);

                            // Remove the page break from the current output
                            Paragraph outputParagraph =
                                    targetSection.getBody()
                                            .getLastParagraph();

                            outputParagraph.getChildObjects()
                                    .removeAt(breakIndex);

                            // Save the current part
                            partDocument.saveToFile(
                                    "output/Part-" + fileIndex + ".docx",
                                    FileFormat.Docx
                            );

                            partDocument.close();
                            fileIndex++;

                            // Create the next document
                            partDocument = createDocument(source);
                            targetSection =
                                    partDocument.getSections().get(0);

                            sourceSection.cloneSectionPropertiesTo(
                                    targetSection
                            );

                            // Copy the paragraph after the page break
                            targetSection.getBody()
                                    .getChildObjects()
                                    .add(paragraph.deepClone());

                            Paragraph firstParagraph =
                                    targetSection.getParagraphs().get(0);

                            // Remove the page break and content before it
                            while (breakIndex >= 0
                                    && firstParagraph.getChildObjects()
                                            .getCount() > 0) {

                                firstParagraph.getChildObjects()
                                        .removeAt(breakIndex);

                                breakIndex--;
                            }

                            if (firstParagraph.getChildObjects()
                                    .getCount() == 0) {

                                targetSection.getBody()
                                        .getChildObjects()
                                        .remove(firstParagraph);
                            }
                        }
                    }
                }
            }
        }

        // Save the last part
        partDocument.saveToFile(
                "output/Part-" + fileIndex + ".docx",
                FileFormat.Docx
        );

        partDocument.close();
        source.close();
    }

    private static Document createDocument(Document source) {

        Document document = new Document();

        source.cloneDefaultStyleTo(document);
        source.cloneThemesTo(document);
        source.cloneCompatibilityTo(document);

        document.addSection();

        return document;
    }
}

如果原文档中包含两个分页符,拆分后会得到:

复制代码
Part-1.docx
Part-2.docx
Part-3.docx

这里识别的是文档中实际存在的 Page Break。文字因页面空间不足而自动流到下一页并不属于分页符,因此不会触发拆分。

如果需要按照 Word 最终显示的每一页拆分文档,应使用前面的 ​​extractPages()​​ 方法。

4. 按分节符拆分 Word 文档

Word 中的分节符会将文档划分为多个 Section。不同 Section 可以具有独立的页面尺寸、页边距、页眉页脚和页面方向等设置。

在 Spire.Doc for Java 中,可以直接遍历 ​​Document.getSections()​​,将每个 Section 克隆到新的 Word 文档中。

typescript 复制代码
import com.spire.doc.Document;
import com.spire.doc.FileFormat;
import com.spire.doc.Section;

public class SplitWordBySectionBreak {
    public static void main(String[] args) {

        // Load the Word document
        Document document = new Document();
        document.loadFromFile("Sample.docx");

        // Traverse all sections
        for (int i = 0;
             i < document.getSections().getCount();
             i++) {

            Section sourceSection =
                    document.getSections().get(i);

            // Create a new document
            Document sectionDocument = new Document();

            // Preserve document-level styles and settings
            document.cloneDefaultStyleTo(sectionDocument);
            document.cloneThemesTo(sectionDocument);
            document.cloneCompatibilityTo(sectionDocument);

            // Clone the current section
            sectionDocument.getSections()
                    .add(sourceSection.deepClone());

            // Save it as a separate Word file
            sectionDocument.saveToFile(
                    "output/Section-" + (i + 1) + ".docx",
                    FileFormat.Docx
            );

            sectionDocument.close();
        }

        document.close();
    }
}

如果原始文档包含三个 Section,拆分后会得到:

css 复制代码
Section-1.docx
Section-2.docx
Section-3.docx

一个 Section 可以包含一页,也可以包含多页。因此,按分节符拆分并不等同于按页拆分,而是保留每个 Section 中包含的全部内容。

Word 文档拆分方式对比

拆分方式 拆分依据 核心实现
每页拆分 Word 实际页面 ​extractPages(i, 1)​
指定页码范围 连续的实际页面 ​extractPages(index, count)​
按分页符拆分 显式分页符 ​BreakType.Page_Break​
按分节符拆分 Word Section ​Section.deepClone()​

如果需要根据 Word 最终排版结果拆分页面,可以使用 ​​extractPages()​​;如果文档已经通过分页符或分节符划分内容,则可以直接按照相应的文档结构进行拆分。

相关推荐
liyinchi19882 小时前
微信小程序支付遇到“由于小程序违规,支付功能暂时无法使用” 解决办法
java·微信小程序·go
横木沉2 小时前
IntelliJ IDEA 无法识别 Git:Git is not installed 问题解决
java·git·github·intellij-idea
code2cat2 小时前
Java进阶篇之Optional
java
用户8181870627463 小时前
第29章 死信队列与延迟消息实战
java·后端
专业程序开发源3 小时前
springboot旅游推荐系统82074-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·php·课程设计·旅游
步行cgn3 小时前
Spring 注入值中含有特殊符号的处理详解
java·后端·spring
user_admin_god3 小时前
第 11 篇:实践三 —— 表单 / 合同字段抽取
java·人工智能·spring boot·语言模型
未秃头的程序猿3 小时前
全链路追踪落地一年:从翻日志到秒级定位,我们都做了什么
java·后端·面试