导入导出功能实现

EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目

读写基本分为两种方式

  1. 采用创建对象的方式
  2. 不创建对象进行操作

导入依赖:

    <!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>easyexcel</artifactId>
      <version>2.0.5</version>
    </dependency>

本文将myql中city表作为读写demo的数据源

方式一:不创建对象

    写入Excel

mybatis:语句编写

   <sql id="exportSql">
        c.ID "城市编号",c.Name "城市名称",c.CountryCode "城市编码",
        c.District "地理区域",
        c.Population "人口数量",
        status "状态",sex "性别",birthday "生日",createTime "时间"
    </sql>

    <select id="getAll" parameterType="map" resultType="map">
        select
        <include refid="exportSql"/>
        from city as c
    </select>

 数据需要处理:

    /**
     * 不创建对象获取数据
     *
     * @return
     */
    private List<List<Object>> dataList2() {
        List<List<Object>> list = new ArrayList<List<Object>>();
        List<Map<String, Object>> all = cityDao.getAll();
        all.forEach(t -> {
            Map<String, Object> t1 = t;
            List<Object> data = new ArrayList<Object>();
            List<List<String>> lists = head2();
            lists.forEach(s -> {
                Object o = t1.get(s.get(0));
                if (o instanceof Date) { //时间类型的不能处理,直接转为String类型
                    String s1 = String.valueOf(o);
                    o=s1;
                }
                data.add(o);
            });
            list.add(data);
        });
        return list;
    }

    /**
     * excel 第一行数据
     *
     * @return
     */
    private List<List<String>> head2() {
        List<String> strings = Arrays.asList(new String[]
                {"城市编号", "城市名称", "城市编码", "地理区域", "人口数量", "状态", "性别", "生日", "时间"});
        List<List<String>> list = new ArrayList<List<String>>();
        strings.forEach(t -> {
            list.add(Collections.singletonList(t));
        });
        return list;
    }

 测试:

    /**
     * 不创建对象简单导出功能-----------------------------------
     */
    @Test
    public void exportByData() {
//        dataList2();
        String file = "C:\\Users\\lhl\\Desktop\\tem.xlsx";
        EasyExcel.write(file).head(head2()).sheet("模板").doWrite(dataList2());
    }

结果:下面数据太多不再展开

   读取Excel

 创建监听类:每一行数据都会读到

public class NoModelDataListener extends AnalysisEventListener<Map<Integer, Object>> {
    /**
     * 每隔100条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 100;
    List<Map<Integer, Object>> list = new ArrayList<Map<Integer, Object>>();
    @Override
    public void invoke(Map<Integer, Object> data, AnalysisContext context) {
        System.out.println("----------------读取excel数据-------------------------");
        System.out.println(data);
        list.add(data);
        if (list.size() >= BATCH_COUNT) {
            saveData();
            list.clear();
        }
    }


    @Override

    public void doAfterAllAnalysed(AnalysisContext context) {
        saveData();
    }


    /**
     * 加上存储数据库
     */

    private void saveData() {
        System.out.println("存储数据库");

    }


    @Test
    public  void fadfda(){
//        System.out.println("hello world !!!");
        try {
            //创建一个URL实例
            URL url = new URL("https://mp.weixin.qq.com/s/ZGjVb3gwYuj3mGv0sCyAbw");
            try {
                //通过URL的openStrean方法获取URL对象所表示的自愿字节输入流
                InputStream is = url.openStream();
                InputStreamReader isr = new InputStreamReader(is,"utf-8");

                //为字符输入流添加缓冲
                BufferedReader br = new BufferedReader(isr);
                String data = br.readLine();//读取数据

                while (data!=null){//循环读取数据
                    System.out.println(data);//输出数据
                    data = br.readLine();
                }
                br.close();
                isr.close();
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }

    
}

 测试:

  /**
     * 读取excel
     */
    @Test
    public void readExcelByNoObj(){
        // 这里 只要,然后读取第一个sheet 同步读取会自动finish
        String file = "C:\\Users\\lhl\\Desktop\\tem.xlsx";
        EasyExcel.read(file, new NoModelDataListener()).sheet().doRead();
    }

效果:

excel简易的读取到此实现了,没有多复杂的处理。 当我们遇到复杂的数据处理的时候,更多还是要创建对象来实现excel数据的导入和读取。

方式二:创建对象

          写入Excel

创建实体类:ExportExcel,get 、set方法不再赘述


@ContentRowHeight(10)
@HeadRowHeight(20)
@ColumnWidth(25)
public class ExportExcel {
    @ExcelProperty("城市编号")
    private Integer id;
    @ExcelProperty("城市名称")
    private String name;
    /**
     * 宽度为50
     */
//    @ColumnWidth(50) 可以单个列进行设置
    @ExcelProperty("城市编码")
    private String countryCode;
    @ExcelProperty("地区")
    private String district;
    @ExcelProperty("人口")
    private Integer population;
    @ExcelProperty("状态")
    private Integer status;
    @ExcelProperty("性别")
    private String sex;
    @DateTimeFormat("yyyy年MM月dd日")
    @ExcelProperty("生日")
    private Date birthday;
    @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
    @ExcelProperty("时间")
    private Date createTime;

...................................
}

测试:效果相同,不再赘述

mybatis层:sql是查询所有不再赘述:

    /**
     * ---------------------------------------------
     * 创建对象导出-----非常方便
     */
    @Test
    public void fdsasfa() {
        List<ExportExcel> list = cityDao.exportAll();
        String file = "C:\\Users\\lhl\\Desktop\\tem.xlsx";
        EasyExcel.write(file, ExportExcel.class).sheet("模板").doWrite(list);
    }

读取Excel

创建监听类:

// 有个很重要的点 ModelDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
public class ModelDataListener extends AnalysisEventListener<ExportExcel> {
    /**
     * 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 5;
    List<ExportExcel> list = new ArrayList<ExportExcel>();

    private CityDao cityDao;//可以操作数据库存储数据

    public ModelDataListener(CityDao demoDAO) {
        System.out.println("-------这个获取传入的dao层-------");
        List<ExportExcel> all = demoDAO.exportAll();
        all.forEach(t-> System.out.println(t));
        this.cityDao=demoDAO;
    }
    /**
     * 这个每一条数据解析都会来调用
     * @param data
     * one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     */
    @Override
    public void invoke(ExportExcel data, AnalysisContext analysisContext) {
//        System.out.println(data);
        list.add(data);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (list.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            list.clear();
        }
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context
     */
    @Override

    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
    }
    /**
     * 加上存储数据库
     */
    private void saveData() {
    }
}

测试:结果正确

    /**
     * 按照创建对象的读取
     */
    @Test
    public void readByModel(){
        String file = "C:\\Users\\lhl\\Desktop\\tem.xlsx";
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
        EasyExcel.read(file, ExportExcel.class, new ModelDataListener(cityDao)).sheet().doRead();
    }

特别注意:由于不创建对象,我没有正确使用,将日期等格式转成了字符串,不要串用,否则会报监听错误。

更严密用法,监听类可以使用泛型,不用每个都创建。

其他更多用法:使用说明 · 语雀

ServletOutputStream fo=response.getOutputStream();
response.addHeader("Content-Disposition","attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
response.setContentType("application/vnd.ms-excel;charset=utf-8");

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值