Apache POI 5:在 word table 单元格中设置超链接

Apache POI 5 : Set hyperlinks in word table cell

我有一个 JDBC 结果集,我试图在 docx 文件的 table 中显示它。结果集中的一列是 link 。我能够解析 link 但无法在单元格中将其设置为 hyperlink 。我经历了多个 SO 问题,但无法实现。正在生成文件,但 link 列显示为空白。

// Set Custom Font Size
    static void setFontSize(XWPFTableCell cell, int size) {
        for (XWPFParagraph paragraph : cell.getParagraphs()) {
            for (XWPFRun run : paragraph.getRuns()) {
                run.setFontSize(size);
            }
        }
    }

    // Set table cell as link
    static void setLink(XWPFTableCell cell, String text, String link,int size) {
        for (XWPFParagraph paragraph : cell.getParagraphs()) {
            XWPFRun run = paragraph.createHyperlinkRun(link);
            run.setText(text);
            run.setUnderline(UnderlinePatterns.SINGLE);
            run.setColor("0000FF");
            run.setFontSize(size);
        }
    }
public Void extractData(ResultSet rs) throws SQLException, DataAccessException {

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

        // Set page orientation
        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);

        // set paper size A3
        ctPageSz.setW(java.math.BigInteger.valueOf(Math.round(16.5 * 1440))); // 16.5 inches
        ctPageSz.setH(java.math.BigInteger.valueOf(Math.round(11.7 * 1440))); // 11.7 inches

        // Creating Table with 1 row and as many columns as in the result set
        XWPFTable table = document.createTable(1, columnsNumber);

        // Get header Row
        XWPFTableRow header = table.getRow(0);
        // Set header columns
        for (int col = 0; col < columnsNumber; col++) {
            header.getCell(col).setText(rsmd.getColumnLabel(col + 1));
            // header.getCell(col).getCTTc().addNewTcPr().addNewShd().setFill("0394fc");
            setFontSize(header.getCell(col), 6);

        }
        // Set data rows
        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 rows = doc.getElementsByTag("a");
                    String text = "";
                    for (Element element : rows) {
                        text = element.text();
                        String href = element.attr("href").trim();
                        String encURL = "";
                        encURL = href.replaceAll(" ", "%20");
                        setLink(desRow.getCell(col), text, encURL,6);
                    }

                } 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;
    }

您的 setLink 方法假定 XWPFTableCell 已经有段落。但新创建的空 XWPFTableCells 并非如此。因此 for (XWPFParagraph paragraph : cell.getParagraphs()) 正文中的代码行将无法到达,因为 cell.getParagraphs() returns 是空的 List.

您的 setLink 方法最好如下所示:

...
 static void setLink(XWPFTableCell cell, String text, String link) {
  XWPFParagraph paragraph = cell.addParagraph();
  XWPFRun run = paragraph.createHyperlinkRun(link);
  run.setText(text);
  run.setUnderline(UnderlinePatterns.SINGLE);
  run.setColor("0000FF");
 }
...

字体大小的设置不应该在setLink里面完成。为此,您有 setFontSize。此方法还假定 XWPFTableCell 已经有段落。但这是真的,因为它是在将文本设置到单元格后调用的。

所以这两种方法都可以这样调用:

...
 XWPFTableCell desCell = desRow.getCell(col);
 setLink(desCell, text, encURL);
 setFontSize(desCell, 6);
...