Ответ зависит от того, насколько разрежены физические строки на вашем листе, ваше желание иметь простой код и насколько вы заботитесь о скорости выполнения.
Хороший компромисс из трех будет только проходить через физические ряды и выполнять прилично хорошо, пока 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
-loops над while
-loops, как это быстрее, чтобы убедиться, что ваш код не будет застревать в бесконечном цикле)
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 для метода, который возвращает java.util.Collections.unmodifiableSortedMap(_rows.subMap(startRow, true, endRow, true))
из HSSF, XSSF и SXSSF (сбой, если начальная строка или конечная строка находятся вне окна доступа или использует колонковый трекер, аналогичный autosize tracker), затем добавьте функцию isColumnEmpty в соответствующий класс, тогда вы можете избежать поддержки вилки, если ваш патч будет принят.
http://stackoverflow.com/questions/12217047/how-to-determine-empty-row – assylias
Возможно, вам также необходимо проверить ячейки «Пустые» - те, которые, как правило, не имеют значения, но некоторые форматирование – Gagravarr
@Gagravarr Вы действительно правы. Я изменил код! – Fitz