将Java HashMap导出到xlsx

时间:2017-02-25 10:59:24

标签: java hashmap apache-poi xls

我需要使用poi将HashMaps转换为xlsx。对于表格数据2我需要这样的东西:

表1:

enter image description here

但我有桌子2:

enter image description here

这是我的HashMaps列表:

  

行数= [{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());
                        }
                    }
                }

有人可以帮忙吗?

1 个答案:

答案 0 :(得分: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变量

建议的解决方案

我会(一开始)想出这样的东西(我添加了一些额外的评论,我通常不会在那里做出更明确的意图是什么以及你需要理解的解决方案的哪些方面) :

    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"))。