我正在验证 Excel 电子表格。我想确保特定列中的所有单元格存储相同的数据类型。
为此,我迭代行,然后收集一组 CellType由 getCellType 方法返回。一旦我有了这样的集合,我就可以确保该集合只有一项以及它是否是预期的类型。
<小时/>问题
不幸的是,Apache POI CellType 非常通用。例如,NUMERIC 用于整数和日期类型。他们也不向我提供有关 field 大小的信息。 此外,我注意到有时日期被识别为字符串。
我的问题是:
- 我是否应该尝试创建自己的更具体细胞类型的枚举,并尝试将单元格内容解析为这些枚举之一(此解决方案似乎是一个重大瓶颈/可能会减慢我的测试速度),
- 或者 Apache POI 中是否有其他我应该使用的方法,
- 或者我应该应用不同的库来解决我的问题吗?
最佳答案
您所观察到的不是 apache poi
的缺点,而是 Excel
存储单元格内容的方式。仅存在 String
、Numeric
、Boolean
、Error
或 Formula
类型的单元格在 Excel
中。数字单元格是否包含日期仅由单元格的数字格式决定。如果单元格的格式为日期,则它会将数字显示为日期,否则不会。如果单元格的类型为 String
,但该字符串看起来像日期,则即使 Excel
也不会自动将该内容作为日期处理。
因此唯一的方法是确定不同的单元格内容,如Busy Developers' Guide to HSSF and XSSF Features - Getting the cell contents所示。主要按细胞类型来区分。对于Numeric
单元格类型,通过DateUtil.isCellDateFormatted
进行额外区分。对于公式单元格,您可能还需要获取 result type of the formula .
完整示例,读取 SAMPLE.xlsx
第一页的所有单元格并尽可能准确地确定单元格类型。
import java.io.FileInputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.ss.usermodel.CellType;
class ReadExcelExample {
public static void main(String[] args) throws Exception {
Workbook wb = WorkbookFactory.create(new FileInputStream("SAMPLE.xlsx"));
Sheet sheet = wb.getSheetAt(0);
for (Row row : sheet) {
for (Cell cell : row) {
CellReference cellRef = new CellReference(row.getRowNum(), cell.getColumnIndex());
System.out.print(cellRef.formatAsString() + " ");
//switch (cell.getCellTypeEnum()) { // until apache poi 3.17
switch (cell.getCellType()) { // from apache poi 4.0.0
case STRING:
System.out.println("is a string cell: " + cell.getRichStringCellValue().getString());
break;
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
System.out.println("is a date cell: " + cell.getDateCellValue());
} else {
System.out.println("is a numeric cell: " + cell.getNumericCellValue());
}
break;
case BOOLEAN:
System.out.println("is a boolean cell: " + cell.getBooleanCellValue());
break;
case FORMULA:
System.out.print("is a formula cell: " + cell.getCellFormula());
//switch (cell.getCachedFormulaResultTypeEnum()) { // until apache poi 3.17
switch (cell.getCachedFormulaResultType()) { // from apache poi 4.0.0
case STRING:
System.out.println(" returning a string: " + cell.getRichStringCellValue().getString());
break;
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
System.out.println(" returning a date: " + cell.getDateCellValue());
} else {
System.out.println(" returning a number: " + cell.getNumericCellValue());
}
break;
case BOOLEAN:
System.out.println(" returning an boolean: " + cell.getBooleanCellValue());
break;
case ERROR:
System.out.println(" returning an error: " + cell.getErrorCellValue());
break;
default:
System.out.println("default formula cell"); //should never occur
}
break;
case ERROR:
System.out.println("is a error cell: " + cell.getErrorCellValue());
break;
case BLANK:
System.out.println("is a blank cell");
break;
default:
System.out.println("default cell"); //should never occur
}
}
}
wb.close();
}
}
关于Java Apache POI - 是否可以获得比 getCellType 方法返回的更详细的单元格类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59580640/