我需要检查.xlsx文件中的列是否为空,但找不到比这更平滑的内容:
public static boolean isColumnEmpty(int column, int firstRow, XSSFSheet sheet) {
XSSFRow row = sheet.getRow(firstRow);
while (row != null) {
Cell c = row.getCell(column, Row.RETURN_BLANK_AS_NULL);
if (c != null) {
return false;
}
row = sheet.getRow(firstRow++);
}
return true;
}
firstRow
只是您想要开始的行(实际上我的列不是完全空的,还有一个标题)。
我想知道你们中有些人是否有更好的想法!
答案 0 :(得分:2)
答案取决于工作表中物理行的稀疏程度,编写简单代码的愿望,以及您对执行速度的关注程度。
三者的良好折衷只会循环通过物理行,只要startRow
比getFirstRowNum()
更接近getLastRowNum()
,就可以很好地执行。
public static boolean isColumnEmpty(Sheet sheet, int columnIndex, int startRow) {
for (Row row : sheet) {
if (row.getRowNum() < startRow) continue;
Cell cell = row.getCell(columnIndex, Row.RETURN_BLANK_AS_NULL);
if (cell != null) {
return false;
}
}
return true;
}
对于密集行的工作簿,您的代码更好。
对于工作量最少的代码,您可以将这两种方法结合起来(我更喜欢for
- 循环遍历while
- 循环,因为它可以更快地验证您的代码获胜&# 39;陷入无限循环中)
public static boolean isColumnEmpty(Sheet sheet, int columnIndex, int startRow) {
int firstRow = sheet.getFirstRowNum();
int lastRow = sheet.getLastRowNum();
// No need to check rows above the first row
startRow = Math.max(startRow, firstRow);
int numRows = sheet.getPhysicalNumberOfRows();
// Compute an estimate of the number of rows that each method
// will access.
// Assume the cost to access one row is the same
// between an explicit getRow() or through the rowIterator.
// Assume physical rows are uniformly spaced, which is unlikely true
// but the best estimate possible without iterating over the rows.
double rowDensity = (lastRow - firstRow + 1) / numRows;
double estimatedForEachLoopCost = numRows;
double estimatedForLoopCost = (lastRow - startRow) + 1) * rowDensity;
if (estimatedForEachLoopCost < estimatedForLoopCost) {
// for-each iteration
for (Row row : sheet) {
if (row.getRowNum() < startRow) continue;
Cell cell = row.getCell(columnIndex, Row.RETURN_BLANK_AS_NULL);
if (cell != null) {
return false;
}
}
return true;
} else {
for (int r=startRow; r<=lastRow; r++) {
Row row = sheet.getRow(r);
if (row == null) continue;
Cell cell = row.getCell(columnIndex, Row.RETURN_BLANK_AS_NULL);
if (cell != null) {
return false;
}
}
return true;
}
}
如果真的关心性能,您可以派生POI并编写一个方法来公开TreeMap<Integer, XSSFRow>
用于访问行的XSSFSheet
。
然后,您可以使用_rows.tailMap(startRow, inclusive=true)
访问最少的行数。
如果您在POI bugzilla上添加了一个补丁和测试用例,以获取从HSSF,XSSF和SXSSF返回java.util.Collections.unmodifiableSortedMap(_rows.subMap(startRow, true, endRow, true))
的方法(如果起始行或结束行在访问窗口之外,则会失败,或者使用列跟踪器类似于autosize column tracker),然后将isColumnEmpty函数添加到相应的类中,如果您的补丁被接受,则可以避免维护fork。