题外话

1.所用框架

  • 后端技术栈 Spring Boot
  • 前端技术栈 Vue

2.后端接口实现

  • 导入 POI 依赖
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi</artifactId>
	<version>4.1.2</version>
</dependency>
  • 创建导入 Excel 接口
  • 导入 Excel 操作我们可以分为3个步骤:
  1. 首先获取到用户上传的 Excel 文件
  2. 解析 Excel 文件,将 Excel 解析成数据库所需要的数据
  3. 进行数据库添加操作
  • 后端接口如何设计,代码如下:
	/**
     * 导入 Excel 数据
     *
     * @param file 你要导入的 Excel 文件
     * @return
     * @throws IOException
     */
	@PostMapping("/import")
    public RespBean importData(MultipartFile file) throws IOException {
    	// 1.自定义一个工具类拿到要解析的文件并解析成要存储的数据
        List<Employee> list = POIUtils.excel2Employee(file);
        // 2.遍历输出你解析的数据格式是否正确
        for (Employee employee : list) {
            System.out.println(employee.toString());
        }
        // 3.进行数据库添加操作
        if (employeeService.addEmp(list) == 1) {
            return RespBean.ok("上传成功!");
        }
        return RespBean.error("上传失败!");
    }
  • 上文中出现的 RespBean 返回值是我项目中自定义的响应类,目的就是为了告诉前端成功或者失败而定义的一个工具类,代码如下:
/**
 * 响应结果类
 */
public class RespBean {
	// 自定义状态码
    private Integer status;
    // 自定义响应消息内容
    private String msg;
    // 自定义返回的对象
    private Object obj;

    public static RespBean build() {
        return new RespBean();
    }
	
	// 响应成功返回 200 正确消息 msg
    public static RespBean ok(String msg) {
        return new RespBean(200,msg,null);
    }

	// 相应成功返回 200 正确消息 msg 以及要返回的对象 obj
    public static RespBean ok(String msg,Object obj) {
        return new RespBean(200,msg,obj);
    }

	// 响应成功返回 500 错误消息 msg
    public static RespBean error(String msg) {
        return new RespBean(500,msg,null);
    }

	// 相应成功返回 500 错误消息 msg 以及要返回的对象 obj
    public static RespBean error(String msg,Object obj) {
        return new RespBean(500,msg,obj);
    }

    private RespBean() {

    }

    private RespBean(Integer status, String msg, Object obj) {
        this.status = status;
        this.msg = msg;
        this.obj = obj;
    }

    public Integer getStatus() {
        return status;
    }

    public RespBean setStatus(Integer status) {
        this.status = status;
        return this;
    }

    public String getMsg() {
        return msg;
    }

    public RespBean setMsg(String msg) {
        this.msg = msg;
        return this;
    }

    public Object getObj() {
        return obj;
    }

    public RespBean setObj(Object obj) {
        this.obj = obj;
        return this;
    }
}
  • POIUtils工具类方法代码实现:
	/**
     * Excel 解析成数据集合
     *
     * @return
     */
    public static List<Employee> excel2Employee(MultipartFile file) {
        List<Employee> list = new ArrayList<>();
        Employee employee = null;
        try {
            //1. 创建一个 workbook 对象
            HSSFWorkbook workbook = new HSSFWorkbook(file.getInputStream());
            //2. 获取 workbook 中表单的数量
            int numberOfSheets = workbook.getNumberOfSheets();
            for (int i = 0; i < numberOfSheets; i++) {
                //3. 获取表单
                HSSFSheet sheet = workbook.getSheetAt(i);
                //4. 获取表单中的行数
                int physicalNumberOfRows = sheet.getPhysicalNumberOfRows();
                for (int j = 0; j < physicalNumberOfRows; j++) {
                    //5. 跳过标题行
                    if (j == 0) {
                        continue;//跳过标题行
                    }
                    //6. 获取行
                    HSSFRow row = sheet.getRow(j);
                    if (row == null) {
                        continue;//防止数据中间有空行
                    }
                    //7. 获取列数
                    int physicalNumberOfCells = row.getPhysicalNumberOfCells();
                    employee = new Employee();
                    for (int k = 0; k < physicalNumberOfCells; k++) {
                        HSSFCell cell = row.getCell(k);
                        switch (cell.getCellType()) {
                        	// 类型是 String 进入此 case 块
                            case STRING:
                                String cellValue = cell.getStringCellValue();
                                switch (k) {
                                    case 1:
                                        employee.setName(cellValue);
                                        break;
                                    case 2:
                                        employee.setWorkID(cellValue);
                                        break;
                                    case 3:
                                        employee.setGender(cellValue);
                                        break;
                                    case 5:
                                        employee.setIdCard(cellValue);
                                        break;
                                    case 6:
                                        employee.setWedlock(cellValue);
                                        break;
                                    case 7:
                                        employee.setNationId(cellValue);
                                        break;
                                    case 8:
                                        employee.setNativePlace(cellValue);
                                        break;
                                    case 9:
                                        employee.setPoliticId(cellValue);
                                        break;
                                    case 10:
                                        employee.setPhone(cellValue);
                                        break;
                                    case 11:
                                        employee.setAddress(cellValue);
                                        break;
                                    case 12:
                                        employee.setDepartmentId(cellValue);
                                        break;
                                    case 13:
                                        employee.setJobLevelId(cellValue);
                                        break;
                                    case 14:
                                        employee.setPosId(cellValue);
                                        break;
                                    case 15:
                                        employee.setEngageForm(cellValue);
                                        break;
                                    case 16:
                                        employee.setTiptopDegree(cellValue);
                                        break;
                                    case 17:
                                        employee.setSpecialty(cellValue);
                                        break;
                                    case 18:
                                        employee.setSchool(cellValue);
                                        break;
                                    case 20:
                                        employee.setWorkState(cellValue);
                                        break;
                                    case 21:
                                        employee.setEmail(cellValue);
                                        break;
                                }
                                break;
                            // 类型是 Date或者数字 进入此 case 块    
                            default: {
                                switch (k) {
                                    case 4:
                                        employee.setBirthday(cell.getDateCellValue());
                                        break;
                                    case 19:
                                        employee.setBeginDate(cell.getDateCellValue());
                                        break;
                                    case 23:
                                        employee.setBeginContract(cell.getDateCellValue());
                                        break;
                                    case 24:
                                        employee.setEndContract(cell.getDateCellValue());
                                        break;
                                    case 22:
                                        employee.setContractTerm(cell.getNumericCellValue());
                                        break;
                                    case 25:
                                        employee.setConversionTime(cell.getDateCellValue());
                                        break;
                                }
                            }
                            break;
                        }
                    }
                    // 最后将解析后的数据添加到员工集合中
                    list.add(employee);
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        return list;
    }

3.前端实现

  • 前端使用的样式是 Element-UI 中的 upload 上传组件,页面制作代码如下:
    1. :show-file-list 是否显示已上传文件列表
    2. :before-upload 上传文件前的调用事件
    3. :on-success 上传成功后的调用事件
    4. :on-error 上传成功后的调用事件
    5. :disabled 是否禁用上传组件
    6. action 要上传的路径
					<el-upload
                        :show-file-list="false"
                        :before-upload="beforeUpload"
                        :on-success="onSuccess"
                        :on-error="onError"
                        :disabled="importDisabled"
                        style="display: inline-flex;margin-right: 10px;"
                        action="这里面填写刚刚写好的服务端接口路径">
                    <el-button size="small" :disabled="importDisabled" type="success" :icon="importDataIcon">
                        {{importDataText}}
                    </el-button>
                </el-upload>
  • 数据定义,了解 Vue 的朋友们应该都知道这段代码的含义,就是自定义几个变量用来使用,这里不过多解释。大家不懂得可以去看 Vue 官网。
data(){
	return{
		// 导入按钮的文本
		importDataText: '导入数据',
		// 导入按钮的图标
		importDataIcon: 'el-icon-upload2',
		// 导入按钮是否被禁用
		importDisabled: false
	}
}
  • 方法实现,代码如下:
methods: {
            // 导入文件失败后回调
            onError() {
                this.importDataText = '导入数据';
                this.importDataIcon = 'el-icon-upload2';
                this.importDisabled = false;
                this.initEmps();
                this.$message.success("导入失败!");
            },
            // 导入文件成功后回调
            onSuccess() {
            	// 成功后文本修改为原来的导入数据
                this.importDataText = '导入数据';
                // 图标修改
                this.importDataIcon = 'el-icon-upload2';
                // 将上传组件改为允许使用
                this.importDisabled = false;
                // 调用刷新数据的方法
                this.initEmps();
                // message 弹出消息
                this.$message.success("导入成功!");
            },
            // 上传文件调用
            beforeUpload() {
            	// 将文本修改为正在导入
                this.importDataText = '正在导入';
                // 修改其图标
                this.importDataIcon = 'el-icon-loading';
                // 将其上传组件暂时禁用
                this.importDisabled = true;
            }
}

4.结果截图

  • 页面中的上传按钮制作如图:
    在这里插入图片描述
  • 选择要上传的 Excel 文件,大家可以自己作判断上传的文件是不是 Excel,由于我这里没有做判断,大家可别学我,在真实的项目中还是要做的,前端做提升用户体验,后端做防止出错。
    在这里插入图片描述
  • 正在导入中的按钮也是不可以点击的,这里我们在事件中已经定义过了,图标也显示成正在加载的样式,UI 界面还是非常不错的。
    在这里插入图片描述
  • 导入成功的显示导入成功,这里我们可以去看下服务端接口打印的结果。
    在这里插入图片描述
  • 服务端打印的结果是正确的,这里我们就完成了简单的 Excel 导入功能。
    在这里插入图片描述

5.结语

  • 文中所用技术或许与你所用的技术不一样,但是稍稍修改也是也可实现Excel导入功能的,这个其实没有什么技术点,代码又不需要死记硬背,要用的时候拿过来用即可,如果各位看官有什么问题,评论区留言或者私信我,我都会回复你的。
Logo

前往低代码交流专区

更多推荐