代码改变世界

spring boot mybatis+ vue 使用POI实现从Excel中批量导入数据

2019-12-27 16:07  全me村的希望  阅读(2171)  评论(0编辑  收藏  举报

一、前端vue+element

  1.前端使用element的upload组件来实现文件的上传

          <el-upload
                        style="display: inline-flex;margin-right: 8px"
                        :show-file-list="false"  
                        :before-upload="beforeUpload"
                        :on-success="onSuccess"
                        :on-error="onError"
                        accept=".xls"
                        :disabled="importDataButtonDisabled"
                        action="/employee/basic/import">
                    <el-button :disabled="importDataButtonDisabled" type="success" size="small" :icon="importDataButtonIcon">
                        {{importDataButtonMsg}}
                    </el-button>
                </el-upload>

    show-file-list:是否显示已选择文件列表

    before-upload:文件上传以前调用的钩子

    on-error:文件上传失败后的钩子

    on-success:文件上传成功后的钩子

    accept:接受的文件类型

    action:上传的地址

  2.回调函数的处理

 

//批量导入用户分为两个步骤:1.上传Excel文件 2.将Excel的数据转换后插入数据库
            //**注意:这里的上传成功的回调只是指Excel文件上传成功,并不意味着整个批量导入用户的操作是成功的
            onSuccess(response, file, fileList){
                //上传成功后的回调 更改《导入数据》的按钮显示的值以及图标
                this.importDataButtonMsg='导入数据';
                this.importDataButtonIcon='el-icon-upload2';
                this.importDataButtonDisabled=false;
                //文件上传成功后,判断员工数据插入数据库的结果(也相当于批量导入用户的操作结果)
               if (response.status == 200){
                   Message.success({message:response.msg})
               }else if (response.status == 500){
                   Message.error({message:response.msg})
               }else {
                   Message.error({message:'未知错误'})
               }
            },
            //上传文件失败后的回调 更改《导入数据》的按钮显示的值以及图标
            onError(err, file, fileList){
                this.importDataButtonMsg='导入数据';
                this.importDataButtonIcon='el-icon-upload2';
                this.importDataButtonDisabled=false;
                this.$message.error(err);
            },
            //上传文件之前的回调 更改《导入数据》的按钮显示的值以及图标 以使用户可以区分按钮的状态
            beforeUpload(){
                this.importDataButtonMsg='正在上传';
                this.importDataButtonIcon='el-icon-loading';
                this.importDataButtonDisabled=true;
            },

 

    批量导入数据分为两个步骤:1.上传Excel文件 2.将Excel的数据转换后插入数据库。 

    为了防止点击了导入数据后再次重复点击导入按钮以及区分未点击按钮和点击导入数据的感官,设置导入数据的按钮的显示值和图标为动态的,通过钩子更新按钮的显示的值和图标。

    注意:这里的上传成功的回调只是指Excel文件上传成功,并不意味着整个批量导入用户的操作是成功的

 

二、后端spring boot + mybatis

  1.controller接受层

 @PostMapping("/import")
    public RespBean importEmp(MultipartFile file){
        // 拿到 file 对象
        List<Employee> employees = EmpUtils.excelToObj(file,nationService.getAllNations(),departmentService.getAllDepartmentWithoutChild(),jobLevelService.getAllJobLevels(),
                politicsstatusService.getAllPoliticsstatuss(),positionService.getAllPositions());
       if (employeeService.importEmp(employees) == employees.size()){
        return RespBean.ok("导入成功!");
       }
       return RespBean.error("导入失败!");
    }

  controller层接收文件使用MultipartFile类来接收,忽略其他参数。

  2.处理MultipartFile类对象

public static List<Employee> excelToObj(MultipartFile file, List<Nation> allNations, List<Department> allDepartment, List<JobLevel> allJobLevels, 
List<Politicsstatus> allPoliticsstatuss, List<Position> allPositions) { List<Employee> employeeList = new ArrayList<>(); InputStream inputStream = null; try { //1.获取文件的输入流 inputStream = file.getInputStream(); //2.获取Excel工作簿对象 HSSFWorkbook workbook = new HSSFWorkbook(inputStream); //3.获取Excel工作表对象 因为此时只有一个工作表对象所以取第一个对象即可 //如果是多个工作表对象 可以通过如下方式获取后进行遍历 // int numberOfSheets = workbook.getNumberOfSheets(); HSSFSheet sheetAt = workbook.getSheetAt(0); //4.循环读取表格的数据 for (Row row : sheetAt) { //表头(标题) 跳过 if (row.getRowNum() == 0) { continue; } //空行直接跳过 if (row == null) { continue; } Employee employee = new Employee(); //获取列数 int physicalNumberOfCells = row.getPhysicalNumberOfCells(); for (int k = 0; k < physicalNumberOfCells; k++) { Cell cell = row.getCell(k); //先通过表格列的类型进行分类 switch (cell.getCellType()) { //处理string类型 case STRING: switch (k) { case 1: employee.setName(cell.getStringCellValue()); break; case 2: employee.setWorkID(cell.getStringCellValue()); break; default: { break; } } break; default: { switch (k) { case 4: //处理日期类型的列 employee.setBirthday(cell.getDateCellValue()); break; case 20: employee.setBeginDate(cell.getDateCellValue()); break; case 22: employee.setBeginContract(cell.getDateCellValue()); break; case 23: employee.setEndContract(cell.getDateCellValue()); break; case 24: //处理double类型的列 employee.setContractTerm(cell.getNumericCellValue()); break; case 25: employee.setConversionTime(cell.getDateCellValue()); break; default: break; } break; } } } employeeList.add(employee); } } catch (IOException e) { e.printStackTrace(); } return employeeList; }

     //1.获取文件的输入流
            inputStream = file.getInputStream();
            //2.获取Excel工作簿对象 HSSFWorkbook workbook = new HSSFWorkbook(inputStream);
            //3.获取Excel工作表对象 因为此时只有一个工作表对象所以取第一个对象即可
            //如果是多个工作表对象 可以通过如下方式获取后进行遍历
   // int numberOfSheets = workbook.getNumberOfSheets();
            HSSFSheet sheetAt = workbook.getSheetAt(0);
            //4.循环读取表格行的数据进行处理

  3.在mybatis的mapper.xml中使用foreach批量插入数据 

 

<insert id="importEmp" parameterType="com.hopec.vhr.bean.Employee">
    insert into employee (name, gender,
      birthday, idCard, wedlock, nationId
      )
      values
      <foreach collection="emps" separator="," item="emp">
        (#{emp.name,jdbcType=VARCHAR}, #{emp.gender,jdbcType=CHAR},
        #{emp.birthday,jdbcType=DATE}, #{emp.idCard,jdbcType=CHAR}, #{emp.wedlock,jdbcType=CHAR}, #{emp.nationId,jdbcType=INTEGER}
        )
      </foreach>
  </insert>

 

  批量插入的返回值为插入数据库的记录数,批量插入要么全部成功,要么全部失败。