首页 文章

Apache-POI在excel中排序行

提问于
浏览
9

我想用一个字符串列对表中的行进行排序 . 我尝试使用Sheet.shiftRows方法实现这一点,但我无法管理 . 它不会在我的方法中切换行的位置 . 我的代码有什么问题?或者也许有更好的方法来排序excel中任何String列的行?

/**
 * Sorts (A-Z) rows by String column
 * @param sheet - sheet to sort
 * @param column - String column to sort by
 * @param rowStart - sorting from this row down
 */
private void sortSheet(Sheet sheet, int column, int rowStart) {
    boolean sorting = true;
    int lastRow = sheet.getLastRowNum();
    while (sorting == true) {
        sorting = false;
        for (Row row : sheet) {
            // skip if this row is before first to sort
            if (row.getRowNum()<rowStart) continue;
            // end if this is last row
            if (lastRow==row.getRowNum()) break;
            Row row2 = sheet.getRow(row.getRowNum()+1);
            if (row2 == null) continue;
            String firstValue = (row.getCell(column) != null) ? row.getCell(column).getStringCellValue() : "";
            String secondValue = (row2.getCell(column) != null) ? row2.getCell(column).getStringCellValue() : "";
            //compare cell from current row and next row - and switch if secondValue should be before first
            if (secondValue.compareToIgnoreCase(firstValue)<0) {                    
                sheet.shiftRows(row2.getRowNum(), row2.getRowNum(), -1);
                sheet.shiftRows(row.getRowNum(), row.getRowNum(), 1);
                sorting = true;
            }
        }
    }
}

知道如何管理工作表中的行排序吗?

UPDATE 上述方法自Apache-POI 3.9版本起作用 .

编辑:添加了缺失的括号--helvio

3 回答

  • 2

    Poi没有内置的排序机制,当然你远远没有那个需要的第一个 .

    我认为你遇到了麻烦,因为你正在移动你正在迭代的行 . 我已经运行了上面的代码,似乎正在发生的事情是代码执行结束时行正在消失 .

    该问题试图对读入表进行就地修改 . 我相信创建第二个输出表更合适 .

    因此,基本方法将是读取工作表,在java中排序就像处理任何其他排序问题一样,写入输出表 . 如果您对行感兴趣的列的字符串值唯一的行号进行了映射,则可以按值对映射进行排序 . 如果您只预见到需要对单个列进行排序,那么这种方法就可以工作 . 无论如何,它并不像在excel中选择排序菜单选项那么简单 .

  • 4

    现在我现在为什么它不起作用 . shiftRows方法中存在一个错误 . 当第三个参数(要移位的行数)为负时,会引起麻烦 .

    这在这里描述:https://issues.apache.org/bugzilla/show_bug.cgi?id=53798

    UPDATE 此错误已在3.9版中修复

  • 1

    要对行进行排序,您需要:

    • 将所有行复制到temp

    • 在temp中排序行

    • 从工作表中删除所有行

    • 使用temp中已排序行的值创建新行

    public static void sortSheet(Workbook workbook, Sheet sheet) {
        List<Row> rows = Lists.newArrayList(sheet.rowIterator());
        rows.sort(Comparator.comparing(cells -> cells.getCell(0).getStringCellValue()));
        removeAllRows(sheet);
    
        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));
    }}
    

相关问题