• 【测试开发】知识点使用EasyExcel,实现excel导出和导入


    上篇介绍了下EasyExcel的读写excel文件的使用,现在利用它来实现项目中的excel文件导出和导入的功能。

    现在有一个字典列表,要把里面的数据实现导出和导入。

    一、实现导出

    既然是整合到项目里,跟之前的练习还是有些区别的。说是导出功能,实际上也算是个下载的操作。

    1. 实现后端接口

    controller 类中增加导出数据字典的控制器方法。

    @Api(value = "数据字典的接口")
    @RestController
    @RequestMapping("/admin/cmn/dict")
    @CrossOrigin
    public class DictController {
        @Autowired
        private DictService dictService;
    
        // 导出数据字典接口
        @GetMapping("exportData")
        public void exportDict(HttpServletResponse response) {
            dictService.exportDictData(response);
        }
    
        // 根据id查询子数据列表
        @ApiOperation(value = "根据id查询子数据列表")
        @GetMapping("findChildData/{id}")
        public Result findChildData(@PathVariable Long id) {
            List<Dict> list = dictService.findChildData(id);
            return Result.ok(list);
        }
    }
    

    这里方法exportDict中传参是HttpServletResponse response,为了方便做下载操作。

    然后DictService接口中增加对应的方法exportDictData

    public interface DictService extends IService<Dict> {
        List<Dict> findChildData(Long id);
       
        void exportDictData(HttpServletResponse response);
    }
    

    接着就是到DictServiceImpl类中实现exportDictData方法了:

        // 导出数据字典接口
        @Override
        public void exportDictData(HttpServletResponse response) {
            try {
                // 设置下载信息
                response.setContentType("application/vnd.ms-excel");
                response.setCharacterEncoding("utf-8");
                String fileName = "dict";
                response.setHeader("Content-disposition", "attachment;filename="+ fileName + ".xlsx");
                // 查询库里的数据
                List<Dict> dictList = baseMapper.selectList(null);
                // Dict 转成 DictEeVo
                List<DictEeVo> dictEeVoList = new ArrayList<>(dictList.size());
                for (Dict dict: dictList) {
                    DictEeVo dictEeVo = new DictEeVo();
                    BeanUtils.copyProperties(dict, dictEeVo);
                    dictEeVoList.add(dictEeVo);
                }
                // 调用方法,进行写操作,这里使用输出流
                EasyExcel.write(response.getOutputStream(), DictEeVo.class).sheet("dict").doWrite(dictEeVoList);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    

    做的事情主要是3件:

    • 先设置下载信息
    • 查询库里的数据
    • 使用EasyExcel.write方法把查出来的数据写到excel文件中

    另外,Dict对应的是表里的实体类,DictEeVo则是excel内容的实体类。

    调用EasyExcel.write的时候要传入的是DictEeVo类型,而数据库查出来的是Dict,所以有了异步转换的操作。

    2. 实现前端

    前端可以很简单的实现,通过一个<a>标签就可以:

        <a href="http://localhost:8202/admin/cmn/dict/exportData" target="_blank">
            <el-button type="text"> 导出</el-button>
        </a>
    

    target="_blank"是为了打开新的标签页。

    测试下:

    二、实现导入

    1. 实现后端接口

    继续增加导入的控制器方法:

        // 导入数据字典
        @PostMapping("importData")
        public Result importDict(MultipartFile file) {
            dictService.importDictData(file);
            return Result.ok();
        }
    

    这里参入是MultipartFile file用于获取上传的文件。

    跟上面一样的套路,一直到实现importDictData方法。

        @Override
        public void importDictData(MultipartFile file) {
    
        }
    

    不过目前里面还写不了,因为需要先去写一个监听器。

    public class DictListener extends AnalysisEventListener<DictEeVo> {
        private DictMapper dictMapper;
    
        public DictListener(DictMapper dictMapper) {
            this.dictMapper = dictMapper;
        }
    
        // 一行一行读取
        @Override
        public void invoke(DictEeVo dictEeVo, AnalysisContext analysisContext) {
            // 调用方法,添加到数据库表里
            Dict dict = new Dict();
            // dictEeVo 转换成 dict
            BeanUtils.copyProperties(dictEeVo, dict);
            dictMapper.insert(dict);
        }
    
        @Override
        public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    
        }
    }
    

    注意这里面的一个细节,因为在invoke方法中,一行行读取后,我需要把这每行的数据添加到数据库中,那么自然需要用到dictMapper

    那么我这个监听器里如何才可以支持传入dictMapper呢?其中一个方法就是通过有参构造方法来注入:

        private DictMapper dictMapper;
    
        public DictListener(DictMapper dictMapper) {
            this.dictMapper = dictMapper;
        }
    

    现在监听器完成,继续完成importDictData方法:

        @Override
        public void importDictData(MultipartFile file) {
            try {
                EasyExcel.read(file.getInputStream(), DictEeVo.class, new DictListener(baseMapper)).sheet().doRead();
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    

    new DictListener(baseMapper))这里在传入监听器的时候里面就要带上dictMapper,这里放的是baseMapper也可以。

    2. 实现前端整合

    添加导入按钮,绑定@click调用上传方法。

    <el-button type="text" @click="importData"> 导入</el-button>
    

    点击导入后跳出对话框,增加友好度。

    • :multiple: 表示是否上传多个文件,这里用单个
      *:on-success: 文件上传成功会调用的方法
    • :action:请求的接口路径

    对应里面的方法:

            //导入数据字典
            importData() {
                this.dialogImportVisible = true
            },
            //上传成功调用
            onUploadSuccess() {
                //关闭弹框
                this.dialogImportVisible = false
                //刷新页面
                this.getDictList(1)
            },
    

    准备一份数据测试一下:

    上传成功。

    查看数据库里数据正确。

    --不要用肉体的勤奋,去掩盖思考的懒惰--
  • 相关阅读:
    博客园 markdown 表格
    python 读取文件时报错UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position 8: illegal multibyte sequence
    在notepad++中markdown高亮并实时预览
    浏览器地址栏无法直接使用Google搜索问题
    百度文库付费文档免费下载
    交易系统开发小结
    思维认知-读mindhacks杂记
    id-aes128-GCM 加解密example
    如何以bean方式注册map
    如何实现跨域cookie共享
  • 原文地址:https://www.cnblogs.com/pingguo-softwaretesting/p/15695792.html
Copyright © 2020-2023  润新知