【问题标题】:How to get an Excel Blank Cell Value in Apache POI?如何在 Apache POI 中获取 Excel 空白单元格值?
【发布时间】:2011-06-23 05:06:42
【问题描述】:

我有一个巨大的 excel 文件,其中包含大量列,如下所示:-

Column1 Column2 Column3 Column4 Column5
abc             def             ghi
        mno             pqr
......

这是我为打印这些值而编写的代码:

try {
    FileInputStream inputStr = new FileInputStream(fileName);
    XSSFWorkbook xssfWork = new XSSFWorkbook(inputStr) ;
    XSSFSheet sheet1 = xssfWork.getSheetAt(0);
    Iterator rowItr = sheet1.rowIterator();

    while ( rowItr.hasNext() ) {
        XSSFRow row = (XSSFRow) rowItr.next();
        System.out.println("ROW:-->");
        Iterator cellItr = row.cellIterator();

        while ( cellItr.hasNext() ) {
            XSSFCell cell = (XSSFCell) cellItr.next();
            System.out.println("CELL:-->"+cell.toString());
        }
    }
} catch (Exception e) {
    e.printStackTrace();
}

这段代码生成的输出是:-

ROW:-->
CELL:-->Column1
CELL:-->Column2
CELL:-->Column3
CELL:-->Column4
CELL:-->Column5
ROW:-->
CELL:-->abc
CELL:-->def
CELL:-->ghi
ROW:-->
CELL:-->mno
CELL:-->pqr

所以,如果我们查看上面的输出,我们可以注意到我留下空白值的单元格没有被 POI 库拾取,有没有办法可以将这些值设为 null。还是一种识别所显示的值跳过空白单元格的方法?

谢谢。

【问题讨论】:

    标签: java apache apache-poi


    【解决方案1】:
    for (Row row: sheet){
    // This will return null if cell is empty / blank
    Cell cell = row.getCell(columnNumber);
    }
    

    【讨论】:

      【解决方案2】:

      如果您想获取所有单元格,无论它们是否存在,那么迭代器不适合您。相反,您需要手动获取适当的单元格,可能缺少单元格策略

      for(Row row : sheet) {
         for(int cn=0; cn<row.getLastCellNum(); cn++) {
             // If the cell is missing from the file, generate a blank one
             // (Works by specifying a MissingCellPolicy)
             Cell cell = row.getCell(cn, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
             // Print the cell for debugging
             System.out.println("CELL: " + cn + " --> " + cell.toString());
         }
      }
      

      the Apache POI documentation on iterating over cells 有更多关于这一切的详细信息

      【讨论】:

      • row.getCell() 方法已弃用。
      • row.getCell(short) 已弃用。对不起。
      • 确实如此! POI 有大量的单元测试表明它工作得很好!
      • 在 POI 3.9 中,正确的语法似乎是 row.getCell(cn, Row.CREATE_NULL_AS_BLANK)。
      • 更新:Row.CREATE_NULL_AS_BLANK 应该是 MissingCellPolicy.CREATE_NULL_AS_BLANK
      【解决方案3】:
      public String[] rowToString(Row row)
      {
          Iterator<Cell> cells = row.cellIterator() ;
          String[] data = new String[row.getLastCellNum()] ;
      
          int previousCell = 0 ;
      
          Cell cell = cells.next() ;
          int currentCell = cell.getColumnIndex();
      
          while (true)
          {
              if (previousCell == currentCell) {
                  switch (cell.getCellType()) {
                      case Cell.CELL_TYPE_NUMERIC:
                          data[previousCell] = cell.getNumericCellValue()+"" ;
                          break;
                      case Cell.CELL_TYPE_STRING:
                          data[previousCell] = cell.getStringCellValue() ;
                          break;
                          /* // there could be other cases here.
                          case Cell.CELL_TYPE_FORMULA:
                              data[previousCell] =eval.evaluateFormulaCell(cell);
                              break;
                          case Cell.CELL_TYPE_BOOLEAN:
                              data[previousCell] = cell.getBooleanCellValue();
                              break;
                          case Cell.CELL_TYPE_BLANK:
                              data[previousCell] = "";
                              break;
                          case Cell.CELL_TYPE_ERROR:
                              data[previousCell] = "ERROR";
                              break;
                          */
                  }
                  if(cells.hasNext()){
                      cell = cells.next() ;
                      currentCell = cell.getColumnIndex();
                  } else {
                      break ;
                  }
      
              } else {
                  data[previousCell] = "";
              }
              previousCell++ ;
      
          }
      
          return data ;
      
      }
      

      【讨论】:

      • 请在您的答案中添加 cmets
      • 你应该在帖子中添加cmets和解释,另外,请看问题的年份
      • 此方法转换字符串数组中的 excel 行,而不跳过空白或空单元格值(在这种情况下,相应的数组值将只有一个空字符串)。
      【解决方案4】:
      List cellDataList = new ArrayList(); 
      
      int lineNumber = 0;   
      
      while (rowIterator.hasNext()) {
          HSSFRow hssfRow = (HSSFRow) rowIterator.next();
          //System.out.println("Befor If");
          lineNumber++;
          if(lineNumber==1){continue;}
          //System.out.println("Out side if ");
      
          Iterator<Cell> iterator = hssfRow.cellIterator();
          List<Cell> cellTempList = new ArrayList();
          int current = 0, next = 1;
          while (iterator.hasNext()) {
            Cell hssfCell = iterator.next();
            current = hssfCell.getColumnIndex();
      
            if(current<next){
                System.out.println("Condition Satisfied");
            }
            else{
                int loop = current-next;
                System.out.println("inside else Loop value : "+(loop));
                for(int k=0;k<loop+1;k++){
                   System.out.println("Adding nulls");
                   cellTempList.add(null);
                   next = next + 1;
                }
            }
      
            cellTempList.add(hssfCell);
      
            next = next + 1;
            System.out.println("At End  next value is : "+next);
        }
        cellDataList.add(cellTempList);
      }
      

      【讨论】:

        【解决方案5】:

        我对同样的问题感到沮丧。这是我在 poi-3.7-20101029 和 poi-3.8 中发现的。

        RowIterator 和 CellIterator 不支持对 NULL 单元格或行进行迭代 - 仅支持物理定义的单元格(可以为 BLANK)。

        返回我期望的解决方案需要使用基于 0 的 Row.getCell([int], Row.CREATE_NULL_AS_BLANK),就像 Chavira 的答案所暗示的那样(假设 8 个单元格行)。或者您可以在迭代时使用Cell.columnIndex 值来检查跳跃数字...

        令人讨厌的是,在使用方法 #1 创建空白单元格后,迭代器将返回现在创建的空白单元格。我认为 CellIterator 忽略 MissingCellPolicy 是一个错误。

        【讨论】:

        • 遇到了同样的问题,使用基于 0 的索引方法(不是通过 foreach)和 CREAT_NULL_AS_BLANK MissingRowPolicy 对我有用。
        【解决方案6】:

        原因很简单:Excel 文件可以包含尽可能多的行和列,因此返回所有可用的空白行和列将导致单元格巨大且占用大量内存。

        假设您有一个 10x10 的工作表,在 Excel 中,它不是“完全”的 10x10,因为您可以很容易地用空白单元格添加 11x10,那么 POI 是否应该返回第 11 列?

        执行您要求的一种方法是使用HSSFCell.getColumnIndex()

        例子:

        //Assuming your have a 2 dimensional array.
        String[][] values = ......;// It is assigned
        
        POIFSFileSystem fileSystem = new POIFSFileSystem(new FileInputStream(fileName));
        HSSFWorkbook workbook = new HSSFWorkbook(fileSystem);
        
        //Going through every worksheet.
        for (int sheetPos = 0; sheetPos < workbook.getNumberOfSheets(); sheetPos++) {
            HSSFSheet sheet = workbook.getSheetAt(sheetPos);
        
            int rowPos = 0;
            Iterator<Row> rows = sheet.rowIterator();
            while (rows.hasNext()) {
                HSSFRow row = (HSSFRow) rows.next();
        
                Iterator<Cell> cells = row.cellIterator();
                while (cells.hasNext()) {
                    HSSFCell cell = (HSSFCell) cells.next();
                    String value = "";
        
                    switch (cell.getCellType()) {
                        case HSSFCell.CELL_TYPE_NUMERIC:
                            value = BigDecimal.valueOf(cell.getNumericCellValue()).toPlainString();
                            break;
        
                        case HSSFCell.CELL_TYPE_STRING:
                            value = cell.getStringCellValue();
                            break;
        
                        case HSSFCell.CELL_TYPE_BLANK:
                            value = "";
                            break;
        
                        case HSSFCell.CELL_TYPE_FORMULA:
                            value = cell.getCellFormula();
                            break;
        
                        default:
                            break;
                    }
        
                    values[rowPos][cell.getColumnIndex()] = value;
                }
        
                rowPos++;
            }
        }
        

        【讨论】:

        • Row.getCell(int) 不推荐使用!不知道你为什么这么认为,但我可以向你保证,事实并非如此——请参阅JavaDocs 以获取证据。
        • @Gagravarr,抱歉,Row.getCell(short) 已弃用。
        【解决方案7】:

        这对我有用....

        int rowNumber;
        int previousCell;
        int currentCell;
        int currentRowNumber;
        HSSFCell cell;
        
        while (rows.hasNext()) {
            previousCell = -1;
            currentCell = 0;
            while (cellIterator.hasNext()) {
                cell = (HSSFCell) cellIterator.next();
                currentCell = cell.getColumnIndex();
                if (previousCell == currentCell-1)  {
                    //...
                }
                else {
                    System.out.println("Blank cell found");
                }
                previousCell = currentCell;
            }
        }
        

        【讨论】:

          【解决方案8】:

          以下是对我有用的。 “row.CREATE_NULL_AS_BLANK”似乎无效,但可能是缺乏 NPOI 知识。

          HSSFCell dataCell= (HSSFCell)row.GetCell(column, NPOI.SS.UserModel.MissingCellPolicy.CREATE_NULL_AS_BLANK);
          

          【讨论】:

          • 非营利组织?如果您使用的是 POI 的 .net 端口,那么任何数量的东西都可能不同;)
          【解决方案9】:
                  for(org.apache.poi.ss.usermodel.Row tmp : hssfSheet){
                      for(int i = 0; i<8;i++){
                          System.out.println(tmp.getCell(i));
                      }               
                  }
          

          【讨论】:

          • 他正在使用 XSSF 打开一个 XLSX 文件 (2007+)。 HSSF 不会解决他的问题。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多