当前位置: 首页 > 知识库问答 >
问题:

Java Apache POI——是否有可能获得比getCellType方法返回的更详细的单元格类型?

鲁熙云
2023-03-14

我正在验证一个Excel电子表格。我想确保特定列中的所有单元格存储相同的数据类型。

为此,我对行进行迭代,然后收集getCellType方法返回的一组CellType。一旦我有了这样的集合,我就可以确保集合只有一个项,以及它是否是预期的类型。

问题

不幸的是,ApachePOI CellType非常通用。例如,NUMERIC用于整数和日期类型。它们也不能提供字段大小的信息。此外,我注意到有时日期被识别为字符串

我的问题是:

  • 我应该尝试创建我自己的更具体的单元格类型的枚举,并尝试解析单元格内容作为这些枚举之一(这个解决方案似乎是一个重大的瓶颈/可能会减慢我的测试),
  • 或者在ApachePOI中是否有其他方法可以替代,
  • 或者我应该应用不同的库来解决我的问题?

共有1个答案

朱天逸
2023-03-14

您观察到的并不是apache poi的缺点,而是Excel存储单元格内容的方式。在Excel中,只有字符串数值布尔错误公式类型的单元格。数字单元格是否包含日期仅由单元格的数字格式决定。如果单元格是日期格式,那么它将数字显示为日期,否则不显示。如果单元格的类型为String,但字符串看起来像日期,那么即使是Excel也不会自动将该内容作为日期处理。

因此,唯一的方法是确定不同的单元内容,如《忙碌的开发人员HSSF和XSSF功能指南——获取单元内容》所示。主要根据细胞类型进行分化。对于Numeric单元格类型,通过DateUtil进行额外区分。iCellDateFormatted。对于公式单元格,您可能还需要获得公式的结果类型。

完整示例,读取样本第一页的所有单元格。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();

 }
}
 类似资料:
  • 我正在使用Appium Java客户端为Sam's Club Android应用程序编写自动化。 在项目详细信息屏幕上,有一个价格字段。我正在尝试获得价格价值。问题是没有该要素的案文。 我查看了页面源并搜索了一下,看看是否有一个价格值在任何地方--但它似乎不存在于页面源的任何地方。 它的效果很好,我可以通过这种方式获得价值,但感觉我在这里做了一些矫枉过正。有更好的方法吗?

  • 问题内容: 假设我有一个.class文件,可以获取该类中包含的所有方法吗? 问题答案: 要了解所有方法,请在控制台中使用以下语句: 要么 或例如:

  • 我正在运行一个由20个节点组成的kubernetes群集。命名空间中的一个pod被重新启动。该吊舱因出口代码为137的OOM而死亡,并按预期重新启动。但我想知道pod之前运行的节点。有什么地方可以查一下日志来了解信息吗?像蒂勒,库贝勒,库贝勒等等。。。

  • 那也许我可以 还是这是不可能的?也许只有在编译时了解了所有的信息,您才能做这种事情?

  • 我有一个实用函数,它从您的数组中返回一个值。但是,您的数组显然可以包含任何类型的元素,那么如何记录返回类型是混合的呢? 在PHPdoc中,我将使用: JSDoc等价物是什么?

  • 问题内容: 我使用反射将包中的每个方法都获取了,然后根据每个方法的返回类型,我想执行一些操作。但不幸的是,我在收藏方面遇到了问题。当我找到一种方法来返回诸如List之类的集合时,我找不到找到有关List元素类型的方法。我使用下面的代码来获取方法的返回类型。 上面的代码运行良好,并获得了所有返回List的方法,但它只是将java.util.List作为返回类型返回,而我找不到找到了解该List中元素