Apache POI 5 在Word表格单元格中设置超链接及解决链接列空白问题
问题核心原因
你遇到的超链接列内容为空是以下3个问题共同导致的:
- 新创建的表格单元格默认包含空段落占位内容,未清空直接新增超链接Run会出现POI渲染优先级问题,导致超链接内容不展示
XWPFRun.setText()未指定插入位置参数0,部分版本POI不会将文本写入到Run的有效内容节点- 解析到多个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
相关产品推荐
相关产品推荐

