在 Java 中使用 Apache POI 生成文档间超链接

2023-12-10

我正在使用 Apache POI 生成 XWPFDocument(在此之前从未使用过它),并且我想将同一个 .docx 文档中的一个段落链接到另一个段落。使用 POI 的本机功能是否可以实现这一点,或者我是否需要深入研究 XML Bean 包装类(即 CTP)来手动实现这一点,还是我运气不好?我见过的有关超链接和 POI 的问题的每个实例都引用了创建外部类型超链接或 Excel 工作簿工作表之间的链接。到目前为止,我只能在按住 Ctrl 键单击已完成文档内的段落的意义上生成“超链接”,并且它似乎只是从文档顶部开始进行文本搜索。这是我目前用来实现此目的的代码。提前致谢!

public static void addInternalHyperlink(XWPFParagraph origin, String text, XWPFParagraph target) {

        if (target != null) {

        // Create the hyperlink itself
        CTHyperlink link = origin.getCTP().addNewHyperlink();       
        link.setAnchor(target.getText());

        // Create hyperlink text
        CTText linkText = CTText.Factory.newInstance();
        linkText.setStringValue(text);      
        CTR ctr = CTR.Factory.newInstance();
        ctr.setTArray(new CTText[] {linkText});

        // Format hyperlink text
        CTFonts fonts = CTFonts.Factory.newInstance();
        fonts.setAscii("Times New Roman");
        CTRPr rpr = ctr.addNewRPr();
        CTColor color = CTColor.Factory.newInstance();
        color.setVal("0000FF");
        rpr.setColor(color);
        CTRPr rpr1 = ctr.addNewRPr();
        rpr1.addNewU().setVal(STUnderline.SINGLE);

        // Insert formatted text into link
        link.setRArray(new CTR[] {ctr});
        }
    }

请注意,我想使用“origin”参数作为包含实际链接的段落,使用“text”参数作为链接文本,使用“target”参数作为实际链接目标。

更新:这是一个包含示例段落的 XML 片段,我已通过 Word GUI 将其链接到章节标题。

<w:p w14:paraId="5B1C3A0C" w14:textId="659E388D" w:rsidR="00A4419C" w:rsidRDefault="00A4419C" w:rsidP="00A4419C"><w:hyperlink w:anchor="_Another_Heading" w:history="1"><w:r w:rsidRPr="00A4419C"><w:rPr><w:rStyle w:val="Hyperlink"/></w:rPr><w:t>Here is some stuff that could b</w:t></w:r><w:r w:rsidRPr="00A4419C"><w:rPr><w:rStyle w:val="Hyperlink"/></w:rPr><w:t>e</w:t></w:r><w:r w:rsidRPr="00A4419C"><w:rPr><w:rStyle w:val="Hyperlink"/></w:rPr><w:t xml:space="preserve"> the link</w:t></w:r></w:hyperlink></w:p><w:p w14:paraId="19996B78" w14:textId="5C39B081" w:rsidR="00A4419C" w:rsidRPr="00A4419C" w:rsidRDefault="00A4419C" w:rsidP="00A4419C"><w:pPr><w:pStyle w:val="Heading1"/></w:pPr><w:bookmarkStart w:id="0" w:name="_Another_Heading"/><w:bookmarkEnd w:id="0"/><w:r><w:t>Another Heading</w:t></w:r><w:bookmarkStart w:id="1" w:name="_GoBack"/><w:bookmarkEnd w:id="1"/></w:p>

该解决方案分为两部分。

首先我们需要一个XWPFHyperlinkRun其目标是文档中的锚点。

其次,我们需要目标锚点,例如,它可以是文档中的书签。所以我们需要在文档中创建这样的书签。

不幸的是,仅使用高级类不支持两者apache poi到目前为止。所以我们需要低级课程形式ooxml-schemas too.

以下代码可以使用apache poi 4.0.0和...一起ooxml-模式-1.4.

import java.io.FileOutputStream;

import org.apache.poi.xwpf.usermodel.*;

import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBookmark;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHyperlink;

import java.math.BigInteger;

public class CreateWordHyperlinkBookmark {

 static XWPFHyperlinkRun createHyperlinkRunToAnchor(XWPFParagraph paragraph, String anchor) throws Exception {
  CTHyperlink cthyperLink=paragraph.getCTP().addNewHyperlink();
  cthyperLink.setAnchor(anchor);
  cthyperLink.addNewR();
  return new XWPFHyperlinkRun(
    cthyperLink,
    cthyperLink.getRArray(0),
    paragraph
   );
 }

 static XWPFParagraph createBookmarkedParagraph(XWPFDocument document, String anchor, int bookmarkId) {
  XWPFParagraph paragraph = document.createParagraph();
  CTBookmark bookmark = paragraph.getCTP().addNewBookmarkStart();
  bookmark.setName(anchor);
  bookmark.setId(BigInteger.valueOf(bookmarkId));
  XWPFRun run = paragraph.createRun();
  paragraph.getCTP().addNewBookmarkEnd().setId(BigInteger.valueOf(bookmarkId));
  return paragraph;
 }

 public static void main(String[] args) throws Exception {

  XWPFDocument document = new XWPFDocument();

  String anchor = "hyperlink_target"; 
  int bookmarkId = 0;

  XWPFParagraph paragraph = document.createParagraph();
  XWPFRun run = paragraph.createRun();
  run.setText("This is a text paragraph having ");

  //create hyperlink run
  XWPFHyperlinkRun hyperlinkrun = createHyperlinkRunToAnchor(paragraph, anchor);
  hyperlinkrun.setText("a link to an bookmark anchor");
  hyperlinkrun.setColor("0000FF");
  hyperlinkrun.setUnderline(UnderlinePatterns.SINGLE);

  run = paragraph.createRun();
  run.setText(" in it.");

  //some empty paragraphs
  for (int i = 0; i < 10; i++) {
   paragraph = document.createParagraph();
  }

  //create bookmarked paragraph as the hyperlink target
  paragraph = createBookmarkedParagraph(document, anchor, bookmarkId++);
  run = paragraph.getRuns().get(0);
  run.setText("This is the target.");

  FileOutputStream out = new FileOutputStream("CreateWordHyperlinkBookmark.docx");
  document.write(out);
  out.close();
  document.close();

 }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Java 中使用 Apache POI 生成文档间超链接 的相关文章

  • 在Java中将*s打印为三角形?

    我在 Java 课程中的作业是制作 3 个三角形 一份左对齐 一份右对齐 一份居中 我必须为什么类型的三角形制作一个菜单 然后输入需要多少行 三角形必须看起来像这样 到目前为止 我能够完成左对齐的三角形 但我似乎无法获得其他两个 我尝试用谷
  • 如何从 Play WSClient 的字符串创建 WSResponse 对象

    文档 https www playframework com documentation 2 4 x JavaTestingWebServiceClients Mock the web service建议使用模拟Web服务测试基于WSCli
  • 如何在 Java 中访问嵌套的 HashMap?

    我有一个 Java 中的 HashMap 其中的内容 你们可能都知道 可以通过以下方式访问 HashMap get keyname 如果一个 HashMap 位于另一个 HashMap 中 即嵌套的 HashMap 我将如何访问内容 我可以
  • Java 读取大文本文件时出现 OutOfMemoryError

    我是 Java 新手 正在读取非常大的文件 需要一些帮助来理解问题并解决它 我们有一些遗留代码 必须对其进行优化才能正常运行 文件大小仅在 10mb 到 10gb 之间变化 只有当文件开始大小超过 800mb 时才会出现启动问题 Input
  • GET 请求的 Spring 注解

    这两种spring GET方法有什么区别呢 哪一种是首选方法 Component Scope request Path public class TestComponent GET Path hello public String prin
  • JavaFX 2.0 FXML 子窗口

    经过多次搜索我发现了这个问题如何创建 javafx 2 0 应用程序 MDI https stackoverflow com questions 10915388 how to create a javafx 2 0 application
  • 如何将现有的 SQLite3 数据库导入 Room?

    好吧 我在桌面上使用 SQLite3 创建了一个只需要读取的某些信息的数据库 我正在制作的应用程序不需要在此表中插入或删除信息 我在 Room 数据库层上做了相当多的谷歌搜索 所有文档都需要在构建应用程序时在 Room 中创建一个新的数据库
  • OpenNLP 与斯坦福 CoreNLP

    我一直在对这两个包进行一些比较 但不确定该往哪个方向走 我简单地寻找的是 命名实体识别 人 地点 组织等 性别识别 一个不错的训练 API 据我所知 OpenNLP 和斯坦福 CoreNLP 提供了非常相似的功能 然而 Stanford C
  • 使用 JAX-WS 的 WebLogic 中没有模式导入的单个 WSDL

    如何使用 JAX WS 配置由 WebLogic 10 3 6 生成的 Web 服务 以将对象架构包含在单个 WSDL 文件声明 而不是导入声明 中 示例代码 界面 import javax ejb Local Local public i
  • Java - JPanel 内有边距和 JTextArea

    我想创建这样的东西 主面板有其边距 x 并且 TextArea 位于该面板的中心 几乎填满了面板 底部是另一个具有自定义尺寸 高度 y 的面板 可以使用某些快捷方式将其切换为可见和不可见 底部面板有 FlowLayout 和几个元素 问题是
  • 更改 JComboBox 中滚动条的大小

    有谁知道如何手动更改 jComboBox 中的滚动条大小 我已经尝试了一大堆东西 但没有任何效果 好吧 我明白了 您可以实现 PopUpMenuListener 并使用它 public void popupMenuWillBecomeVis
  • MongoDB java 驱动程序 3.0 在身份验证时无法捕获异常

    我超级卡住o 0 在尝试通过 Java 驱动程序进行身份验证时 存在捕获异常的问题 正如你可能会看到的Throwable类不工作 private MongoClient mongoClient private MongoDatabase m
  • JAXB 编组器无参数默认构造函数

    我想从 java 库中编组一个 java 对象 当使用 JAXB marschaller 编组 java 对象时 我遇到了一个问题 A 类没有无参数默认构造函数 我使用Java Decompiler来检查类的实现 它是这样的 public
  • 从浏览器访问本地文件?

    您好 我想从浏览器访问系统的本地文件 由于涉及大量安全检查 是否可以通过某种方式实现这一目标 或使用 ActiveX 或 Java Applet 的任何其他工作环境 请帮帮我 要通过浏览器访问本地文件 您可以使用签名的 Java Apple
  • android 中的 java.net.URL ..新手问题

    我是java新手 正在尝试android开发 以下代码生成 malformedURLException 有人可以帮助我识别异常吗 任何提示都会非常有帮助 package com example helloandroid import and
  • 传递 Android DialogFragment 参数时,onCreateDialog 捆绑参数意外为 null

    我正在尝试使用 DialogFragment 在 Android 中显示一个基本对话框 并使用对话框消息的参数 如中所述StackOverflow线程 https stackoverflow com questions 15459209 p
  • 如何将库添加到 LIBGDX 项目的依赖项 gradle

    一切都在问题中 我已经尝试了在 SO 和其他网站中找到的所有答案 但没有运气 这就是我迄今为止尝试过的 adding compile fileTree dir lib include jar 到我的 build gradle adding
  • 如何清理 Runtime.exec() 中使用的用户输入?

    我需要通过命令行调用自定义脚本 这些脚本需要很少的参数并在 Linux 机器上调用 当前版本容易出现各种shell注入 如何清理用户给出的参数 参数包括登录名和路径 Unix 或 Windows 路径 用户应该能够输入任何可能的路径 该路径
  • java.lang.ClassCastException:com.sun.proxy.$Proxy8 无法转换为 org.openqa.selenium.internal.WrapsDriver

    我有以下切入点和 AspectJ 中给出的建议 Pointcut call org openqa selenium WebElement sendKeys public void onWebElementAction After onWeb
  • Android Google 地图无法在当前主题中找到样式“mapViewStyle”

    添加谷歌地图视图时 我扩展了MapView 使用xml编辑器将其添加到活动中 并将我的谷歌地图api密钥手动添加到布局xml文件中 我的权限在清单文件中允许互联网 我想知道的是 在 xml 编辑器中 我收到错误 无法在当前主题中找到样式 m

随机推荐