【问题标题】:Apache POI: Sort rows by date [duplicate]Apache POI:按日期对行进行排序[重复]
【发布时间】:2017-02-23 18:56:10
【问题描述】:

我正在使用 Apache POI 从 XML 创建 Excel 文档。我有一个带有日期值的单元格,我将其设置为日期:

HSSFCellStyle styleDate = workbook.createCellStyle();
HSSFDataFormat dataFormat = workbook.createDataFormat();
styleDate.setDataFormat(dataFormat.getFormat("dd/mm/yyyy Hh:mm"));
styleDate.setAlignment(HorizontalAlignment.CENTER);

excel 中的数据显示为日期。我需要在 Excel 文档中按日期升序排序。

我知道 POI 没有内置排序功能,并且我无法使用 Aspose Cells,因为我没有获得业务方的额外许可费用批准。

Excel 文件结构: 工作表:

1. Item 1: 01/01/2016 (sorted correctly using HashMap sorting)
1.1. Sub item 1: 01/01/2016 02:00 (not sorted, needs to be sorted)
1.2. Sub item 2: 01/01/2016 05:00 (not sorted, needs to be sorted)
1.3. Sub item 3: 01/01/2016 01:00 (not sorted, needs to be sorted)

2. Item 2: 02/01/2016 (sorted correctly using HashMap sorting)
2.1. Sub item 1: 02/01/2016 02:00 (not sorted, needs to be sorted)
2.2. Sub item 2: 02/01/2016 05:00 (not sorted, needs to be sorted)
2.3. Sub item 3: 02/01/2016 01:00 (not sorted, needs to be sorted)

HashMap 排序

for (int i = 0; i < nodeList.getLength(); i++) {
    itemHashMap.put(getNodeValue(nodeList, i, "item"),
                                getNodeValue(nodeList, i, "itemDate"));
}

【问题讨论】:

  • 为什么不在写入前对数据进行排序,并按照预期的顺序写入行。
  • 我可能最终会这样做,因为所有其他变体似乎都失败了。谢谢

标签: java excel sorting apache-poi


【解决方案1】:
private void sortSheet(Sheet sheet, int column, int rowStart) {
 boolean sorting = true;
 int lastRow = sheet.getLastRowNum();
 while (sorting) {
    sorting = false;
    for (Row row : sheet) {
        if (row.getRowNum() < rowStart) continue;
        if (lastRow == row.getRowNum()) break;
        Row nextRow = sheet.getRow(row.getRowNum() + 1);
        if (nextRow == null) continue;
        Date firstValue = row.getCell(column).getDateCellValue() ;
        Date secondValue = nextRow.getCell(column).getDateCellValue() ;
        if (secondValue.before(firstValue)) {                    
            sheet.shiftRows(nextRow.getRowNum(), nextRow.getRowNum(), -1);
            sheet.shiftRows(row.getRowNum(), row.getRowNum(), 1);
            sorting = true;
        }
    }
 }
}

【讨论】:

  • 谢谢!如果我有这种格式的数据怎么办: 1. 项目日期(使用 hashmap 键值排序正确排序) 1.1。带日期的子项(未排序) 1.2。带有日期的子项目(未排序) 2. 项目日期(排序正常,如上)。我不认为它会在这种情况下工作..?
  • 您可以使用compareTo 来比较您的对象。
  • 你的数据模型不是很清楚。你能举个具体的例子吗?
  • 我已经更新了我的初始帖子。我实际上认为我必须创建另一个带有键 + 值的列表(我需要考虑,因为有重复的键,所以我不能使用集合)进行子项目排序,因为通过 POI 没有官方方便的方法。
  • 您是否知道 shiftRows 在使用 -1 时会隐藏上排或在使用 1 时隐藏下排并且两者都会留下空行?您需要创建一个时间行来使用该方法。
【解决方案2】:

不要将 Date 对象转换为 String。相反,直接在模型中使用它们。建议格式不是模型的责任,而是使用 TableCellRenderer。

允许 getValueAt 返回 Date 对象。

修改表模型并覆盖 getColumnClass 方法并返回蜂巢列的适当类(如 Date.class)。

默认情况下,表格将为您格式化 Date 对象。

【讨论】:

  • 当这个答案提到 Java Swing API 时,怎么会有两个赞成票?提问者正在尝试使用 Apache POI 创建 XLS 电子表格,而不是呈现 JTable。答案完全无关。
【解决方案3】:

就目前而言,Apache POI 不允许对生成的 excel 文件中的数据进行简单的排序。

您当然可以使用 Aspose,但这需要许可证。我要由 Apache POI 处理并用于结束 excel 文档的传入数据是 XML 格式:

<transaction>
    <transactionDate>2015-10-23T00:00:00+03:00</transactionDate>
    <transactionAmount>23</transactionAmount>
    <transactionBatch>000</transactionBatch>
    <transactionBatchDate>2015-10-27T10:12:00+02:00</transactionBatchDate>
    <transactionServiceFee>1</transactionServiceFee>
    <transactionNetAmount>22</transactionNetAmount>
</transaction>
<transaction>
    <transactionDate>2016-02-25T11:13:59+02:00</transactionDate>
    <transactionAmount>-1000</transactionAmount>
    <transactionBatch>000</transactionBatch>
    <transactionBatchDate>2016-02-25T11:14:40+02:00</transactionBatchDate>
    <transactionServiceFee>-30</transactionServiceFee>
    <transactionNetAmount>-970</transactionNetAmount>
</transaction>
    <transaction>
    <transactionDate>2015-10-23T00:00:00+03:00</transactionDate>
    <transactionAmount>23</transactionAmount>
    <transactionBatch>001</transactionBatch>
    <transactionBatchDate>2015-10-27T10:12:00+02:00</transactionBatchDate>
    <transactionServiceFee>1</transactionServiceFee>
    <transactionNetAmount>22</transactionNetAmount>
</transaction>
<transaction>
    <transactionDate>2016-02-25T11:13:59+02:00</transactionDate>
    <transactionAmount>-1000</transactionAmount>
    <transactionBatch>001</transactionBatch>
    <transactionBatchDate>2016-02-25T11:14:40+02:00</transactionBatchDate>
    <transactionServiceFee>-30</transactionServiceFee>
    <transactionNetAmount>-970</transactionNetAmount>
</transaction>
....

我必须在结果 Excel 中以以下方式呈现数据:

1. transactionBatch 000: transactionBatchDate (sorted by date in asc.)
1.1. transaction: transactionDate (sorted by date grouped by above batch)
1.2. transaction: transactionDate (sorted by date grouped by above batch)
1.3. transaction: transactionDate (sorted by date grouped by above batch)

2. transactionBatch 001: transactionBatchDate (sorted by date in asc.)
2.1. transaction: transactionDate (sorted by date grouped by above batch)
2.2. transaction: transactionDate (sorted by date grouped by above batch)
2.3. transaction: transactionDate (sorted by date grouped by above batch)

为了解决我的问题,我首先必须按日期对 XML 中的数据进行排序。这是通过让我的模型实现 Comparable 接口来实现的。

在我可以像这样按日期批次排序之后:

Map<String, String> transactionBatchHashMap = new HashMap<>();
for (int i = 0; i < nodeList.getLength(); i++) {
            transactionBatchHashMap.put(getNodeValue(nodeList, i, "transactionBatch"),
                                        getNodeValue(nodeList, i, "transactionBatchDate"));
        }

        transactionBatchHashMap = sortMapByValues(transactionBatchHashMap);

然后通过使用简单的 foreach 循环,我可以将事务分组到每个批次下:

for (Map.Entry<String, String> entry : transactionBatchHashMap.entrySet()) {

            HSSFRow batchRow = spreadSheet.createRow(rowNumber);
            ...

            for (int i = 0; i < nodeList.getLength(); i++) {
                String transactionBatchValue = getNodeValue(nodeList, i, "transactionBatch");
                String hashMapBatchKeyValue = entry.getKey();

                if (transactionBatchValue.equals(hashMapBatchKeyValue)) {   
                ...

【讨论】:

    猜你喜欢
    • 2012-10-19
    • 2015-02-25
    • 2017-07-16
    • 1970-01-01
    • 1970-01-01
    • 2020-10-30
    • 2013-04-23
    • 2013-05-10
    相关资源
    最近更新 更多