Solución:
Poi no tiene un mecanismo de clasificación incorporado, aunque, por supuesto, estás lejos de ser el primero con esa necesidad.
Creo que se está metiendo en problemas porque está moviendo filas sobre las que está iterando. He ejecutado el código anterior y parece que lo que está sucediendo es que las filas desaparecen de la hoja al final de la ejecución del código.
La pregunta intenta hacer una modificación en el lugar de una hoja de lectura. Creo que sería más apropiado crear una segunda hoja de salida.
Entonces, el enfoque básico sería leer la hoja, ordenar en Java tal como trataría cualquier otro problema de ordenación, escribir en la hoja de salida. Si hizo un mapa del número de fila que es exclusivo del valor de cadena de la columna que le interesa, puede ordenar el mapa por valor. Este tipo de enfoque funcionaría si solo previera la necesidad de ordenar en una sola columna. En cualquier caso, no es tan simple como elegir la opción de menú de clasificación desde Excel.
Ahora sé por qué no funciona. Hay un error en el método shiftRows. Cuando el tercer argumento (número de filas para cambiar) es negativo, causa problemas.
Esto se describe aquí: https://issues.apache.org/bugzilla/show_bug.cgi?id=53798
ACTUALIZAR
Este error se ha corregido a partir de la versión 3.9.
Para ordenar las filas necesita:
- copiar todas las filas a la temperatura
- ordenar filas en la temperatura
- eliminar todas las filas de la hoja
- crear nuevas filas con valores de filas ordenadas de temp
Código:
import org.apache.commons.compress.utils.Lists;
import org.apache.poi.hssf.usermodel.HSSFOptimiser;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import java.util.List;
public static void sortSheet(Workbook workbook, Sheet sheet) {
//copy all rows to temp
List<Row> rows = Lists.newArrayList(sheet.rowIterator());
//sort rows in the temp
rows.sort(Comparator.comparing(cells -> cells.getCell(0).getStringCellValue()));
//remove all rows from sheet
removeAllRows(sheet);
//create new rows with values of sorted rows from temp
for (int i = 0; i < rows.size(); i++) {
Row newRow = sheet.createRow(i);
Row sourceRow = rows.get(i);
// Loop through source columns to add to new row
for (int j = 0; j < sourceRow.getLastCellNum(); j++) {
// Grab a copy of the old/new cell
Cell oldCell = sourceRow.getCell(j);
Cell newCell = newRow.createCell(j);
// If the old cell is null jump to next cell
if (oldCell == null) {
newCell = null;
continue;
}
// Copy style from old cell and apply to new cell
CellStyle newCellStyle = workbook.createCellStyle();
newCellStyle.cloneStyleFrom(oldCell.getCellStyle());
newCell.setCellStyle(newCellStyle);
// If there is a cell comment, copy
if (oldCell.getCellComment() != null) {
newCell.setCellComment(oldCell.getCellComment());
}
// If there is a cell hyperlink, copy
if (oldCell.getHyperlink() != null) {
newCell.setHyperlink(oldCell.getHyperlink());
}
// Set the cell data type
newCell.setCellType(oldCell.getCellType());
// Set the cell data value
switch (oldCell.getCellType()) {
case BLANK:
newCell.setCellValue(oldCell.getStringCellValue());
break;
case BOOLEAN:
newCell.setCellValue(oldCell.getBooleanCellValue());
break;
case ERROR:
newCell.setCellErrorValue(oldCell.getErrorCellValue());
break;
case FORMULA:
newCell.setCellFormula(oldCell.getCellFormula());
break;
case NUMERIC:
newCell.setCellValue(oldCell.getNumericCellValue());
break;
case STRING:
newCell.setCellValue(oldCell.getRichStringCellValue());
break;
}
}
// If there are are any merged regions in the source row, copy to new row
for (int j = 0; j < sheet.getNumMergedRegions(); j++) {
CellRangeAddress cellRangeAddress = sheet.getMergedRegion(j);
if (cellRangeAddress.getFirstRow() == sourceRow.getRowNum()) {
CellRangeAddress newCellRangeAddress = new CellRangeAddress(newRow.getRowNum(),
(newRow.getRowNum() +
(cellRangeAddress.getLastRow() - cellRangeAddress.getFirstRow()
)),
cellRangeAddress.getFirstColumn(),
cellRangeAddress.getLastColumn());
sheet.addMergedRegion(newCellRangeAddress);
}
}
}
}
private static void removeAllRows(Sheet sheet) {
for (int i = 0; i < sheet.getLastRowNum(); i++) {
sheet.removeRow(sheet.getRow(i));
}
}