【问题标题】:Export Java HashMap to xlsx将 Java HashMap 导出到 xlsx
【发布时间】:2017-02-25 10:59:24
【问题描述】:

我需要使用 poi 将 HashMaps 转换为 xlsx。对于工作表 data2,我需要类似的东西:

表1:

但我有table2:

这是我的 HashMap 列表:

rows=[{kol2=s, kol1=s}, {kol2=bbbb, kol3=bbbb, kol1=aaaa}, {kol2=bbbb, kol3=bbbb, kol1=aaaa}, {kol2=bbbb, kol3 =bbbb, kol1=aaaa}, {kol2=s, kol1=s}]}

这是我的代码:

            XSSFWorkbook workBook = new XSSFWorkbook();
            XSSFSheet sheet = workBook.createSheet("data");
            XSSFSheet sheet2 = workBook.createSheet("data2");
            int rowCount = 0;
            int help = 1;


                List<HashMap<String, Object>> rows = ((List<HashMap<String, Object>>) x);
                int rowCount2 = 0;
                int header = 1;
                Row header2 = sheet2.createRow(0);
                for (int i = 0; i < rows.size(); i++) {
                    int li = 0;
                    Row row2 = sheet2.createRow(++rowCount2);
                    HashMap<String, Object> row = rows.get(i);
                    int columnCount2 = 0;

                    for (HashMap.Entry<String, Object> subElement : row.entrySet()) {

                        if (subElement.getValue() != null) {

                            if (i == li) {
                                Cell cell = header2.createCell(header);
                                cell.setCellValue(subElement.getKey().toString());
                                header++;
                            }
                            li++;
                            Cell cell2 = row2.createCell(++columnCount2);
                            cell2.setCellValue(subElement.getValue().toString());
                        }
                    }
                }

有人可以帮忙吗?

【问题讨论】:

    标签: java hashmap apache-poi xls


    【解决方案1】:

    遍历 HashMap 的 EntrySet

    第一个问题是您正在迭代 HashMap 的 entrySet

    for (HashMap.Entry<String, Object> subElement : row.entrySet()) {
        // no guaranteed order
    }
    

    查看Set#iterator() 方法的JavaDoc 你会看到:

    返回此集合中元素的迭代器。 元素没有特定的顺序返回(除非这个集合是某个提供保证的类的实例)。

    有些 Set 是有序的(例如 TreeSet),但由于您使用的是 HashMap,因此您的 EntrySet 也不会被订购。

    请注意工作表中的列顺序是 kol2-kol3-kol1。你不希望它是 kol1-kol2-kol3 吗?

    不创建空列

    您忘记为地图中没有的列创建空单元格。

    if (subElement.getValue() != null) {
        // there won't be an empty cell if you e.g. don't have kol2 in your rows Map, 
        // since this just skips your current value
    }
    

    这就是为什么你最终会得到这样的结果:

    kol2   kol3   kol1
    s      s      
    bbbb   bbbb   aaaa
    ...
    

    代替:

    kol2   kol3   kol1
    s             s      
    bbbb   bbbb   aaaa
    ...
    

    在循环内创建标题行

    通过在循环中创建标题行,您的解决方案变得比必要的复杂。只需创建标题行然后循环遍历List 中的条目会容易得多。

    if (i == li) {
        Cell cell = header2.createCell(header);
        cell.setCellValue(subElement.getKey().toString());
        header++;
    }
    

    如果您在循环之外执行此操作,则不需要 liheader 变量

    建议的解决方案

    我会(首先)想出这样的东西(我添加了一些我通常不会放在那里的额外 cmets,以更清楚地说明意图是什么以及您需要了解解决方案的哪些方面):

        XSSFSheet sheet2 = workBook.createSheet("data2");
        List<HashMap<String, Object>> rows = ((List<HashMap<String, Object>>) x);
    
        List<String> headers = Arrays.asList("kol1", "kol2", "kol3");
        int currentRowNumber = 0;
    
        // create header row
        Row header = sheet2.createRow(currentRowNumber);
        for (int i = 0; i < headers.size(); i++) {
            Cell headerCell = header.createCell(i);
            headerCell.setCellValue(headers.get(i));
        }
    
        // create data rows (we loop over the rows List)
        for (int i = 0; i < rows.size(); i++) {
            HashMap<String, Object> row = rows.get(i);
    
            // we neet to increment the rowNumber for the row in the sheet at the beginning of 
            // each row. entry 0 in the rows List is in sheetRow 1, entry 1 in sheetRow 2, etc.
            currentRowNumber++;
            Row sheetRow = sheet2.createRow(currentRowNumber);
    
            // we can now loop over the columns inside the row loop (using the headers List)
            // we create a Cell for each column, but only fill it if there is
            for (int j = 0; j < headers.size(); j++) {
                Cell cell = sheetRow.createCell(j);
    
                // only fill the cell if we are having data in the row map for the current column
                String currentColumnName = headers.get(j);
                if (row.containsKey(currentColumnName)) {
                    cell.setCellValue(row.get(currentColumnName).toString());
                }
            }
        }
    

    如果您想要不同的列顺序,只需更改标题列表即可完成(例如Arrays.asList("kol2", "kol3", "kol1"))。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多