Apache POI - 将 Word 文档 (docx) 拆分为页面

2023-12-03

我一直在尝试根据预定义的标准将 docx 文档分割为多个文档。以下是我将其切成段落的方法

        try {
        FileInputStream in = new FileInputStream(file);
        XWPFDocument doc = new XWPFDocument(in);
        List<XWPFParagraph> paragraphs = doc.getParagraphs();
        for (int idx = 0; idx < paragraphs.size(); idx++) {
            XWPFDocument outputDocument = new XWPFDocument();
            createParagraphInAnotherDocument(outputDocument, paragraphs.get(idx).getText());
            String fullPath = String.format("./content/output/%1$s_%2$s_%3$04d.docx", FileUtils.getFileName(file), getName(), idx);
            FileOutputStream outputStream = new FileOutputStream(fullPath);
            outputDocument.write(outputStream);
            outputDocument.close();

            doc.close();
        }

    } catch (IOException e) {
        e.printStackTrace();
    }

虽然我可以使用上面的代码提取段落,但我找不到提取页面的方法。我的理解是,word中的页面是渲染关注点,它发生在word应用程序的运行时。


据我所知,执行此操作的唯一方法是询问 Word 文档的 DOM 模型,然后确定每个页面上有多少个段落。以下是该问题的可能解决方案(仅当页面由分页符明确分隔时才有效)

public static void main(String[] args) {
    XWPFDocument doc = null;

    try {
        //Input Word Document
        File file = new File("C:/TestDoc.docx");
        FileInputStream in = new FileInputStream(file);
        doc = new XWPFDocument(in);

        //Determine how many paragraphs per page
        List<Integer> paragraphCountList = getParagraphCountPerPage(doc);

        if (paragraphCountList != null && paragraphCountList.size() > 0) {
            int docCount = 0;
            int startIndex = 0;
            int endIndex = paragraphCountList.get(0);

            //Loop through the paragraph counts for each page
            for (int i=0; i < paragraphCountList.size(); i++) {
                XWPFDocument outputDocument = new XWPFDocument();

                List<XWPFParagraph> paragraphs = doc.getParagraphs();
                List<XWPFParagraph> pageParagraphs = new ArrayList<XWPFParagraph>();

                if (paragraphs != null && paragraphs.size() > 0) {
                    //Get the paragraphs from the input Word document
                    for (int j=startIndex; j < endIndex; j++) {
                        if (paragraphs.get(j) != null) {
                            pageParagraphs.add(paragraphs.get(j));
                        }
                    }

                    //Set the start and end point for the next set of paragraphs
                    startIndex = endIndex;

                    if (i < paragraphCountList.size()-2) {
                        endIndex = endIndex + paragraphCountList.get(i+1);
                    } else {
                        endIndex = paragraphs.size()-1;
                    }


                    //Create a new Word Doc with the paragraph subset
                    createPageInAnotherDocument(outputDocument, pageParagraphs);

                    //Write the file
                    String outputPath = "C:/TestDocOutput"+docCount+".docx";
                    FileOutputStream outputStream = new FileOutputStream(outputPath);
                    outputDocument.write(outputStream);
                    outputDocument.close();

                    docCount++;
                    pageParagraphs = new ArrayList<XWPFParagraph>();
                }
            }
        }

    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            doc.close();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
}


private static List<Integer> getParagraphCountPerPage(XWPFDocument doc) throws Exception {
    List<Integer> paragraphCountList = new ArrayList<>();
    int paragraphCount = 0;

    Document domDoc = convertStringToDOM(doc.getDocument().getBody().toString());
    NodeList rootChildNodeList = domDoc.getChildNodes().item(0).getChildNodes();

    for (int i=0; i < rootChildNodeList.getLength(); i++) {
        Node childNode = rootChildNodeList.item(i);

        if (childNode.getNodeName().equals("w:p")) {
            paragraphCount++;

            if (childNode.getChildNodes() != null) {
                for (int k=0; k < childNode.getChildNodes().getLength(); k++) {
                    if (childNode.getChildNodes().item(k).getNodeName().equals("w:r")) {
                        for (int m=0; m < childNode.getChildNodes().item(k).getChildNodes().getLength(); m++) {
                            if (childNode.getChildNodes().item(k).getChildNodes().item(m).getNodeName().equals("w:br")) {

                                paragraphCountList.add(paragraphCount);
                                paragraphCount = 0;
                            }
                        }
                    }
                }
            }
        }
    }

    paragraphCountList.add(paragraphCount+1);

    return paragraphCountList;
}


private static Document convertStringToDOM(String xmlData) throws Exception {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = factory.newDocumentBuilder();

    Document document = builder.parse(new InputSource(new StringReader(xmlData)));    

    return document;
}


private static void createPageInAnotherDocument(XWPFDocument outputDocument, List<XWPFParagraph> pageParagraphs) throws IOException {
    for (int i = 0; i < pageParagraphs.size(); i++) {
        addParagraphToDocument(outputDocument, pageParagraphs.get(i).getText());
    }
}


private static void addParagraphToDocument(XWPFDocument outputDocument, String text) throws IOException {
    XWPFParagraph paragraph = outputDocument.createParagraph();
    XWPFRun run = paragraph.createRun();
    run.setText(text);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Apache POI - 将 Word 文档 (docx) 拆分为页面 的相关文章

随机推荐

  • 如何使用SQL存储过程创建数据库?

    如何使用SQL存储过程创建数据库 为什么我不能将数据库作为变量发送 从外部发送数据库名称有限制吗 如果有这样的限制我该怎么办 create proc AddDatabase Name varchar 100 FileName varchar
  • android 保存以编程方式创建的视图

    我以编程方式创建一个RelativeLayout 其中包含一些其他视图 并将其添加到在XML 中定义的父视图 但是 重新创建活动后 以编程方式创建的所有视图 包括布局 都会消失 我是否需要 SharedPreferences 对象来保存值
  • 如何从数组中删除偶数?

    我需要删除该数组的偶数 function removeEvens numbers Do not modify code below this line const oddNumbers removeEvens 1 2 3 4 5 conso
  • iOS 通用应用程序在手机上似乎略有放大

    我有一个 iPad 应用程序 我正在将其转换为通用应用程序以在手机上显示 它有一个标签栏和一个导航栏 我的问题是它们在手机上都太大了 我可以发誓我听到 Paul Hegarty 斯坦福大学 iTunes U 课程的 Swift 应用程序开发
  • 终止CBPeripheralManager端的连接

    有没有推荐的方法CBPeripheralManager终止连接 到目前为止我发现的最好方法就是不响应动态值 然后 BLE 堆栈似乎会关闭连接 但这看起来相当粗糙 一定会有更好的办法 不 您无法从外围侧以明确的方式强行关闭连接 没有适用于它的
  • 升级到 Rails 3 后尝试启动服务器时出错

    我刚刚按照以下说明升级到 Rails 3这个铁路广播 当我尝试启动服务器时 会发生以下情况 rails s script rails 6 in require no such file to load rails commands Load
  • Winpty 和 Git Bash

    我有同样的问题Python 无法在 git bash 命令行中工作 当我在 Git Bash 中输入时Python 它只是挂起 然而 输入winpty python工作完美 到底是什么winpty 为什么上面的命令有用 Quoting 自述
  • jquery历史插件设置当前页面可能吗?

    我用jquery分页插件 不幸的是它没有方法从对象外部设置当前页面 我真的研究过这个对象 函数不长 但作为一个 jquery 初学者 我什至无法找到事件如何绑定 显然是通过单击 我不知道如何修改这个函数 所以我可以调用类似的东西 curre
  • 静态 NextJS 站点中的 localStorage:ReferenceError:localStorage 未定义

    我尝试在 NextJS 静态站点上使用 localStorage 但遇到 localStorage is not Defined 错误 我的错误显示组件的代码是 export default function Category const
  • 即使在 'global $wpdb 之后 $wpdb 也为 null

    我已经看过几乎所有链接 但仍然无法解决我的问题 我得到 wpdb 作为null 我正在这样检查 我在 single php 文件中执行此操作 echo pre print r wpdb pre 我已经检查了以下文件 一切都已加载 wp co
  • javascript数组参数列表[重复]

    这个问题在这里已经有答案了 可能的重复 在Javascript中使用动态参数调用动态函数 我有一个数组 表示需要传递给函数调用的参数 如何动态构造这个函数调用 e g function constructRequest params par
  • 我如何知道我的 Google 地图当前的实际比例?

    我的网站上有一个 Google 地图 v3 我想知道我当前的缩放比例是多少 问题是用户可以改变它的缩放 因此比例可以改变 我需要的信息是地图的实际宽度 以公里为单位 我知道我可以使用 Bounds 但是还有其他方法吗 我真的不想使用 Bou
  • R grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, 中的错误:绘图时找不到多边形边缘

    我知道还有其他关于此的帖子 但我已经尝试了他们建议的所有内容 但没有任何效果 我以前没有这个问题 现在突然之间 在运行我之前运行的代码时 我开始遇到这个问题 我认为这与我正在创建的主题有关 但我不明白为什么这之前工作得很好 现在却给了我这个
  • Azure B2C 注册策略重定向到应用程序后,AngularJS 哈希 # 问题

    我们想要做的是在用户成功注册后自动登录 登录 假设用户收到了应用程序的邀请 他们转到 注册 页面 填写表格并单击 创建 按钮 如果一切正常 用户将被添加到 Azure B2C 目录 然后我们会以某种方式自动运行登录策略或自动登录的其他方式
  • 如何在 Firebase 中注册用户名?

    我正在尝试在 Firebase 中实现用户名注册 因为它只提供了类似于createUserWithEmailAndPassword 但你无法创建用户名 我不知道该怎么做 下面是我的注册代码 但我还想输入一个可以使用它的用户名 当用户发布某些
  • 对矩阵中的每 N 个值求和

    因此 我查看了之前发布的这个问题 该问题用于对矩阵中每行中的每 2 个值求和 链接在这里 对行中的特定列求和 我还在这里查看了另一个问题 R 对矩阵中的每 k 列求和这和我的更相似 在这种情况下我无法让解决方案发挥作用 这是我正在使用的代码
  • Android Studio 无法构建新项目,在等待从属 aapt 进程时超时

    我已经安装了 Android Studio 1 2 并创建了一个新项目 当我尝试构建时 它挂起 这是在 Gradle 控制台中 以及大约 20 个其他副本 在 png cruncher 之后有不同的数字 Exception in threa
  • 适合给定金额的最佳硬币

    给定一组硬币 您如何以最优化的方式达到给定的金额 假设在这种情况下 我们有 1 5 10 20 和 50 分硬币的随机数 最大的硬币优先 我的第一直觉是使用所有可能适合的最大硬币 然后如果超出总和 则使用价值下一个最小的硬币 这种方法会起作
  • 在 Adob​​e Air 的 iOS 本机扩展中访问 ViewController

    短的 Air Native Extensions 的 Android API 在 Context Object 上提供了 getActivity 我正在寻找一种方法 在 iOS Native Extensions 中获取当前的 ViewCo
  • Apache POI - 将 Word 文档 (docx) 拆分为页面

    我一直在尝试根据预定义的标准将 docx 文档分割为多个文档 以下是我将其切成段落的方法 try FileInputStream in new FileInputStream file XWPFDocument doc new XWPFDo