zoukankan      html  css  js  c++  java
  • 以ORM的思路来从Excel文件中读取JSON数据列表

    1.一个常见的问题就是如何读取excel。

    这里面有几个分支的问题,一个是如何使用poi读取excel,网上例子很多,但是这只解决了第一步。如何将excel读取入一定的数据结构这是第二个问题,还有就是读取到数据了以后如何存放,如何将其转换成我们希望的对象?这些问题一个比一个在应用的更高层级上,也就是说,如果excel是数据源,如何将数据源读取到的数据转换成我们喜爱的实体类,也就是ORM的思想,只是在读取excel这个事情上,我们的数据源是个文件,需要一定的驱动去读取,仅此而已。

    2..破解问题

    我们需要poi包的支持,这是世界java圈里公认的组件,不用再次发明轮子。我们需要用到json包,用alibaba出品的fastjson包,这个也非常好用。感谢zj的推荐。思考的过程是这样的,在我们现有的知识里面,已经有这样几个概念了,excel通过poi可以读取它的值,json包可以把string直接转换成pojo,那么我们将他们建立联系,从excel中读取行到json,再把json变成实体类,就可以达到我们预想的效果了。那么还有一个问题需要解决,就是如何指定类的属性与excel对应列的关系。仔细想了一阵子,还没想到好的解决办法,如果没有办法自动,那就可以用指定的方法,外部指定其实已经解耦了,只是没那么完美而已。

    3.解决问题

    第一步,我们建立pojo类属性与excel的对照关系,我们还是利用json作为中间传递的载体。
    /**
     * 创建用于翻译中文列名到英文变量名的对照字典。
     * @param keys  中文或默认的excel列名称
     * @param values 变量名
     * @return
     * @throws Exception
     */
    public JSONObject genImportKyes(String[] keys,String[] values) throws Exception {
        try {
            JSONObject result = new JSONObject();
            for (int i = 0; i < keys.length; i++) {
                result.put(keys[i], values[i]);
            }
            return result;
        }catch (Exception e){
            e.printStackTrace();
            throw e;
        }
    }
    调用的时候比如excel有字段"序号", "数量", "日期", "小计", "备注",而我们的pojo对象的属性是"id","count","date","sum","memo",我们这样调用
    JSONObject keys = eo.genImportKyes(new String[]{"序号", "数量", "日期", "小计", "备注"},new String[]{"id","count","date","sum","memo"} );
    这样这个keys里面我们就建立了excel中的列名和我们实体类属性的对应关系了。
    第二步,从excel的指定行去读取一行,来建立属性名和excel列的位置的对应关系。也就是我们需要知道我们的序号兑换成的id这个数据是放在excel的第几列里面的。
    public JSONObject createRowIndex(Row row, JSONObject keys) {
        int col_count = row.getLastCellNum();
        JSONObject jsonObject = new JSONObject();
        for (int i = 0; i < col_count; i++) {
            String cv = row.getCell(i).getStringCellValue();
            if (keys == null) {
                jsonObject.put(cv, i);
            } else {
                String key = keys.getString(cv);
                jsonObject.put(key, i);
            }
        }
        return jsonObject;
    }
    通过读取excel的一个row放进这个函数,再加上我们第一步准备好的keys,我们就可以比较容易的做出对应关系来。因为第一步我们解决了excel列明与实体类属性的对照关系,在第二步我们解决了属性与excel的列的对应位置关系,接下来我们就可以去读取格子了,因为我们需要的信息都准备好了。也就是我们已经建立好了读取的规则。
    第三步:读取excel的其他所有行,并按照第一步建立的关系创建出json对象来。这中间有一个需要注意的地方是我们队与excel中的特殊类型需要额外的关照一下,比如日期类型、数字类型等等。具体可以看源码public String parseCell(Cell cell) 这个函数的实现。我们通过每一行的读取来获得一个json的对象,接下来我们在使用json包转javaobject的能力把它变成对应的实体类。接近成功了。
    

    4.最后我们来看看,假设我们有一个excel文件是这样的


    我们希望读取出来以后的实体类是这样的。

    是时候展示真正的实力啦。

    @Test
    public void test1() throws Exception {
        excelOpterator eo = new excelOpterator().setHeadRowIndex(0);
        JSONObject keys = eo.genImportKyes(new String[]{"序号", "数量", "日期", "小计", "备注"},new String[]{"id","count","date","sum","memo"} );
        JSONArray rows = eo.readXls("C:/excel.xls", keys);
        for(Object jo :rows){
            testEntity to = JSON.toJavaObject((JSONObject)jo,testEntity.class );
            System.out.println(to);
        }
    }
    

    看到输出的时候总是很开心,但是回头看自己思考的过程,也会比较有意思,希望大家都能享受到这个轻松的结果。bingo

    文末有福利

    https://gitee.com/youliaoo/lutraExcelHelper

  • 相关阅读:
    fzuoj Problem 2177 ytaaa
    zoj The 12th Zhejiang Provincial Collegiate Programming Contest Capture the Flag
    zoj The 12th Zhejiang Provincial Collegiate Programming Contest Team Formation
    zoj The 12th Zhejiang Provincial Collegiate Programming Contest Beauty of Array
    zoj The 12th Zhejiang Provincial Collegiate Programming Contest Lunch Time
    zoj The 12th Zhejiang Provincial Collegiate Programming Contest Convert QWERTY to Dvorak
    zoj The 12th Zhejiang Provincial Collegiate Programming Contest May Day Holiday
    zoj The 12th Zhejiang Provincial Collegiate Programming Contest Demacia of the Ancients
    zjuoj The 12th Zhejiang Provincial Collegiate Programming Contest Ace of Aces
    csuoj 1335: 高桥和低桥
  • 原文地址:https://www.cnblogs.com/pcode/p/9202029.html
Copyright © 2011-2022 走看看