Java 读取 Excel 2007 文件
在 Java 中读取 Excel 2007 (.xlsx) 文件,可以使用 Apache POI 库,以下是详细的实现方法:

添加依赖
确保你的项目中包含 Apache POI 的依赖,如果你使用 Maven,添加以下依赖到 pom.xml:
<dependencies>
<!-- Apache POI for Excel 2007+ -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
</dependencies>
基本读取代码示例
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;
import java.io.IOException;
public class ExcelReader {
public static void main(String[] args) {
String filePath = "path/to/your/file.xlsx";
try (FileInputStream fis = new FileInputStream(filePath);
Workbook workbook = new XSSFWorkbook(fis)) {
// 获取第一个工作表
Sheet sheet = workbook.getSheetAt(0);
// 遍历每一行
for (Row row : sheet) {
// 遍历每一列
for (Cell cell : row) {
// 根据单元格类型获取值
switch (cell.getCellType()) {
case STRING:
System.out.print(cell.getStringCellValue() + "\t");
break;
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
System.out.print(cell.getDateCellValue() + "\t");
} else {
System.out.print(cell.getNumericCellValue() + "\t");
}
break;
case BOOLEAN:
System.out.print(cell.getBooleanCellValue() + "\t");
break;
case FORMULA:
System.out.print(cell.getCellFormula() + "\t");
break;
default:
System.out.print("\t");
}
}
System.out.println();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
更实用的封装方法
以下是一个更实用的方法,可以将 Excel 数据读取为二维列表:
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class ExcelReaderUtil {
public static List<List<Object>> readExcel(String filePath) throws IOException {
List<List<Object>> data = new ArrayList<>();
try (FileInputStream fis = new FileInputStream(filePath);
Workbook workbook = new XSSFWorkbook(fis)) {
Sheet sheet = workbook.getSheetAt(0);
for (Row row : sheet) {
List<Object> rowData = new ArrayList<>();
for (Cell cell : row) {
rowData.add(getCellValue(cell));
}
data.add(rowData);
}
}
return data;
}
private static Object getCellValue(Cell cell) {
switch (cell.getCellType()) {
case STRING:
return cell.getStringCellValue();
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
return cell.getDateCellValue();
} else {
return cell.getNumericCellValue();
}
case BOOLEAN:
return cell.getBooleanCellValue();
case FORMULA:
return cell.getCellFormula();
case BLANK:
return null;
default:
return null;
}
}
public static void main(String[] args) {
try {
List<List<Object>> excelData = ExcelReaderUtil.readExcel("example.xlsx");
// 打印数据
for (List<Object> row : excelData) {
for (Object cell : row) {
System.out.print(cell + "\t");
}
System.out.println();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
处理大文件(使用 SAX 模式)
对于非常大的 Excel 文件,可以使用 SAX 模式(事件驱动)来节省内存:
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.eventusermodel.XSSFReader.SheetIterator;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class LargeExcelReader {
public static void main(String[] args) throws IOException, InvalidFormatException {
String filePath = "large_file.xlsx";
try (FileInputStream fis = new FileInputStream(filePath)) {
XSSFReader reader = new XSSFReader(fis);
SharedStringsTable sst = reader.getSharedStringsTable();
XMLReader parser = XMLReaderFactory.createXMLReader();
parser.setContentHandler(new SheetHandler(sst));
SheetIterator sheets = (SheetIterator) reader.getSheetsData();
while (sheets.hasNext()) {
InputStream sheet = sheets.next();
InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource);
sheet.close();
}
}
}
private static class SheetHandler extends DefaultHandler {
private SharedStringsTable sst;
private String cellContents;
private boolean nextIsString;
private List<List<String>> sheetData = new ArrayList<>();
private List<String> currentRow = new ArrayList<>();
public SheetHandler(SharedStringsTable sst) {
this.sst = sst;
}
@Override
public void startElement(String uri, String localName, String name, Attributes attributes) {
if (name.equals("c")) {
String cellType = attributes.getValue("t");
if (cellType != null && cellType.equals("s")) {
nextIsString = true;
} else {
nextIsString = false;
}
cellContents = "";
}
}
@Override
public void characters(char[] ch, int start, int length) {
cellContents += new String(ch, start, length);
}
@Override
public void endElement(String uri, String localName, String name) {
if (name.equals("v")) {
if (nextIsString) {
int idx = Integer.parseInt(cellContents);
currentRow.add(new XSSFRichTextString(sst.getItemAt(idx)).getString());
} else {
currentRow.add(cellContents);
}
} else if (name.equals("row")) {
sheetData.add(currentRow);
currentRow = new ArrayList<>();
}
}
}
}
注意事项
- 内存管理:对于大文件,考虑使用 SAX 模式或分块读取
- 错误处理:添加适当的异常处理
- 性能:频繁的文件 I/O 操作会影响性能,考虑缓存或批量处理
- 日期格式:Excel 中的日期可能需要特殊处理
- 公式计算:如果需要读取公式的计算结果,可以使用
FormulaEvaluator
代码提供了从简单到复杂的多种读取 Excel 2007 文件的方法,你可以根据实际需求选择合适的实现方式。


