我想从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的情况下迭代所有非空行?现在(有了休息)我的算法正常工作 - 我正在获取我需要的数据。我只是想知道是否可以编写没有break
或continue
的代码。
答案 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
的情况下退出循环:
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
。这不是那么糟糕。
答案 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