方法概览
| 方法 | 核心库 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 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 字符串。

添加 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>
核心思路
- 使用
FileInputStream加载 Excel 文件。 - 根据文件版本(
.xls或.xlsx)创建相应的Workbook对象 (HSSFWorkbook或XSSFWorkbook)。 - 遍历
Sheet。 - 遍历
Row。 - 遍历
Cell,获取单元格的值和样式(如字体、颜色、对齐方式)。 - 将获取到的信息拼接成 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 的核心是 ExcelReader 和 ReadListener。
- 创建一个
ExcelReaderBuilder来指定文件路径。 - 创建一个自定义的
AnalysisEventListener(监听器)。 - 在监听器的
invoke方法中,逐行处理数据,我们可以在这里构建 HTML 的<tr>和<td>部分。 - 在
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。

使用 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());
}
}
}
总结与最佳实践
-
首选推荐:EasyExcel。
- 理由:性能卓越,API 简洁,内存占用低,适合处理任何大小的 Excel 文件,对于大多数不需要精确还原样式的场景,它是最佳选择。
-
精细控制:Apache POI。
- 理由:功能最全面,对 Excel 的还原度最高,可以精确控制每一个单元格的样式、字体、颜色、边框、合并单元格等,如果你的业务要求高度还原 Excel 的外观,或者你已经在使用 POI,那么它是唯一的选择。
-
避免使用:JExcelApi。
- 理由:技术陈旧,不支持
.xlsx格式,社区不活跃,除非在维护一个非常古老的遗留项目,否则不建议使用。
- 理由:技术陈旧,不支持
最终建议: 如果你的项目是新的,或者对性能有要求,毫不犹豫地选择 EasyExcel,如果你需要将一个复杂的 Excel 报告原封不动地转换成网页展示,那么使用 Apache POI 会更可靠。
