我想从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循环后添加
while (rowIterator.hasNext()) {
row = rowIterator.next();
if (isCellEmpty(row.getCell(2))) {
break;
}
// some code ...
}
但现在我有一个中断声明。如何在不使用break或continue的情况下迭代所有非空行?现在(休息时)我的算法工作正常——我正在获取我需要的数据。我只是想知道是否可以在没有break
或continue
的情况下编写代码。
如果您想保持while
循环并避免中断,最简单的可能是状态布尔值,例如
boolean inData = true;
while (rowIterator.hasNext() && inData) {
row = rowIterator.next();
if (row == null || isCellEmpty(row.getCell(2))) {
inData = false;
} else {
// Use the row
}
}
否则,我建议阅读Apache POI关于在行和单元格上迭代的文档,您可以采取其他方法,这些方法可能会更好!
哦,别忘了行可以是null
,所以在尝试获取单元格
看起来POI没有任何特性或特性可以在非空行上迭代。
POIS的开发人员发布了关于这个主题的帖子。查看Apache POI HSSF+XSSF部分在行和单元格上迭代和单元格上迭代,并控制缺失/空白单元格
请注意,POI与Iterator一起工作,因此我将使用Apache Commons Collections中的Apache IteratorUtils,而不是循环,由于某些传递依赖关系,它可能已经在类路径中了。
为了使您的代码更干净、可读,该解决方案将类似于
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
}
您可能认为我们正在迭代book两次,但我们没有。
第一个循环确实如此,但进一步的迭代是在有效行的子集上进行的。此外,我们使可重复使用验证空单元格#2。我们还得到了一个可靠的迭代程序,它只有有效和可计算的条目。
谓词给出了很多可能性。类似于通过继承或组合链接谓词。
它的成本实际上是,第一个循环遍布主迭代程序。但结果是值得的。
IteratorUtils作为CollectionUtils是非常好的utils
不确定我是否答对了问题,你在找这样的东西吗?
Row row;
while (rowIterator.hasNext()
&& !isCellEmpty((row = rowIterator.next()).getCell(2))) {
// do something with row
}
这将处理所有行,直到找到一个空单元格并结束循环。
您有几个选项可以在不使用break
:的情况下退出循环
- 使用一些其他控制流,例如
return
、throw
为环路保护添加一个额外条件:
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
。还不错。
将函数
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.
}
}
如果一行包含null
值,则此while (rowIterator.hasNext() && hasCellData)
循环将在某个时间点停止。它从不检查此行之外是否有一些数据。
示例:-假设在工作表中,数据从第1行填充到第50行,但中间有一个第30行为空,则这不会在第30行之后重复。
谢谢。
可能过于简单,但以下内容还不够吗?
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;
}
}
能够根据Laiv的答案删除空行。我已经修改以支持通过Row。这是修改后的答案
import org.apache.commons.collections4.Predicate;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
public class ValidRowPredicate implements Predicate<Row> {
@Override
public boolean evaluate(Row row) {
Cell cell = row.getCell(2);
if (cell == null || cell.getCellType() == CellType.BLANK) {
return false;
} else if (cell.getCellType() == CellType.STRING &&
cell.getStringCellValue().isEmpty()) {
return false;
}
return true;
}
}
学分转到Laiv