1. 概述

在处理Microsoft Excel文件时,从不同单元格读取值可能会有些棘手。Excel文件是按照行和单元格组织的数据表,其中可以包含字符串、数字、日期、布尔值甚至公式。Apache POI 是一个库,提供了全面的工具来处理各种Excel文件和值类型。

本教程将重点学习如何处理Excel文件,遍历行和单元格,并了解正确读取每个单元格值类型的方法。

2. Maven依赖

首先,我们在pom.xml中添加Apache POI的依赖:

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.2.5</version>
</dependency>

Apache POI的最新版本 [poi-ooxml](https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml) 可以在Maven中央仓库找到。

3. Apache POI概述

整个层次结构从工作簿开始,它代表整个Excel文件。每个文件可以包含一个或多个工作表,它们是行和单元格的集合。根据Excel文件的版本,HSSF是表示旧版Excel文件(.xls*)的类的前缀,而XSSF用于最新版本(.xlsx)。* 因此我们有:

  • XSSFWorkbookHSSFWorkbook 类代表Excel工作簿
  • Sheet 接口代表Excel工作表
  • Row 接口代表行
  • Cell 接口代表单元格

3.1. 处理Excel文件

首先,我们打开要读取的文件并将其转换为FileInputStream以便进一步处理。FileInputStream构造函数会抛出java.io.FileNotFoundException,所以我们需要用try-catch块包裹它,并在最后关闭流:

public static void readExcel(String filePath) {
    File file = new File(filePath);
    try {
        FileInputStream inputStream = new FileInputStream(file);
        ...
        inputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

3.2. 遍历Excel文件

成功打开InputStream后,是时候创建XSSFWorkbook,并遍历每个工作表的行和单元格。如果我们知道确切的工作表数量或特定工作表的名称,我们可以使用XSSFWorkbookgetSheetAt(int index)getSheet(String sheetName)方法。

由于我们要阅读任何类型的Excel文件,我们将使用三个嵌套的for循环,一个用于工作表,一个用于每个工作表的行,最后一个是每个工作表的单元格。

为了简化教程,我们将只将数据打印到控制台:

FileInputStream inputStream = new FileInputStream(file);
Workbook baeuldungWorkBook = new XSSFWorkbook(inputStream);
for (Sheet sheet : baeuldungWorkBook) {
...
}

然后,为了遍历工作表的行,我们需要找到第一行和最后一行的索引,这些信息来自工作表对象:

int firstRow = sheet.getFirstRowNum();
int lastRow = sheet.getLastRowNum();
for (int index = firstRow + 1; index <= lastRow; index++) {
    Row row = sheet.getRow(index);
}

最后,我们也对单元格做同样的操作。在访问每个单元格时,我们可以选择传递一个MissingCellPolicy,它基本上告诉POI当单元格值为空或null时返回什么。MissingCellPolicy枚举包含三个枚举值:

  • RETURN_NULL_AND_BLANK
  • RETURN_BLANK_AS_NULL
  • CREATE_NULL_AS_BLANK;

单元格迭代的代码如下:

for (int cellIndex = row.getFirstCellNum(); cellIndex < row.getLastCellNum(); cellIndex++) {
    Cell cell = row.getCell(cellIndex, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
    ...
}

3.3. 读取Excel单元格值

如前所述,Microsoft Excel的单元格可以包含不同的值类型,因此能够区分不同单元格的值类型并使用适当的方法提取值非常重要。以下是所有值类型列表:

  • NONE
  • NUMERIC
  • STRING
  • FORMULA
  • BLANK
  • BOOLEAN
  • ERROR

我们将关注四种主要的单元格值类型:NumericStringBooleanFormula,其中Formula包含前三者的计算结果。

让我们创建一个辅助方法,该方法基本上会检查每个值类型,并根据此使用适当的方法获取值。也可以将单元格值视为字符串并使用相应的方法检索

有两个重要的注意事项。首先,日期值作为Numeric值存储,而且如果单元格的值类型是FORMULA,我们需要使用getCachedFormulaResultType()而不是getCellType()方法来检查公式计算的结果

public static void printCellValue(Cell cell) {
    CellType cellType = cell.getCellType().equals(CellType.FORMULA)
      ? cell.getCachedFormulaResultType() : cell.getCellType();
    if (cellType.equals(CellType.STRING)) {
        System.out.print(cell.getStringCellValue() + " | ");
    }
    if (cellType.equals(CellType.NUMERIC)) {
        if (DateUtil.isCellDateFormatted(cell)) {
            System.out.print(cell.getDateCellValue() + " | ");
        } else {
            System.out.print(cell.getNumericCellValue() + " | ");
        }
    }
    if (cellType.equals(CellType.BOOLEAN)) {
        System.out.print(cell.getBooleanCellValue() + " | ");
    }
}

现在,我们只需要在单元格循环中调用printCellValue方法就完成了。下面是完整代码的片段:

...
for (int cellIndex = row.getFirstCellNum(); cellIndex < row.getLastCellNum(); cellIndex++) {
    Cell cell = row.getCell(cellIndex, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
    printCellValue(cell);
}
...

4. 结论

在这篇文章中,我们展示了一个使用Apache POI读取Excel文件并访问不同单元格值的示例项目。

完整的源代码可以在GitHub上找到