Apache POI:检查列是否为空

我需要检查列是否为空或不在.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只是你想要开始的行(实际上我的列不是完全空的,还有一个标题)。

我想知道你们有没有更好的主意?

答案的不同在于您的工作表中物理行的稀疏程度,您希望拥有简单的代码以及您关心执行速度的多less。

三者之间的一个很好的折中scheme只会循环遍历物理行,并且只要startRowgetLastRowNum()更接近getFirstRowNum()可以很好地执行。

 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; } 

对于密集行的工作簿,您的代码更好。

对于那些工作量最less的代码,可以将这两种方法结合起来(我更喜欢for -loops的while -loops,因为validation代码不会陷入无限循环)

 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,并写一个方法来暴露XSSFSheet用于访问行的TreeMap<Integer, XSSFRow> 。 然后你可以用_rows.tailMap(startRow, inclusive=true)访问最less的行数。

如果您在POI bugzilla中为HSSF,XSSF和SXSSF返回一个返回java.util.Collections.unmodifiableSortedMap(_rows.subMap(startRow, true, endRow, true))补丁和testing用例(如果启动失败行或结束行在外部访问窗口,或者使用类似于autosize列跟踪器的列跟踪器),然后将isColumnEmpty函数添加到适当的类,那么如果您的修补程序被接受,则可以避免维护fork。