【问题标题】:Apache-POI sorting rows in excelApache-POI在excel中对行进行排序
【发布时间】:2012-10-19 12:38:27
【问题描述】:

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

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

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

更新上述方法从 Apache-POI 3.9 版本开始有效。

编辑:添加缺少的括号 -helvio

【问题讨论】:

    标签: java excel sorting row apache-poi


    【解决方案1】:

    Poi 没有内置的排序机制,当然你远不是第一个有这种需求的人。

    我认为您遇到了麻烦,因为您正在移动要迭代的行。我已经运行了上面的代码,似乎正在发生的事情是在代码执行结束时行正在从工作表中消失。

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

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

    【讨论】:

    • 感谢demongolem的努力和建议。你是对的——他们正在消失。我面临同样的结果。然后我将尝试对 java 列表中的行进行排序,然后将它们放入工作表中。谢谢
    【解决方案2】:

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

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

    更新 此错误已从 3.9 版本修复

    【讨论】:

    • 我想补充一点,我已经测试了他的原始代码并且它没有任何变化(实际上,一个小的变化:你忘了关闭最后一个括号lol)
    • @Helvio 正如我在解决方案中所写,此错误已在 3.9 版本中修复,因此现在应该可以使用 :-) 。您使用哪个版本?感谢括号缺少提示 - 已更正。
    • 我正在使用 3.15-beta。我还编辑了你原来的问题,因为缺少的括号没有解决:)
    • 我正在使用 apache poi 3.9 .....,“shiftRows”行正在执行,仍然没有排序
    【解决方案3】:

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

    • 将所有行复制到 temp
    • 对 temp 中的行进行排序
    • 从工作表中删除所有行
    • 使用来自 temp 的已排序行的值创建新行

    代码:

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

    【讨论】:

    • 哪一列是排序的基础?
    • @plaidshirt index = 0 ,见行rows.sort(Comparator.comparing(cells -&gt; cells.getCell(0)...
    • 我在这一行收到错误消息:if (cellRangeAddress.getFirstRow() == sourceRow.getRowNum()) { 错误消息:org.apache.xmlbeans.impl.values.XmlValueDisconnectedException at org.apache.xmlbeans.impl.values.XmlObjectBase.check_orphaned(XmlObjectBase.java:1258) at org.openxmlformats.schemas.spreadsheetml.x2006.main.impl.CTRowImpl.getR(Unknown Source)
    猜你喜欢
    • 1970-01-01
    • 2017-02-23
    • 2013-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多