Apache POI excel导出(单元格html代码渲染)

发布时间 2023-07-24 17:42:15作者: IamHzc

需求:将渲染后的html代码,导出到单元格中。

代码实现

public class ExcelUtil {

    /**
     * 设置单元格富文本值
     */
    public static void setCellRichTextString(Workbook wb, Cell cell, Object obj, boolean isHead){
        if(obj == null){
            cell.setCellValue(StringPool.EMPTY);
            return;
        }
        String htmlCode = (String) obj;
        Document document = Jsoup.parse(htmlCode);
        //获取html文本内容
        StringBuilder htmlCodeStrSb = new StringBuilder();
        //前端特殊字符组件每个<p>标签为一行
        Elements allP = document.select("p");
        for (Element p : allP) {
            htmlCodeStrSb.append(p.text());
            htmlCodeStrSb.append("\n");
        }
        htmlCodeStrSb.deleteCharAt(htmlCodeStrSb.length() - 1);
        //对于表格头不需要进行字体样式渲染
        if(isHead){
            cell.setCellValue(htmlCodeStrSb.toString());
            return;
        }
        //html转为RichTextString
        RichTextString richTextString = ExcelUtil.convertToRichTextString(wb, document.body(), htmlCodeStrSb.toString());
        cell.setCellValue(richTextString);

    }



    public static RichTextString convertToRichTextString(Workbook workbook, Element element, String htmlCode) {
        RichTextString richTextString = new HSSFRichTextString(htmlCode);
        int startIndex = 0;
        for (Node node : element.childNodes()) {
            Font font = workbook.createFont();
            startIndex = applyFontRecursive(workbook, richTextString, node, startIndex, font);
        }
        return richTextString;
    }

    public static int applyFontRecursive(Workbook workbook, RichTextString richTextString,
                                         Node node, int startIndex, Font parentFont) {
        if (node instanceof TextNode) {
            TextNode textNode = (TextNode) node;
            String text = textNode.getWholeText();
            if (!text.isEmpty()) {
                startIndex = startIndex + text.length();
            }
        } else if (node instanceof Element) {
            Element childElement = (Element) node;
            String tagName = childElement.tagName();
            Font font = copyFont(workbook, parentFont);
            switch (tagName) {
                case "strong": //加粗
                    font.setBold(true);
                    break;
                case "em": //斜体
                    font.setItalic(true);
                    break;
                case "sup": //上标
                    font.setTypeOffset(Font.SS_SUPER);
                    break;
                case "sub": //下标
                    font.setTypeOffset(Font.SS_SUB);
                    break;
                case "span":
                    String style = childElement.attr("style");
                    if(StringUtils.isNotBlank(style)) {
                        if (style.contains("text-decoration: line-through;")) {  //水平删除斜线
                            font.setStrikeout(true);
                        }
                        if (style.contains("text-decoration: underline;")) { //下划线
                            font.setUnderline(Font.U_SINGLE);
                        }
                    }
                default:
                    break;
            }
            richTextString.applyFont(startIndex, startIndex + ((Element) node).text().length(), font);
            for (Node childNode : childElement.childNodes()) {
                startIndex = applyFontRecursive(workbook, richTextString, childNode, startIndex, font);
            }
        }
        return startIndex;
    }

    /**
     * 拷贝字体
     */
    public static Font copyFont(Workbook workbook, Font font){
        Font copyFont = workbook.createFont();
        copyFont.setBold(font.getBold());
        copyFont.setItalic(font.getItalic());
        copyFont.setStrikeout(font.getStrikeout());
        copyFont.setUnderline(font.getUnderline());
        copyFont.setTypeOffset(font.getTypeOffset());
        return copyFont;
    }



}