alibaba / easyexcel

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

关于inlineStr 解析的问题 #3860

Open vesio opened 2 months ago

vesio commented 2 months ago

建议先去看文档

快速开始常见问题

触发场景描述

用户给了一个excel文件,用wps打开显示的值是 1 我收到excel文件,用easyexcel解析出来的值是 201 具体是由 inlineStr 这个类型导致的 我看了一下excle里面的sheet1.xml easyexcel的代码是把 201 的两个值拼接到一起了

<c r="M2" s="2" t="inlineStr">
    <v>20</v>
    <is>
        <t>1</t>
    </is>
</c>

触发Bug的代码, 控制台输出的最后一段数据是 12:"201", 说明easyexcel 取到的数据是 201

    @Test
    public void noModelRead() {
        //String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";
        String fileName = "D:\\test\\bug.xlsx";
        // 这里 只要,然后读取第一个sheet 同步读取会自动finish
        EasyExcel.read(fileName, new NoModelDataListener()).sheet().doRead();
        // 控制台输出
        //[main] INFO com.alibaba.easyexcel.test.demo.read.NoModelDataListener - 解析到一条数据:{0:"15258822991196",6:"16扶手二[5222]",7:"17199467844119",8:"18北京大版城央首府24栋2503[5222]",10:"19美丽洲椰子水350ml*12",12:"201"}
        //[main] INFO com.alibaba.easyexcel.test.demo.read.NoModelDataListener - 1条数据,开始存储数据库!
        //[main] INFO com.alibaba.easyexcel.test.demo.read.NoModelDataListener - 存储数据库成功!
        //[main] INFO com.alibaba.easyexcel.test.demo.read.NoModelDataListener - 所有数据解析完成!
    }

我用poi的 XSSFWorkbook 读取这个文件读取到的是, 最后的输出是 1

    @Test
    public void mytest() throws Exception {
        XSSFWorkbook workbook = new XSSFWorkbook("D:\\test\\bug.xlsx");
        XSSFSheet sheet = workbook.getSheetAt(0);
        for (Row row : sheet) {
            StringBuilder sb = new StringBuilder();
            for (Cell cell : row) {
                sb.append(cell.getStringCellValue()).append(" ");
            }
            System.out.println(sb);
        }
        // 控制台输出
        //原始单号 下单时间 付款时间 承诺发货时间 客户邮箱 QQ 收货人 手机 收货地址 客户备注 货品名称 规格 数量 物流公司 物流单号 
        //258822991196 扶手二[5222] 199467844119 北京大版城央首府24栋2503[5222] 美丽洲椰子水350ml*12 1
    }

提示的异常或者没有达到的效果

上面的代码都是用 easyexcel 4.0.1执行的

我试过用 easyexcel 2.2.6也会有这样的问题 这样的问题会导致用户那边看到的数据和我取到的数据不一致,用户会很困惑 用户那边的excel也不知道是什么软件生成的

我查了一下通义千问 说是这个文件是错误的xml结构,但是wps确实是可以解析,poi也能解析 image

出问题的文件也附带了 bug.xlsx

psxjoy commented 2 months ago

像是和 #3823 反馈的一样情况导致的问题。 我会尝试跟进并修复该问题。

vesio commented 2 months ago

感谢你的回复 我看了一下源码有 CellInlineStringValueTagHandler 这个类 但是这个类里面什么都没做 复用了父类(AbstractCellValueTagHandler) 的 characters 方法 characters方法里面

    @Override
    public void characters(XlsxReadContext xlsxReadContext, char[] ch, int start, int length) {
        xlsxReadContext.xlsxReadSheetHolder().getTempData().append(ch, start, length);
    }

是 getTempData().append(ch, start, length) 我debug看了一下 getTempData() 得到的是 20 (ch, start, length) 是 1 就导致 20 append 1, 最后输出 201的问题

我直接改源码的话又怕有其他的问题出现,所以特地问一下,因为这个问题在 2.2.6的版本,或者再往前的版本就存在了

psxjoy commented 2 months ago

Hi,我已经提交对应的PR #3861 。你可以参考PR的实现逻辑,或者直接在CellInlineStringValueTagHandler 上重载方法