eec icon indicating copy to clipboard operation
eec copied to clipboard

相同的两列小数,一列取到的值正常,一列取到科学计数法

Open RexH0 opened this issue 3 years ago • 8 comments

我看了单元格的格式都是数字 36C9DFD2-6D7B-49E4-B54E-ED03DD90DF6F DED55820-CAC8-43FB-9A99-D10E1EBA5372

RexH0 avatar Apr 28 '21 03:04 RexH0

方便的话可以将样本发我一份,[email protected]

wangguanquan avatar Apr 28 '21 04:04 wangguanquan

样本已发至邮箱

发自我的iPhone

在 2021年4月28日,12:12,wangguanquan @.***> 写道:

 @.***

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.

RexH0 avatar Apr 28 '21 10:04 RexH0

应该是浮点数精度引起的,文件内部保存的原始值就是0.087.0000000000000007E-2

<c r="L19" s="30"><v>0.08</v></c><c r="M19" s="30"><v>7.0000000000000007E-2</v></c>

不过eec可以像jdbc的一样读取内容,调用row.getDouble(12)或者row.getDecimal(12)获取值,样本文件读出的double数据为0.07,decimal数据为0.070000000000000007,所以你现在知道为什么第二个数是用科学计数法了,因为精度太大了。

测试代码如下:

try (ExcelReader reader = ExcelReader.read(Paths.get("./八一系统模板发票TEYASI1.xlsx"))) {
    reader.sheet(0).rows().filter(row -> row.getRowNumber() > 17 && !row.isEmpty()).forEach(row -> println(row.getDouble(12)));
    reader.sheet(0).reset(); // 重置位置,这样就可以重复读了
    println("-------------DECIMAL-------------");
    reader.sheet(0).rows().filter(row -> row.getRowNumber() > 17 && !row.isEmpty()).forEach(row -> println(row.getDecimal(12)));
} catch (IOException e) {
    e.printStackTrace();
}

更好的,你可以将列表转为对象,这样就可以指定类型了,你可以定义如下实体,

public class Item {
    @ExcelColumn("亚马逊FBA子单号/箱唛号")
    private String fbaNo;

    @ExcelColumn("Reference ID(亚马逊追踪编码)")
    private String refId;

    @ExcelColumn("单个产品申报单价")
    private BigDecimal price;

    @ExcelColumn("单个产品净重KG(必填)")
    private BigDecimal weight;

    @Override
    public String toString() {
        return "fbaNo: " + fbaNo + ", refId: " + refId + ", price: " + price + ", weight: " + weight;
    }
}

// 测试代码
reader.sheet(0).reset();
reader.sheet(0).rows()
        .filter(row -> row.getRowNumber() > 16 && !row.isEmpty()) // 这里从第16行开始,因为这一行包含头部信息
        .map(row -> row.too(Item.class)) // 转为Item对象
        .filter(Objects::nonNull)
        .forEach(Print::println);

会读取如下数据

fbaNo: FBA15DRV4JP4U000001, refId: 2Z91JHMR, price: 0.08, weight: 0.070000000000000007
fbaNo: FBA15DRV4JP4U000002, refId: 2Z91JHMR, price: 0.08, weight: 0.070000000000000007
fbaNo: FBA15DRV4JP4U000003, refId: 2Z91JHMR, price: 0.08, weight: 0.070000000000000007
fbaNo: FBA15DRV4JP4U000004, refId: 2Z91JHMR, price: 0.08, weight: 0.070000000000000007
fbaNo: FBA15DRV4JP4U000005, refId: 2Z91JHMR, price: 0.08, weight: 0.070000000000000007
fbaNo: FBA15DRV4JP4U000006, refId: 2Z91JHMR, price: 0.08, weight: 0.070000000000000007
fbaNo: FBA15DRV4JP4U000007, refId: 2Z91JHMR, price: 0.08, weight: 0.070000000000000007
fbaNo: FBA15DRV4JP4U000008, refId: 2Z91JHMR, price: 0.08, weight: 0.070000000000000007
fbaNo: FBA15DRV4JP4U000009, refId: 2Z91JHMR, price: 0.08, weight: 0.070000000000000007
fbaNo: FBA15DRV4JP4U000010, refId: 2Z91JHMR, price: 0.08, weight: 0.070000000000000007
fbaNo: FBA15DRV4JP4U000011, refId: 2Z91JHMR, price: 0.08, weight: 0.070000000000000007
fbaNo: FBA15DRV7YTGU000001, refId: 87EL4DRZ, price: 0.08, weight: 0.070000000000000007

wangguanquan avatar Apr 28 '21 15:04 wangguanquan

是否可通过 CellType.DOUBLE.equals(row.getCellType(i)) 来判断 Cell类型 从而确定是否可以使用row.getDecimal(12) 或 row.getDouble(12)来获取数据?

RexH0 avatar Sep 06 '21 01:09 RexH0

不可以的,Office是Number类的,并不区分Double和Decimal,只是在java端区分并转换,其实你完全可以根据业务来决定使用哪种类型,或者决定保留几位精度,或者直接使用string类型。

wangguanquan avatar Sep 06 '21 03:09 wangguanquan

我现在就是用row.getString(i),获取出来有时候就会是科学计数法。业务上因为模板的每列数据类型不是固定的 ,可能有的模板数字在第10列,有的模板在第11列,所以不太好判断哪列可以使用获取getDouble()或者getDecimal(),所以我的想法就是能不能确定了格子的数据格式 然后直接使用对应的方法。

RexH0 avatar Sep 06 '21 05:09 RexH0

#getCellType返回单元格的类型,理论上只有numeric,string, boolean这三种,如果是numeric内部还会进一步根据单元格设置了格式化判断是否可能是date

wangguanquan avatar Sep 06 '21 05:09 wangguanquan

image 刚测试了一下,CellType 这个枚举类里面的类型都有

RexH0 avatar Sep 06 '21 05:09 RexH0