alibaba / easyexcel

快速、简洁、解决大文件内存溢出的java处理Excel工具
https://easyexcel.opensource.alibaba.com
Apache License 2.0
32.69k stars 7.58k forks source link

通过Map<Integer, String> oneRowData写入的时候,如果数据列的个数小于headMap的个数,会使得部分列无法回填 #3901

Open HaiweiCode opened 3 months ago

HaiweiCode commented 3 months ago

触发场景描述

有个需求,将解析异常的数据单独生成一份excel,由于解析异常,所以只能在onException中拿到ReadCellData,于是我们的想法是将解析异常的ReadCellData封装成Map<Integer,String>,key是excel的列标(columnIndex),value是写入对应列的值,然后用ExcelWriter写入

触发Bug的代码

通过端点,我们定位到ExcelWriteAddExecutor.addBasicTypeToExcel(RowData oneRowData, Row row, int rowIndex, int relativeRowIndex)方法中

           for (Map.Entry<Integer, Head> entry : headMap.entrySet()) {
            if (dataIndex >= oneRowData.size()) {
                return;
            }
            int columnIndex = entry.getKey();
            Head head = entry.getValue();
            doAddBasicTypeToExcel(oneRowData, head, row, rowIndex, relativeRowIndex, dataIndex++, columnIndex);
            maxCellIndex = Math.max(maxCellIndex, columnIndex);
        }

excel如果某个单元格是空的,那么oneRowData.size()就会小于headMap.size,比如我想回填的excel的头共有18列,但是oneRowData只有第一列和第18列的数据,而headMap中是18列的完整表头信息,这个时候,当headMap.entrySet()遍历到第2个的时候,dataIndex >= oneRowData.size()就已经满足,退出循环,oneRowData中第18列的数据没有回填进去。这是因为dataIndex是跟着headMap.entrySet()循环,但是我感觉应该跟着oneRowData循环。