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

  • 相关阅读:
    算法导论————KMP
    KMP算法
    几个很好的OJ网站
    查找(二分、hash、桶)
    动态规划
    贪心(未完待续)
    搜索的题
    codeVS 1031 质数环
    《将博客搬至CSDN》
    HDU1717小数化分数2
  • 原文地址:https://www.cnblogs.com/pcode/p/9202029.html
Copyright © 2011-2022 走看看