如何不使用break或continue语句迭代所有非空行?

时间:2016-03-30 08:57:28

标签: java apache apache-poi

我想从Excel文件中获取数据。我正在使用while循环,迭代器和hasNext()方法来遍历所有行。 我的问题:有时在有数据的行之后有空行(可能是单元格类型字符串和值“”或null),我不想迭代。 所以我添加了方法isCellEmpty()

public static boolean isCellEmpty(final Cell cell) {
    if (cell == null || cell.getCellType() == Cell.CELL_TYPE_BLANK) {
        return true;
    }
    if (cell.getCellType() == Cell.CELL_TYPE_STRING && cell.getStringCellValue().isEmpty()) {
        return true;
    }
    return false;
}

并在主方法中循环播放后添加它:

while (rowIterator.hasNext()) {
    row = rowIterator.next();
    if (isCellEmpty(row.getCell(2))) {
        break;
    }
    // some code ...
}

但现在我有一个休息声明。如何在不使用break或continue的情况下迭代所有非空行?现在(有了休息)我的算法正常工作 - 我正在获取我需要的数据。我只是想知道是否可以编写没有breakcontinue的代码。

7 个答案:

答案 0 :(得分:4)

如果你想保持你的while循环,并避免休息,最简单的可能是状态布尔值,例如

boolean inData = true;
while (rowIterator.hasNext() && inData) {
   row = rowIterator.next();
   if (row == null || isCellEmpty(row.getCell(2))) {
      inData = false;
   } else {
      // Use the row
   }
}

否则,我建议reading the Apache POI documentation on iterating over rows and cells,您可以采取其他可能更好的方法!

哦,不要忘记行可以是null,因此您需要在尝试获取单元格之前检查它

答案 1 :(得分:2)

看起来POI没有任何调整或功能来迭代非空行。

他们已经提到了这个主题。查看Apache POI HSSF+XSSF部分迭代行和单元格遍历单元格,控制缺失/空白单元格

我没有实现 whiles 循环,而是使用 Apache Commons 。由于POI适用于迭代器,您可以使用Apache IteratorUtils

这个 Utils 附带了 Apache-common-collections ,它可能在你的类路径中,因为它很常见,因为它是第三方lib的依赖。< / p>

为了使您的代码清洁和礼貌。这将是解决方案

import org.apache.commons.collections.Predicate;

public class ValidRowPredicate implements Predicate{
    @Override
    public boolean evaluate(Object object) {
       Row row = (Row) object;
       Cell cell = row.getCell(2);
       if (cell == null || cell.getCellType() == Cell.CELL_TYPE_BLANK) {
          return false;
       } else if (cell.getCellType() == Cell.CELL_TYPE_STRING && 
                  cell.getStringCellValue().isEmpty()) {
         return false;
      }
      return true;
    }
}

然后在你的主要代码中:

Iterator<Row> rawIterator = rowIterator;
Iterator<Row> cleanIterator = IteratorUtils.filteredIterator(rawIterator , new ValidRowPredicate());

while(cleanIterator.hasNext()){
   Row row = cleanIterator.next();
   // some code
} 

你可能会在书上循环2次。不,我们不是。第一个循环可以,但是进一步的迭代是在有效行的子集上。看看它的好处。通过这种方式,我们使可移植验证空单元格2 ,以便我们可以在代码中的任何位置随时重现它。

我们还有一个有效的 Iterator,它只有 有效行,因此我不需要担心空白或空白。我们可以通过任何其他组件或层移动此迭代器,我们将确保目标不需要再次检查它。

Predicates 提供了很多可能性。就像通过继承链接Predicats一样,独立执行谓词,可以参数化,...

它的成本实际上是整个主Iterator的第一个循环。但结果值得。

IteratorUtils 作为 CollectionUtils 非常好 utils ,我们经常进入我们的类路径,没有人敢用它。问题是为什么不

希望它有所帮助!

答案 2 :(得分:1)

我不确定问题是否正确,您是否正在寻找类似的内容?

Row row;
while (rowIterator.hasNext() 
          && !isCellEmpty((row = rowIterator.next()).getCell(2))) {
    // do something with row
}

这将处理所有行,直到找到一个空单元格并结束循环。

答案 3 :(得分:1)

有几个选项可以在不使用break的情况下退出循环:

  • 使用其他一些控制流程,例如: returnthrow;
  • 为循环保护添加额外条件:

    boolean shouldContinue = true;
    while (shouldContinue && rowIterator.hasNext()) {
      row = rowIterator.next();
      if (isCellEmpty(...)) {
        shouldContinue = false;
      }
    }
    
  • 排出循环体内的迭代器:

    while (rowIterator.hasNext()) {
      row = rowIterator.next();
      if (isCellEmpty(...)) {
        while (rowIterator.hasNext()) rowIterator.next();
      }
    }
    

或者只使用break。这不是那么糟糕。

答案 4 :(得分:0)

  

更改您的功能isCellEmpty()使用switch而不是nested if-else

public static boolean isCellEmpty(final Cell cell) {
   switch(cell.getCellType()){
       case Cell.CELL_TYPE_BLANK :
       case cell.CELL_TYPE_STRING :
          if(StringUtils.isBlank(cell.getCellValue())
               return true;
          else
               return false;
         break;
       default :
               return false;
     break;               
   }

}

现在使用此代码

boolean hasCellData= true;
while (rowIterator.hasNext() && hasCellData) {
   row = rowIterator.next();  //iterate through each rows.
   if (row == null || isCellEmpty(row.getCell(2))) {
      hasData = false;
   } else {
      //if row contains data then do your stuffs.
   }
}

如果某行包含while (rowIterator.hasNext() && hasCellData)值,则此null循环将在某个时间点停止。它永远不会检查这行之外是否有一些数据。

  

示例: - 假设在您的工作表数据中从第1行填充到第50行,但在它们之间有一个第30行,它是空白的,然后在第30行之后不会迭代。

感谢。

答案 5 :(得分:0)

可能过于简单,但下列内容是否足够?

while (rowIterator.hasNext()) {
    row = rowIterator.next();
    if (!isCellEmpty(row.getCell(2))) {
        // some code ...
    }
}

如果我们想要在遇到空行/单元格时停止迭代,可以采取以下方法:

for(boolean shouldContinue = true; shouldContinue && rowIterator.hasNext(); ) {
   if (!isCellEmpty(row.getCell(2))) {
        // some code ...
    } else {
        shouldContinue = false;
    }
}

答案 6 :(得分:0)

能够根据莱夫的答案删除空行。我已修改为支持传递行。这是修改后的答案

with open(file_path, 'rb') as fh:
    response = HttpResponse(fh.read(), content_type="application/force-download")
    response['Content-Disposition'] = 'inline; filename=' + os.path.basename(file_path)
    return response

信用归Laiv