You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache POI 5 在Word表格单元格中设置超链接及解决链接列空白问题

问题核心原因

你遇到的超链接列内容为空是以下3个问题共同导致的:

  1. 新创建的表格单元格默认包含空段落占位内容,未清空直接新增超链接Run会出现POI渲染优先级问题,导致超链接内容不展示
  2. XWPFRun.setText()未指定插入位置参数0,部分版本POI不会将文本写入到Run的有效内容节点
  3. 解析到多个a标签时重复调用setLink方法,会导致内容覆盖、格式混乱

修复后的代码

1. 修改setLink工具方法

// 设置自定义字体大小
static void setFontSize(XWPFTableCell cell, int size) {
    for (XWPFParagraph paragraph : cell.getParagraphs()) {
        for (XWPFRun run : paragraph.getRuns()) {
            run.setFontSize(size);
        }
    }
}

// 将表格单元格内容设置为链接
static void setLink(XWPFTableCell cell, String text, String link, int size) {
    // 先清空单元格原有内容
    cell.removeParagraph(0);
    XWPFParagraph paragraph = cell.addParagraph();
    // 取消段落默认边距,避免和其他单元格行高不一致
    paragraph.setSpacingAfter(0);
    paragraph.setSpacingBefore(0);
    
    // 创建超链接Run
    XWPFRun run = paragraph.createHyperlinkRun(link);
    // 指定插入位置为0,确保文本写入有效节点
    run.setText(text, 0);
    run.setUnderline(UnderlinePatterns.SINGLE);
    run.setColor("0000FF");
    run.setFontSize(size);
}

2. 修改extractData核心逻辑

public Void extractData(ResultSet rs) throws SQLException, DataAccessException {

    ResultSetMetaData rsmd = rs.getMetaData();
    int columnsNumber = rsmd.getColumnCount();
    XWPFDocument document = new XWPFDocument();

    // 设置页面方向
    CTDocument1 ctDocument = document.getDocument();
    CTBody ctBody = ctDocument.getBody();
    CTSectPr ctSectPr = (ctBody.isSetSectPr()) ? ctBody.getSectPr() : ctBody.addNewSectPr();
    CTPageSz ctPageSz = (ctSectPr.isSetPgSz()) ? ctSectPr.getPgSz() : ctSectPr.addNewPgSz();
    ctPageSz.setOrient(STPageOrientation.LANDSCAPE);

    // 设置纸张尺寸为A3
    ctPageSz.setW(java.math.BigInteger.valueOf(Math.round(16.5 * 1440))); // 16.5英寸
    ctPageSz.setH(java.math.BigInteger.valueOf(Math.round(11.7 * 1440))); // 11.7英寸

    // 创建表格,行数为1,列数与结果集列数一致
    XWPFTable table = document.createTable(1, columnsNumber);

    // 获取表头行
    XWPFTableRow header = table.getRow(0);
    // 设置表头列
    for (int col = 0; col < columnsNumber; col++) {
        header.getCell(col).setText(rsmd.getColumnLabel(col + 1));
        setFontSize(header.getCell(col), 6);
    }
    // 设置数据行
    while (rs.next()) {
        XWPFTableRow desRow = table.createRow();
        for (int col = 0; col < columnsNumber; col++) {
            final var value = rs.getObject(col + 1);
            String v = value == null ? "" : value.toString();

            if (v.startsWith("<a")) {
                Document doc = Jsoup.parse(v);
                Elements links = doc.getElementsByTag("a");
                XWPFTableCell cell = desRow.getCell(col);
                // 先清空单元格原有内容
                cell.removeParagraph(0);
                XWPFParagraph paragraph = cell.addParagraph();
                paragraph.setSpacingAfter(0);
                paragraph.setSpacingBefore(0);
                // 处理所有a标签,支持同一单元格多个超链接
                for (int i = 0; i < links.size(); i++) {
                    Element element = links.get(i);
                    String text = element.text();
                    String href = element.attr("href").trim();
                    String encURL = href.replaceAll(" ", "%20");
                    XWPFRun run = paragraph.createHyperlinkRun(encURL);
                    run.setText(text, 0);
                    run.setUnderline(UnderlinePatterns.SINGLE);
                    run.setColor("0000FF");
                    run.setFontSize(6);
                    // 多个链接之间加空格分隔,可按需调整
                    if (i != links.size() - 1) {
                        paragraph.createRun().setText(" ", 0);
                    }
                }
            } else {
                desRow.getCell(col).setText(v);
                setFontSize(desRow.getCell(col), 6);
            }
        }
    }

    table.removeBorders();
    XWPFStyles styles = document.createStyles();
    XWPFStyle style;
    style = createTableStyle(styles, "ListTableStyle");
    table.setStyleID(style.getStyleId());
    try {
        document.write(os);
        document.close();
    } catch (IOException e) {
        log.error("Error occurred: {0}", e);
    }
    return null;
}

额外注意事项

  • 确保使用的Apache POI版本在4.1.2及以上,低版本createHyperlinkRun存在已知渲染bug
  • 如果生成的超链接点击无法跳转,可检查转义后的URL是否符合规范,部分特殊字符需要额外编码处理

内容的提问来源于stack exchange,提问作者Ladu anand

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 05:15:03