【測試開發】知識點-使用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)
        },

准備一份數據測試一下:

上傳成功。

查看數據庫里數據正確。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM