杰瑞科技汇

excel 转 html java

方法概览

方法 核心库 优点 缺点 适用场景
Apache POI SXSSF (.xlsx)
HSSF (.xls)
功能强大,控制力强,是 Java 操作 Office 的标准库。 代码相对繁琐,需要手动处理样式、合并单元格等细节。 需要精细控制转换过程,处理复杂格式,或已有 POI 项目。
EasyExcel EasyExcel (阿里巴巴) 性能极高,内存占用极低(流式读取),API 简洁易用。 相对 POI 较年轻,但生态已非常成熟,社区活跃。 推荐首选,特别是处理大文件(百MB到GB级别)时。
JExcelApi / JXL jxl.jar 非常轻量,API 简单,适合简单的 Excel 读写。 已停止更新多年,不支持 .xlsx (OOXML) 格式,功能有限。 遗留项目或仅处理非常简单的 .xls 文件。

使用 Apache POI (功能最强大)

Apache POI 是最经典的 Java 操作 Office 文件的库,对于转换 HTML,我们需要结合 POI 来解析 Excel,然后自己构建 HTML 字符串。

excel 转 html java-图1
(图片来源网络,侵删)

添加 Maven 依赖

<dependencies>
    <!-- Apache POI for .xlsx files -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>5.2.5</version>
    </dependency>
    <!-- For .xls files (optional) -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>5.2.5</version>
    </dependency>
</dependencies>

核心思路

  1. 使用 FileInputStream 加载 Excel 文件。
  2. 根据文件版本(.xls.xlsx)创建相应的 Workbook 对象 (HSSFWorkbookXSSFWorkbook)。
  3. 遍历 Sheet
  4. 遍历 Row
  5. 遍历 Cell,获取单元格的值和样式(如字体、颜色、对齐方式)。
  6. 将获取到的信息拼接成 HTML 标签(如 <table>, <tr>, <td>, <span>)。

完整代码示例

这个示例会尽量保留 Excel 的基本样式,如加粗、字体颜色、背景色和单元格对齐。

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
public class PoiExcelToHtml {
    public static void main(String[] args) {
        String excelFilePath = "input.xlsx"; // 你的Excel文件路径
        String htmlOutputPath = "output.html"; // 生成的HTML文件路径
        try {
            convertExcelToHtml(excelFilePath, htmlOutputPath);
            System.out.println("转换成功!HTML文件已生成于: " + htmlOutputPath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void convertExcelToHtml(String excelFilePath, String htmlOutputPath) throws Exception {
        // 1. 加载Excel文件
        InputStream is = new FileInputStream(excelFilePath);
        Workbook workbook;
        if (excelFilePath.toLowerCase().endsWith(".xlsx")) {
            workbook = new XSSFWorkbook(is);
        } else if (excelFilePath.toLowerCase().endsWith(".xls")) {
            workbook = new HSSFWorkbook(is);
        } else {
            throw new IllegalArgumentException("不支持的文件格式,请使用 .xls 或 .xlsx 文件。");
        }
        // 2. 创建StringBuilder来构建HTML内容
        StringBuilder html = new StringBuilder();
        html.append("<html><head><meta charset=\"UTF-8\"><style>")
            .append("table { border-collapse: collapse; width: 100%; }")
            .append("th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }")
            .append("th { background-color: #f2f2f2; }")
            .append(".bold { font-weight: bold; }")
            .append(".italic { font-style: italic; }")
            .append(".bg-yellow { background-color: #ffff00; }")
            .append(".text-right { text-align: right; }")
            .append("</style></head><body>");
        // 3. 遍历所有Sheet
        for (int sheetIdx = 0; sheetIdx < workbook.getNumberOfSheets(); sheetIdx++) {
            Sheet sheet = workbook.getSheetAt(sheetIdx);
            html.append("<h2>").append(sheet.getSheetName()).append("</h2>");
            html.append("<table>");
            // 4. 遍历所有Row
            for (Row row : sheet) {
                html.append("<tr>");
                // 5. 遍历所有Cell
                for (Cell cell : row) {
                    html.append("<td");
                    // 处理单元格样式
                    CellStyle style = cell.getCellStyle();
                    if (style != null) {
                        // 对齐方式
                        switch (style.getAlignment()) {
                            case ALIGN_CENTER:
                                html.append(" style=\"text-align:center;\"");
                                break;
                            case ALIGN_RIGHT:
                                html.append(" style=\"text-align:right;\"");
                                break;
                        }
                        // 背景色
                        if (style.getFillForegroundColor() != IndexedColors.AUTOMATIC.getIndex()) {
                            byte[] rgb = style.getFillForegroundColorColor().getRGB();
                            String hexColor = String.format("#%02x%02x%02x", rgb[0], rgb[1], rgb[2]);
                            html.append(" style=\"background-color:").append(hexColor).append(";\"");
                        }
                    }
                    // 合并单元格处理(简化版,只处理rowspan和colspan逻辑较复杂,这里省略)
                    // CellRangeAddress region = sheet.getMergedRegion(row.getRowNum(), cell.getColumnIndex());
                    // if (region != null) { ... }
                    html.append(">");
                    // 处理单元格值
                    switch (cell.getCellType()) {
                        case STRING:
                            html.append(cell.getStringCellValue());
                            break;
                        case NUMERIC:
                            if (DateUtil.isCellDateFormatted(cell)) {
                                html.append(cell.getDateCellValue());
                            } else {
                                html.append(cell.getNumericCellValue());
                            }
                            break;
                        case BOOLEAN:
                            html.append(cell.getBooleanCellValue());
                            break;
                        case FORMULA:
                            html.append(cell.getCellFormula());
                            break;
                        default:
                            html.append("");
                    }
                    html.append("</td>");
                }
                html.append("</tr>");
            }
            html.append("</table>");
        }
        html.append("</body></html>");
        is.close();
        // 6. 将HTML内容写入文件
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(htmlOutputPath))) {
            writer.write(html.toString());
        }
    }
}

使用 EasyExcel (性能最好,推荐)

EasyExcel 是阿里巴巴开源的项目,它解决了 POI 在处理大文件时内存占用高的问题,它采用“一行一读”的流式 API,内存占用极小,虽然它没有直接提供 toHtml 方法,但其 API 更简洁,同样可以轻松实现转换。

添加 Maven 依赖

<dependencies>
    <!-- EasyExcel core dependency -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>easyexcel</artifactId>
        <version>3.3.2</version>
    </dependency>
</dependencies>

核心思路

EasyExcel 的核心是 ExcelReaderReadListener

  1. 创建一个 ExcelReaderBuilder 来指定文件路径。
  2. 创建一个自定义的 AnalysisEventListener (监听器)。
  3. 在监听器的 invoke 方法中,逐行处理数据,我们可以在这里构建 HTML 的 <tr><td> 部分。
  4. doAfterAllAnalysed 方法中,完成 HTML 的收尾工作(如 </table>, </body>)。

完整代码示例

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.read.metadata.ReadRow;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.read.metadata.ReadTable;
import org.apache.poi.ss.usermodel.*;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class EasyExcelToHtml {
    public static void main(String[] args) {
        String excelFilePath = "input.xlsx";
        String htmlOutputPath = "output_easyexcel.html";
        try {
            convertExcelToHtml(excelFilePath, htmlOutputPath);
            System.out.println("转换成功!HTML文件已生成于: " + htmlOutputPath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void convertExcelToHtml(String excelFilePath, String htmlOutputPath) throws IOException {
        // 1. 创建StringBuilder来构建HTML
        StringBuilder htmlBuilder = new StringBuilder();
        htmlBuilder.append("<html><head><meta charset=\"UTF-8\"><style>")
                   .append("table { border-collapse: collapse; width: 100%; }")
                   .append("th, td { border: 1px solid #ddd; padding: 8px; }")
                   .append("th { background-color: #f2f2f2; }")
                   .append("</style></head><body>");
        // 2. 使用EasyExcel读取文件
        // 这里我们假设只读取第一个Sheet
        EasyExcel.read(excelFilePath)
                .sheet() // 读取第一个Sheet
                .headRowNumber(0) // 假设第一行是标题行
                .registerReadListener(new CustomHtmlReadListener(htmlBuilder))
                .doRead();
        // 3. 完成HTML
        htmlBuilder.append("</body></html>");
        // 4. 写入文件
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(htmlOutputPath))) {
            writer.write(htmlBuilder.toString());
        }
    }
    /**
     * 自定义监听器,用于逐行处理Excel数据并构建HTML
     */
    private static class CustomHtmlReadListener extends AnalysisEventListener<List<String>> {
        private final StringBuilder htmlBuilder;
        private boolean isFirstRow = true;
        public CustomHtmlReadListener(StringBuilder htmlBuilder) {
            this.htmlBuilder = htmlBuilder;
        }
        @Override
        public void invoke(List<String> data, AnalysisContext context) {
            // EasyExcel 默认不处理样式,所以这里我们只处理数据
            // 如果需要处理样式,需要使用 POI 的方式,或者使用 EasyExcel 的高级API,但会复杂很多
            if (isFirstRow) {
                htmlBuilder.append("<table><thead><tr>");
                for (String header : data) {
                    htmlBuilder.append("<th>").append(header != null ? header : "").append("</th>");
                }
                htmlBuilder.append("</tr></thead><tbody>");
                isFirstRow = false;
            } else {
                htmlBuilder.append("<tr>");
                for (String cellValue : data) {
                    htmlBuilder.append("<td>").append(cellValue != null ? cellValue : "").append("</td>");
                }
                htmlBuilder.append("</tr>");
            }
        }
        @Override
        public void doAfterAllAnalysed(AnalysisContext context) {
            htmlBuilder.append("</tbody></table>");
        }
    }
}

注意:EasyExcel 的监听器模式更侧重于数据读取,获取样式信息比 POI 复杂,如果对样式还原要求不高,EasyExcel 是最简单高效的选择,如果样式要求严格,建议使用 POI。

excel 转 html java-图2
(图片来源网络,侵删)

使用 JExcelApi (轻量级,但已过时)

这个库非常轻量,API 也简单,但已经很久没有更新了,不支持现代的 .xlsx 格式。

添加 Maven 依赖 (可能需要手动安装 JXL JAR)

<dependency>
    <groupId>net.sourceforge.jexcelapi</groupId>
    <artifactId>jxl</artifactId>
    <version>2.6.12</version>
</dependency>

完整代码示例

import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;
import java.io.File;
import java.io.IOException;
public class JxlExcelToHtml {
    public static void main(String[] args) {
        String excelFilePath = "input.xls"; // 注意:JXL只支持.xls
        String htmlOutputPath = "output_jxl.html";
        try {
            convertExcelToHtml(excelFilePath, htmlOutputPath);
            System.out.println("转换成功!HTML文件已生成于: " + htmlOutputPath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void convertExcelToHtml(String excelFilePath, String htmlOutputPath) throws IOException, WriteException {
        Workbook workbook = Workbook.getWorkbook(new File(excelFilePath));
        StringBuilder html = new StringBuilder();
        html.append("<html><head><meta charset=\"UTF-8\"></head><body><table>");
        for (int sheetIdx = 0; sheetIdx < workbook.getNumberOfSheets(); sheetIdx++) {
            Sheet sheet = workbook.getSheet(sheetIdx);
            html.append("<h2>").append(sheet.getName()).append("</h2>");
            for (int i = 0; i < sheet.getRows(); i++) {
                html.append("<tr>");
                for (int j = 0; j < sheet.getColumns(); j++) {
                    Cell cell = sheet.getCell(j, i);
                    html.append("<td>").append(cell.getContents()).append("</td>");
                }
                html.append("</tr>");
            }
        }
        html.append("</table></body></html>");
        workbook.close();
        try (java.io.BufferedWriter writer = new java.io.BufferedWriter(new java.io.FileWriter(htmlOutputPath))) {
            writer.write(html.toString());
        }
    }
}

总结与最佳实践

  1. 首选推荐EasyExcel

    • 理由:性能卓越,API 简洁,内存占用低,适合处理任何大小的 Excel 文件,对于大多数不需要精确还原样式的场景,它是最佳选择。
  2. 精细控制Apache POI

    • 理由:功能最全面,对 Excel 的还原度最高,可以精确控制每一个单元格的样式、字体、颜色、边框、合并单元格等,如果你的业务要求高度还原 Excel 的外观,或者你已经在使用 POI,那么它是唯一的选择。
  3. 避免使用JExcelApi

    • 理由:技术陈旧,不支持 .xlsx 格式,社区不活跃,除非在维护一个非常古老的遗留项目,否则不建议使用。

最终建议: 如果你的项目是新的,或者对性能有要求,毫不犹豫地选择 EasyExcel,如果你需要将一个复杂的 Excel 报告原封不动地转换成网页展示,那么使用 Apache POI 会更可靠。

分享:
扫描分享到社交APP
上一篇
下一篇