Java实现Excel批量导入数据库

Java实现Excel批量导入数据库

前言:项目开发中最容易碰到的需求即将Excel数据批量上传到数据库中存储 -> Java实现,Excel数据表,MySQL数据库,具体步骤如下…

实现批量导入时需要导入的pom.xml文件


        org.apache.poi
        poi
        3.17
    
    
        org.apache.poi
        poi-ooxml
        3.17
    

一.前端页面传入Excel表格

1.新建Excel表格Java实现Excel批量导入数据库_第1张图片
2.前端html实现(这里使用的是layui前端框架实现的前端页面)

(1).HTML标签

 
       

点击批量上传,或将文件拖拽到此

(2).使用layui中jQuery进行对传入模板的处理,并限制传入的文件后缀名格式

//1.拖拽、点击自动上传  选完文件后不自动上传
        upload.render({
            elem: '#uploadExcel'
            ,url: "upload/uploadExcelSendedNumUp"
            ,multiple: true
            ,accept: 'file' //文件  后台:@RequestParam("file")
            ,acceptMime:'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel,application/vnd.ms-excel.sheet.macroEnabled.12'
            //文件窗口默认显示 xlsx|xls|xlsm 的文件
            ,exts:'xlsx|xls|xlsm' //限制后缀名
            ,progress: function(n){
                var percent = n + '%' //获取进度百分比
                element.progress('demo', percent); //可配合 layui 进度条元素使用
            }
            ,done: function(res){
                var errorArray = res.msg.split(";");
                var error=res.msg;
                var prefix = "
    " var suffix = "
" var errorCon = ""; var errorRemind = "上传失败:" for(var i = 0;i'; } var errorReal = errorRemind + prefix + errorCon + suffix; if(!errorCon){ if( error !== null || error !== undefined || error !== ''){ errorReal = ""+error+""; table.reload('dcSendedNum'); }else{console.log(error); errorReal = "上传成功"; table.reload('dcSendedNum');//重新渲染,局部页面刷新 } } layer.open({ id:"openErrorMsg" ,btnAlign:'c' ,title:'提示信息' ,content:errorReal }); //調用此方法,使数据回显渲染 table.reload('dcSendedNumFileInfo'); },error:function (res) { layer.msg("上传异常,请检查上传的Excel表格"); } });

二.后台处理(以下为主要的实现代码)

建议:应将下面的某些方法进行分割开来

1.Controller层实现

@RequestMapping(value = "/uploadExcelSendedNumUp")
@ResponseBody
public WebMapPageResult uploadExcelFile(@RequestParam("file") MultipartFile mulFile) {
   //批量插入数据
    List sendedNumbers = localSaveObj.saveExcelFile(mulFile, new SendedNumber());
 }

Java实现Excel批量导入数据库_第2张图片

2.localSaveObj处理类中对Excel表格的处理

public  List saveExcelFile(MultipartFile mulFile, T t) {
        if (!mulFile.isEmpty()) {
            try {
                String filename = mulFile.getOriginalFilename();
                String suffix = filename.substring(filename.lastIndexOf("."));// 后缀名
                String uuid = UUID.randomUUID().toString();
                String uuidName = uuid + suffix;
                String path = uploadConfig.getPath()+uuidName;
                String saveType = getSaveFileType(t);
                saveFileInfo(filename,uuidName,path,saveType);//文件信息插入到数据库
                File file = new File(path);
                file.mkdirs();
                File dest = new File(path);

            /*取出Excel表中的每一个单元格的值,存放在list集合中*/
            InputStream in = mulFile.getInputStream();
            //lastIndexOf() 方法可返回一个指定的字符串值最后出现的位置,如果指定第二个参数 start,则在一个字符串中的指定位置从后向前搜索。”
            String type = t.toString().substring(t.toString().lastIndexOf(".")+1, t.toString().lastIndexOf("#"));
            List> bankListByExcel = importExcelHelperObj.getBankListByExcel(in, filename,type);
            /*保存上传的Excel文件到本地目录*/
            mulFile.transferTo(dest);

            String errors = ImportExcelHelper.getErrors();
            List list = null;
            if(errors.isEmpty()){
                list = shiftType.listDisToObj(bankListByExcel, t, filename);
            }
            return list;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    return null;
}

Java实现Excel批量导入数据库_第3张图片
3.importExcelHelperObj类中的处理 对相关的字段进行校验

/**
     * Excel导入
     */
    public List> getBankListByExcel(InputStream in, String fileName, String type) throws Exception {
        List> list = null;
        // 创建Excel工作薄
        Workbook work = getWorkbook(in, fileName); //获取work对象
        if (null == work) {
            throw new Exception("创建Excel工作薄为空!");
        }
        Sheet sheet = null;
        Row row = null;
        Cell cell = null;
        list = new ArrayList>();

    // 遍历Excel中所有的sheet  只遍历第一张表
    for (int i = 0; i < 1; i++) {  //没有分表分list,多个表的数据放在一个list集合下。  work.getNumberOfSheets()
   // for (int i = 0; i < work.getNumberOfSheets(); i++) {  //没有分表分list,多个表的数据放在一个list集合下。  work.getNumberOfSheets()

        sheet = work.getSheetAt(i);//获取工作薄的第i个sheet页
        if (sheet == null) {
            continue;
        }

        //真正的行数,去掉没有数值,但有样式的行。
        int realRowNum = getRealRowNum(sheet); //获取当前sheet总共有多少真实有效的行

        // 遍历当前sheet中的所有行
        // 包涵头部,所以要小于等于最后一列数,这里也可以在初始值加上头部行数,以便跳过头部
        for (int j = sheet.getFirstRowNum(); j <= realRowNum; j++) { //j为实际行数

            row = sheet.getRow(j);//返回当前j的行数
            if (row == null || j==0) {//若当前行是第一行则跳过,即使xmls中标题部分
                continue;
            }

            // 遍历所有的列
            List li = new ArrayList();

            //校验3:列数与模板列数不一致
            Row firstRow = sheet.getRow(0); //获取到当前0行,这里是获取第一行标题部分。
            Cell firstCell= firstRow.getCell(0); //获取0行第一列的数值
            if(firstCell==null){
                continue;
            }
            String firstCellVal = getCellValue(firstCell,type,0).toString().trim();//对0行第0列的表格中数值进行格式化,获取单元格中数据
            String errCellNumMsg = DataValidation.verifyCellsNum(firstRow.getLastCellNum(),firstCellVal,type);//校验Excel表格有效单元格数量
            if (!errCellNumMsg.equals("")){
                errors += errCellNumMsg;
                break;
            }

            String isCharge = "";
            for (int y = firstRow.getFirstCellNum(); y < firstRow.getLastCellNum(); y++) { //得到一行记录,y是每一行记录中的第几个单元格(从零开始计数)
                cell = row.getCell(y);//获取第y个单元格的值
                String cellValue = getCellValue(cell,type,y).toString().trim();//对表格中数值进行格式化

                //校验4.1:为空校验,必填单元格(字段)校验
                if (type.equals("SendedNumber") || type.equals("SpamMessageFeeReceipt")) {

                    if (type.equals("SendedNumber")){
                        if (y==2 && "".equals(cellValue) && cellValue.trim().length()==0){
                            cellValue="0";
                        }else {
                            String errorCellEmp = DataValidation.verifyIsNullCell(j, y, cellValue);
                            verifyErrorMsg(errorCellEmp);
                            if(!errorCellEmp.isEmpty()){
                                continue;
                            }
                        }
                    }


                    //对distribute导入模板进行非空验证
                }else if(y<16) {//对16个单元格进行非空校验(即必填校验)
                    if (!type.equals("DistributeAccess")){
                        if (y == 5) { //这样写是:当y= 5时,对y=5进行特殊处理,y=5表示表格信息是 sP代码,Sp代码不能为空
                            String errorCellEmp = DataValidation.verifyIsNullCell(j, y, cellValue);//单元格为"",也是必填校验
                            if (!errorCellEmp.isEmpty()) {//当error不为空,添加错误补充信息
                                verifyErrorMsg(errorCellEmp);
                                break;
                            }
                            /*else {  //error 为空,表示此次验证没有出现问题
                                verifyErrorMsg(errorCellEmp);
                                if(!errorCellEmp.isEmpty()){
                                    continue;
                                }
                            }*/


                        } else {

                            String errorCellEmp = DataValidation.verifyIsNullCell(j, y, cellValue);
                            verifyErrorMsg(errorCellEmp);
                            if (!errorCellEmp.isEmpty()) {
                                continue;
                            }

                        }
                    }
                }
                //5.0 校验:校验码号分配表中同一个partyCode(SpCode),是否得到同一批数据,同一个partyCode的一行数据是相同的
                if(type.equals("Distribute")){

                    if(y==5){//y= 5:时的单元格的值就是SP代码的值
                        String errorCellEmp = DataValidation.verifyIsNullCell(j, y, cellValue);//非空校验
                        if (errorCellEmp.isEmpty()){
                            dataValidationObj.setMapDataDist(cellValue); //将Distribute表中数据放到Map中
                        }

                        String  errorCellMdmCode = dataValidationObj.verifyIsNotFoundMdmCode(j, y, cellValue);
                        verifyErrorMsg(errorCellMdmCode);

                    }else if(y>5 &&y <16){     //同一个sp代码、业务类型可以不同、备注可以不同,其他的需要相同。
                                               //对必填项进行校验,分配表前16个全为必填项
                        String errorDifferData = dataValidationObj.verifySpcodeOneRowDifferent(j,y, cellValue);
                        verifyErrorMsg(errorDifferData);
                    }
                }

                //校验5.1:码号唯一校验
                if (y == 0 && !type.equals("DistributeAccess")) {
                    String errorUnique = dataValidationObj.verifyCodeUnique(j, y, cellValue, type);
                    verifyErrorMsg(errorUnique);

                }

                //校验6:垃圾短信费用单记录唯一性 与 使用量记录的唯一性
               if(y < 5 && type.equals("SpamMessageFeeReceipt") || type.equals("SendedNumber")){
                   String errorMsgUnique = dataValidationObj.verifySpamMsgUnique(j, y, cellValue,type);
                   verifyErrorMsg(errorMsgUnique);
               }

                //对DistributeAccess信息导入模板   必填项进行非空验证  码号开通接入信息上报
                if(type.equals("DistributeAccess")){
                    //码号开通接入信息上报   非空效验
                    if (y<11 && y!=7 ){
                        String errorCellEmp = DataValidation.verifyIsNullCell(j, y, cellValue);//非空校验
                        verifyErrorMsg(errorCellEmp);
                        //将结果直接存到verifyErrorMsg()中  若都有值则不会中断程序的执行,若errorCellEmp不会'',则程序会中断,上传失败
                        if (!errorCellEmp.isEmpty()){
                            continue;
                        }
                    }

                    if (y==0){
                        String code = getCellValue(row.getCell(0),type,0).toString().trim();
                        boolean b = ValueByKey.IsDigit(code);
                        String errorCellEmp="";
                        if (!b){
                            String coordinate = DataValidation.getCoordinate(j, y);
                            String errorDescribe = ErrorEnumMessage.ITCANONLYBENUMBERS.getErrorDescribe();
                            errorCellEmp = coordinate+errorDescribe;
                            System.out.println("errorCellEmp = " + errorCellEmp);
                        }
                        verifyErrorMsg(errorCellEmp);
                        if (!errorCellEmp.isEmpty()){
                            continue;
                        }
                    }

                    //处理条件必填项
                    if (y==12 && "拆机".equals(getCellValue(row.getCell(4),type,4).toString().trim())){
                        //对条件必填项进行 处理 先验证必填项 然后再去验证与之关联的项
                        if (StringUtils.isBlank(cellValue)){
                            String coordinate = DataValidation.getCoordinate(j,y);
                            String errorCellEmp = coordinate + ErrorEnumMessage.CONDITIONISREQUIRED.getErrorDescribe();
                            verifyErrorMsg(errorCellEmp);
                            if (!errorCellEmp.isEmpty()){
                                continue;
                            }
                        }
                    }
                    
                    //处理条件必填项
                    if ((y==7 || y==17) && !"自营".equals(getCellValue(row.getCell(6),type,6).toString().trim())){
                        String errorCellEmp = DataValidation.verifyIsNullCell(j, y, cellValue);//非空校验
                        verifyErrorMsg(errorCellEmp);
                        //将结果直接存到verifyErrorMsg()中  若都有值则不会中断程序的执行,若errorCellEmp不会'',则程序会中断,上传失败
                        if (!errorCellEmp.isEmpty()){
                            continue;
                        }
                    }


                }

                li.add(cellValue);
            }
            dataValidationObj.setEmptyMemberVar("");
            list.add(li);//装载一行的数据到list中
        }
    }

    dataValidationObj.setEmptyMapVar();
    return list;
}

4.DataValidation中的处理,对Excel表格中有效单元格列数的处理

 /**
     *  校验5:校验Excel表格有效单元格数量   DistributeAccess为实体类对象
     */
    public static String verifyCellsNum(int end,String firstCellVal,String type){
        String error = "";
        String str = firstCellVal.substring(0,2);
        if(type.equals("DistributeAccess") && end==28){
            return error;
        }if(type.equals("Distribute") && end==38){
            return error;
        }else if(type.equals("SendedNumber") && end==4 && str.equals("码号")){
            return error;
        }else if(type.equals("SpamMessageFeeReceipt") && end==5 && str.equals("SP")){
            return error;
        }
        return ErrorEnumMessage.COMMONERRORS.getErrorDescribe();
    }

  /**
     * 校验4:单元格为"",也是必填校验
     */
    public static String verifyIsNullCell(int x,int y,String cellValue){
        String error = "";
        if(StringUtils.isBlank(cellValue)){
            String coordinate = DataValidation.getCoordinate(x,y);
            error = coordinate + ErrorEnumMessage.CELLEMPTY.getErrorDescribe();
        }
        return error;
    }

至此,以上为后台对Excel表格中,每一行和每一列数据进行数据处理

因此从Excel表格中获取每行的数据信息,生成list对象集合
Java实现Excel批量导入数据库_第4张图片

根据获得到的对象集合,便可以实现数据批量导入数据库了

你可能感兴趣的:(java)