• Springboot中EasyExcel导出及校验后导入前后台功能实现


    一、引入maven依赖

    1. 在pom.xml中引入maven依赖

    	<properties>
            <poi.version>4.0.0</poi.version>
        </properties>
    		
    	<dependencies>
    		<dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>easyexcel</artifactId>
                <version>2.2.6</version>
            </dependency>
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi</artifactId>
                <version>${poi.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>${poi.version}</version>
            </dependency>
            <dependency>
                <groupId>cn.afterturn</groupId>
                <artifactId>easypoi-base</artifactId>
                <version>${poi.version}</version>
            </dependency>
       	</dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    二、实体类及工具类

    1. 导入时的自定义校验注解

    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.Target;
    
    import static java.lang.annotation.RetentionPolicy.RUNTIME;
    
    /**
     * @author Mioky
     */
    @Target(ElementType.FIELD)
    @Retention(RUNTIME)
    @Documented
    public @interface ExamStemDtoAnnotation {
    
        // 校验是否为空
        boolean validIsBlank() default false;
    
        // 校验是否为布尔类型的值
        boolean validIsBoolean() default false;
    
        // 校验是否为时间格式
        boolean validIsTime() default false;
    
        // 是否校验间隔为逗号
        boolean validIsSplitByComma() default false;
    
        // 是否校验数值是否为整数
        boolean validIsNumber() default false;
    
        // 是否校验数值是否为长整型
        boolean validIsLong() default false;
    
        // 是否校验数值是否为数字或保留两位小数的数字
        boolean validIsDouble() default false;
    
        // 字段描述信息
        String errorDesc() default "";
    
        String timeFormat() default "";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    2. 格式校验工具类

    import cn.hutool.core.util.ObjectUtil;
    import cn.hutool.core.util.ReflectUtil;
    import cn.hutool.core.util.StrUtil;
    import java.lang.reflect.Field;
    import java.time.format.DateTimeFormatter;
    import java.util.List;
    
    import static cn.hutool.core.util.NumberUtil.*;
    
    /**
     * @author Mioky
     */
    public class ExcelValid {
    
        public static void validField(Object object, List<String> errorDescList, Class<?> zClass) throws IllegalAccessException {
    
            Field[] fields = zClass.getDeclaredFields();
    
            for (Field field : fields) {
                // 设置可访问
                field.setAccessible(true);
    
                // 反射进行参数校验,根据自定义注解中的属性值是否为true决定是否校验
                ExamStemDtoAnnotation examStemDtoAnnotation = field.getAnnotation(ExamStemDtoAnnotation.class);
                if (ObjectUtil.isNotNull(examStemDtoAnnotation)) {
                    if (examStemDtoAnnotation.validIsBlank()) {
                        // 字符串是否为空校验
                        String readMsg = (String) field.get(object);
                        if (readMsg!=null && StrUtil.isBlank(readMsg)) {
                            errorDescList.add(examStemDtoAnnotation.errorDesc());
                        } else {
                            if(readMsg==null){
                                errorDescList.add(examStemDtoAnnotation.errorDesc());
                            }else {
                                // 去掉换行
                                String fieldValueStr = readMsg.replaceAll("[\r\n]", "");
                                // 将去除空格后的数据 替换 原数据
                                ReflectUtil.setFieldValue(object, field, fieldValueStr.trim());
                            }
                        }
                    }
    
                    // 布尔类型的值是否为是或否
                    if (examStemDtoAnnotation.validIsBoolean()) {
                        String readMsg = (String) field.get(object);
                        if (readMsg == null || "".equals(readMsg) ) {
                            errorDescList.add(examStemDtoAnnotation.errorDesc());
                        }else {
                            if((!"是".equals(readMsg) && !"否".equals(readMsg))){
                                errorDescList.add(examStemDtoAnnotation.errorDesc());
                            }
                        }
                    }
    
                    // 时间格式是否为指定格式
                    if (examStemDtoAnnotation.validIsTime()) {
                        String timeFormat = examStemDtoAnnotation.timeFormat();
                        String readMsg = (String) field.get(object);
                        if (readMsg==null || "".equals(readMsg)) {
                            String content = examStemDtoAnnotation.errorDesc() + ",时间格式应为:" + timeFormat;
                            errorDescList.add(content);
                        }else {
                            if(!isDateVail(readMsg, timeFormat)){
                                String content = examStemDtoAnnotation.errorDesc() + ",时间格式应为:" + timeFormat;
                                errorDescList.add(content);
                            }
                        }
                    }
    
                    // 值是否为数字
                    if (examStemDtoAnnotation.validIsNumber()) {
                        String readMsg = (String) field.get(object);
                        if (readMsg == null || "".equals(readMsg)) {
                            errorDescList.add(examStemDtoAnnotation.errorDesc());
                        }else {
                            if(!isNumber(readMsg)){
                                errorDescList.add(examStemDtoAnnotation.errorDesc());
                            }
                        }
                    }
    
                    // 值是否为长整型
                    if (examStemDtoAnnotation.validIsLong()) {
                        String readMsg = (String) field.get(object);
                        if (readMsg == null || "".equals(readMsg)) {
                            errorDescList.add(examStemDtoAnnotation.errorDesc());
                        }else {
                            if(!isLong(readMsg)){
                                errorDescList.add(examStemDtoAnnotation.errorDesc());
                                // 将去除空格后的数据 替换 原数据
                                ReflectUtil.setFieldValue(object, field, null);
                            }
                        }
                    }
    
                    // 值是否为数字或double类型的
                    if (examStemDtoAnnotation.validIsDouble()) {
                        String readMsg = (String) field.get(object);
                        if (readMsg == null || "".equals(readMsg)) {
                            errorDescList.add(examStemDtoAnnotation.errorDesc());
                        }else {
                            if(!isInteger(readMsg) && !isDouble(readMsg)){
                                errorDescList.add(examStemDtoAnnotation.errorDesc());
                            }
                        }
                    }
    
                    // 字符串是否为逗号隔开的
                    if (examStemDtoAnnotation.validIsSplitByComma()) {
                        String readMsg = (String) field.get(object);
                        if (readMsg == null || "".equals(readMsg)) {
                            errorDescList.add(examStemDtoAnnotation.errorDesc());
                        }else {
                            if(!isSplitByComma(readMsg)){
                                errorDescList.add(examStemDtoAnnotation.errorDesc());
                            }
                        }
                    }
                }
            }
        }
    
        public static Integer parseBooleanStrToInteger(String str){
            return "是".equals(str)?1:0;
        }
    
        public static Boolean parseBooleanStrToBoolean(String str){
            return "是".equals(str);
        }
    
        private static boolean isNumber(String str) {
            // 这个代码意思是如果没有抛出异常 就证明是数字,抛出异常了那么就不是数字
            // 异常不适合做逻辑判断,不适合做业务逻辑,异常使用不合理,不符合代码规范
            try {
                // parseInt 是将字符串转换为整数类型,返回一个int类型,如果字符串中有非数字类型字符,则会抛出一个NumberFormatException的异常
                if("".equals(str)){
                    return false;
                }else {
                    Integer.parseInt(str);
                }
                return true;
            } catch (NumberFormatException e) {
                e.printStackTrace();
                return false;
            }
        }
    
        private static boolean isDateVail(String date,String format) {
            //用于指定 日期/时间 模式
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern(format);
            boolean flag = true;
            try {
                if("".equals(date)){
                    return false;
                }else {
                    dtf.parse(date);
                }
            } catch (Exception e) {
                flag = false;
            }
            return flag;
        }
    
        private static boolean isSplitByComma(String str) {
            boolean flag = true;
            String comma1 = ",";
            String comma2 = ",";
            try {
                if("".equals(str)){
                    return false;
                }else {
                    if(str.contains(comma1)){
                        String[] split = str.split(comma1);
                        return true;
                    }else if(str.contains(comma2)){
                        String[] split = str.split(comma2);
                        return true;
                    }
                }
            } catch (Exception e) {
                flag = false;
            }
            return flag;
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187

    3. Excel导入的公用监听

    import com.alibaba.excel.context.AnalysisContext;
    import com.alibaba.excel.event.AnalysisEventListener;
    import com.alibaba.excel.read.metadata.holder.ReadRowHolder;
    import lombok.SneakyThrows;
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.stream.Collectors;
    
    /**
     * @author Mioky
     */
    public class ExcelListener<T> extends AnalysisEventListener<T> {
        /**
         * 这个集合用于接收 读取Excel文件得到的数据
         */
        private List<T> list;
        private Class<?> zClass;
        private String sheetName;
        private Boolean checkFlag;
    
        public ExcelListener(List<T> list,Class<?> zClass,String sheetName) {
            this.list = list;
            this.zClass = zClass;
            this.sheetName = sheetName;
            this.checkFlag = true;
        }
    
        /**
         * 这个每一条数据解析都会来调用
         */
        @SneakyThrows
        @Override
        public void invoke(T data, AnalysisContext context) {
            String name = context.readSheetHolder().getSheetName();
            if(!sheetName.equals(name)){
                checkFlag = false;
            }else {
                List<String> errorDescList = new ArrayList<>();
                // 参数校验
                ExcelValid.validField(data,errorDescList,zClass);
                ReadRowHolder readRowHolder = context.readRowHolder();
                Integer rowIndex = readRowHolder.getRowIndex() +1;
                Method setId = zClass.getMethod("setRowIndex", Integer.class);
                setId.invoke(data, rowIndex);
    
                Method setError = zClass.getMethod("setErrorDescList", List.class);
                if(errorDescList.size()>0){
                    errorDescList = errorDescList.stream().distinct().collect(Collectors.toList());
                }
                setError.invoke(data, errorDescList);
                list.add(data);
            }
        }
    
        /**
         * 所有数据解析完成了 都会来调用
         */
        @Override
        public void doAfterAllAnalysed(AnalysisContext context) {
    
        }
    
        public Boolean getCheckFlag() {
            return checkFlag;
        }
    
        public List<T> getList() {
            return list;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    4. 导入时校验失败返回的对象

    import lombok.Data;
    import java.util.List;
    
    /**
     * @author Mioky
     */
    @Data
    public class ErrorData {
    	// 行号
        private Integer row;
        // 校验失败的具体信息 
        private List<String> errorMsgList;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    5. 导入时的校验方法返回的参数

    import lombok.Data;
    import java.util.List;
    
    /**
     * 导入Excel的校验方法返回的参数
     * @author Mioky
     */
    @Data
    public class ImportData {
        List<?> excelList;
        List<ErrorData> errorDataList;
        Boolean checkFlag;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    6.表对象

    import cn.afterturn.easypoi.excel.annotation.Excel;
    import cn.afterturn.easypoi.excel.annotation.ExcelIgnore;
    import com.alibaba.excel.metadata.AbstractCell;
    import com.community.common.excel.ExamStemDtoAnnotation;
    import lombok.Data;
    import lombok.EqualsAndHashCode;
    
    import java.util.List;
    
    /**
     * @author Mioky
     * AbstractCell 中包含rowIndex属性,用于在导入时返回格式有误的数据行
     */
    @EqualsAndHashCode(callSuper = true)
    @Data
    public class FactoryMonthInfoExcel extends AbstractCell {
    
        @ExamStemDtoAnnotation(errorDesc ="管理区域为空" ,validIsBlank = true)
        @Excel(name = "管理区域",orderNum = "1",width = 20)
        private String factoryName;
    
        @ExamStemDtoAnnotation(errorDesc ="区域编号不能为空且只能为数字" ,validIsLong = true)
        @Excel(name = "区域编号",orderNum = "2",width = 30)
        private String factoryId;
    
        @ExamStemDtoAnnotation(errorDesc ="送餐只能为数字",validIsNumber = true)
        @Excel(name = "送餐",orderNum = "3")
        private String foodDelivery;
    
        @ExamStemDtoAnnotation(errorDesc ="关怀数只能为数字" ,validIsNumber = true)
        @Excel(name = "关怀数",orderNum = "4")
        private String careNum;
    
        @ExamStemDtoAnnotation(errorDesc ="加梯数只能为数字" ,validIsNumber = true)
        @Excel(name = "加梯数",orderNum = "5")
        private String laddersNum;
    
        @ExamStemDtoAnnotation(errorDesc ="减排只能为数字" ,validIsNumber = true)
        @Excel(name = "减排",orderNum = "6")
        private String ersNum;
    
        @ExamStemDtoAnnotation(errorDesc ="时间格式错误" ,validIsBlank = true,validIsTime = true,timeFormat="yyyy年MM月")
        @Excel(name = "时间(月)",orderNum = "7",width = 20)
        private String date;
    
        @ExcelIgnore
        private Long id;
    
        @ExcelIgnore
        private List<String> errorDescList;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    三、Excel导出

    1. Controller层代码

     	 /**
         * 导出小区月度指标数据配置Excel
         */
        @GetMapping("/exportFactoryMonthInfoExcel")
        @ApiOperation(value="导出小区月度指标数据配置Excel")
        public void exportFactoryMonthInfoExcel(HttpServletResponse response,Long factoryId) {
            List<FactoryMonthInfoExcel> factoryMonthInfos = iFactoryMonthInfoService.getFactoryMonthInfoExcelList(factoryId);
            ExcelUtil.exportExcel(factoryMonthInfos,"小区月度指标数据配置","小区月度指标数据配置", FactoryMonthInfoExcel.class,"小区月度指标数据配置"+ DateFormatUtil.formatDateToTimeStr(new Date()) +".xls",response);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2. 前台代码(Get)

        // 导出
        exportExcel() {
          var url =
            vueConfig.deal + '://' + vueConfig.webIp + ':' + vueConfig.webPort
          location.href =
            url +
            '/FactoryMonthInfo/exportFactoryMonthInfoExcel?factoryId=' +
            parseInt(this.factoryId)
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3. 前台代码(Post)

    import axios from 'axios'
    import jsFileDownload from 'js-file-download'
    
     // 导出
        exportExcel() {
          var url =
            vueConfig.deal + '://' + vueConfig.webIp + ':' + vueConfig.webPort
          let openUrl = url + '/FactoryTarget/ExportFactoryTarget' // 请求的接口
          axios({
            method: 'post',
            url: openUrl,
            responseType: 'blob', // 返回类型为数据流
            data: this.queryParam, // 需要传参的话,在这传
          }).then((res) => {
            if (res && res.data) {
              // 调用js-file-download下载文件,第一个参数是数据流,第二个参数是文件名
              if (res.headers['content-disposition']) {
                var filename = res.headers['content-disposition'].split(
                  'attachment;filename='
                )[1]
                jsFileDownload(res.data, filename)
              }
            }
          })
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    四、Excel导入

    1. Controller层代码

    	 /**
         * 导入小区月度指标配置数据Excel
         */
        @PostMapping("/importFactoryMonthInfoExcel")
        @ApiOperation(value = "导入小区月度指标配置数据Excel")
        @ResponseBody
        public BoardMessage importFactoryMonthInfoExcel(@RequestParam("file") MultipartFile file) {
            // 校验并获取Excel中的数据
            ImportData importData = iFactoryMonthInfoService.checkExcel(file);
            if (importData != null && importData.getCheckFlag()) {
                List<ErrorData> errorDataList = importData.getErrorDataList();
                if (errorDataList != null && errorDataList.size() > 0) {
                    return new BoardMessage(ErrorCode.getSuccess(), "导入失败!请检查导入文档的格式是否正确", errorDataList, " importFactoryMonthInfoExcel", null);
                } else {
                    List<?> excelList = importData.getExcelList();
                    List<FactoryMonthInfoExcel> successList = new ArrayList<>();
                    for (Object item : excelList) {
                        successList.add((FactoryMonthInfoExcel) item);
                    }
                    // 导入数据
                    Boolean flag = iFactoryMonthInfoService.importFactoryMonthInfoExcel(successList);
                    if (flag) {
                        return new BoardMessage(ErrorCode.getSuccess(), "导入成功", flag, " importFactoryMonthInfoExcel", null);
                    }
                }
            }
            return new BoardMessage(ErrorCode.getFail(), "导入失败!请检查导入文档的格式是否正确", false, "importFactoryMonthInfoExcel", null);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    2. Service层代码

     	ImportData checkExcel(MultipartFile file);
    
        Boolean importFactoryMonthInfoExcel(List<FactoryMonthInfoExcel> successList);
    
    • 1
    • 2
    • 3

    3. ServiceImpl层代码

      		@Override
            @SuppressWarnings("unchecked") // 这个注解可以隐藏new ExcelListener的警告
            public ImportData checkExcel(MultipartFile file) {
                    ImportData importData = new ImportData();
    
                    List<ErrorData> errorDataList = new ArrayList<>();
                    try {
                            // 拿出所有的错误列表,返回所有的报错信息,和行号
                            List<FactoryMonthInfoExcel> factoryMonthInfoExcelList = new ArrayList<>();
    
                            ExcelListener excelListener = new ExcelListener(factoryMonthInfoExcelList, FactoryMonthInfoExcel.class, "小区月度指标数据配置");
                            EasyExcel.read(file.getInputStream(), FactoryMonthInfoExcel.class, excelListener).sheet().headRowNumber(2).doRead();
                            // 判断表名是否相同(没有验证所有表头字段,只是简单校验了表名)
                            Boolean checkFlag = excelListener.getCheckFlag();
                            importData.setCheckFlag(checkFlag);
                            if(checkFlag){
                            List<FactoryMonthInfoExcel> excelList = excelListener.getList();
    
                            if (excelList != null && excelList.size() > 0) {
                                    List<Long> allFactoryIds = factoryPlusService.getSubrangeFactoryIdList(0L);
                                    List<Long> factoryIds = excelList.stream().filter(x -> x.getFactoryId() != null && !"".equals(x.getFactoryId())).map(FactoryMonthInfoExcel::getFactoryId).map(Long::valueOf).collect(Collectors.toList());
                                    // 根据区域编号和时间查询已有数据
                                    List<FactoryMonthInfo> factoryMonthInfo = factoryMonthInfoMapper.getFactoryMonthInfoList(factoryIds);
                                    for (FactoryMonthInfoExcel excelRow : excelList) {
                                            if (excelRow.getFactoryId() != null && !allFactoryIds.contains(Long.valueOf(excelRow.getFactoryId()))) {
                                                    excelRow.getErrorDescList().add("编号为" + excelRow.getFactoryId() + "的区域不存在");
                                            }
    
                                            if (excelRow.getFactoryId() != null && factoryMonthInfo != null && factoryMonthInfo.size() > 0) {
                                                    List<FactoryMonthInfo> collectList = factoryMonthInfo.stream()
                                                            .filter(x -> x.getFactoryId() != null && x.getFactoryName() != null && x.getMonthStr() != null)
                                                            .filter(item ->
                                                                    item.getFactoryName().equals(excelRow.getFactoryName()) &&
                                                                            item.getFactoryId().equals(Long.valueOf(excelRow.getFactoryId())) &&
                                                                            item.getMonthStr().equals(excelRow.getDate())
                                                            ).collect(Collectors.toList());
    
                                                    if (collectList.size() > 0) {
                                                            FactoryMonthInfo target = collectList.get(0);
                                                            excelRow.setId(target.getId());
                                                    }
                                            }
    
                                            // 此处获取监听器中数据格式校验错误的集合
                                            List<String> errorDescList = excelRow.getErrorDescList();
                                            if (errorDescList.size() > 0) {
                                                    ErrorData errorData = new ErrorData();
                                                    errorData.setRow(excelRow.getRowIndex());
                                                    errorData.setErrorMsgList(errorDescList);
                                                    errorDataList.add(errorData);
                                            }
                                    }
                            } else {
                                    ErrorData errorData = new ErrorData();
                                    errorData.setRow(0);
                                    errorData.setErrorMsgList(Collections.singletonList("未读取到数据"));
                                    errorDataList.add(errorData);
                            }
                            importData.setErrorDataList(errorDataList);
                            importData.setExcelList(excelList);
                    }
                    } catch (Exception e) {
                            log.error(Thread.currentThread().getStackTrace()[1].getMethodName() + e.getMessage());
                            ErrorData errorData = new ErrorData();
                            errorData.setRow(0);
                            errorData.setErrorMsgList(Collections.singletonList("导入失败!请检查导入文档的格式是否正确"));
                            errorDataList.add(errorData);
                            importData.setErrorDataList(errorDataList);
                    }
                    return importData;
            }
    
            @Override
            public Boolean importFactoryMonthInfoExcel(List<FactoryMonthInfoExcel> successList) {
                    try {
                            // 此处编写业务逻辑(修改数据库数据)
                            List<FactoryMonthInfo> factoryMonthInfos = new ArrayList<>();
                            for (FactoryMonthInfoExcel factoryMonthInfoExcel : successList) {
                                    FactoryMonthInfo factoryMonthInfo = new FactoryMonthInfo();
                                    BeanUtils.copyProperties(factoryMonthInfoExcel, factoryMonthInfo);
                                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 00:00:00");
                                    factoryMonthInfo.setDate(simpleDateFormat.parse(factoryMonthInfoExcel.getDate()+"01日 00:00:00"));
                                    factoryMonthInfo.setAddTime(new Date());
                                    factoryMonthInfo.setFoodDelivery(Integer.valueOf(factoryMonthInfoExcel.getFoodDelivery()));
                                    factoryMonthInfo.setFactoryId(Long.valueOf(factoryMonthInfoExcel.getFactoryId()));
                                    factoryMonthInfo.setCareNum(Integer.valueOf(factoryMonthInfoExcel.getCareNum()));
                                    factoryMonthInfo.setLaddersNum(Integer.valueOf(factoryMonthInfoExcel.getLaddersNum()));
                                    factoryMonthInfo.setErsNum(Integer.valueOf(factoryMonthInfoExcel.getErsNum()));
                                    factoryMonthInfo.setAddTime(new Date());
                                    factoryMonthInfo.setMenId(0);
                                    factoryMonthInfos.add(factoryMonthInfo);
                            }
                            return saveOrUpdateBatch(factoryMonthInfos);
                    } catch (Exception e) {
                            log.error(Thread.currentThread().getStackTrace()[1].getMethodName() + e.getMessage());
                            return false;
                    }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98

    4. 前台代码

    	 <el-dialog title="导入小区年度数据信息表" :visible.sync="dialog03" width="30%" center :closeOnClickModal="false" :show-close="false" @close="closeDialog03()">
          <el-row :gutter="20">
            <el-col :span="20">
              <el-form style="text-align:center" label-width="60px" ref="uploadformRef">
                <el-form-item>
                  <!-- 导入文件方式 -->
                  <el-upload drag :limit=limitNum :auto-upload="false" accept=".xls,.xlsx" :action="UploadUrl()" :before-upload="beforeUploadFile" :on-change="fileChange" :on-exceed="exceedFile"
                    :on-success="handleSuccess" :on-error="handleError" :file-list="fileList">
                    <i class="el-icon-upload"></i>
                    <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
                    <div class="el-upload__tip" slot="tip">只能上传xlsx/xls文件</div>
                  </el-upload>
                </el-form-item>
              </el-form>
            </el-col>
          </el-row>
          <div slot="footer" class="dialog-footer">
            <el-button size="mini" @click="closeDialog03()">取消</el-button>
            <el-button size="mini" type="primary" @click="uploadFile">立即上传</el-button>
          </div>
        </el-dialog>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
     UploadUrl: function () {
          // 因为action参数是必填项,我们使用二次确认进行文件上传时,直接填上传文件的url会因为没有参数导致api报404,所以这里将action设置为一个返回为空的方法就行,避免抛错
          return ''
        },
        beforeUploadFile(file) {
          // 上传文件之前的钩子, 参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传
          let extension = file.name.substring(file.name.lastIndexOf('.') + 1)
          //   let size = file.size / 1024 / 1024 文件大小
          const whiteList = ['xls', 'xlsx']
          if (whiteList.indexOf(extension) === -1) {
            this.$message.error('上传文件只能是xls、xlsx格式')
            return false
          }
        },
        fileChange(file, fileList) {
          // 文件状态改变时的钩子
          this.fileList.push(file.raw)
        },
        exceedFile(files, fileList) {
          // 文件超出个数限制时的钩子
          this.$message.warning(
            `只能选择 ${this.limitNum} 个文件,当前共选择了 ${
              files.length + fileList.length
            }`
          )
        },
        handleSuccess(res, file, fileList) {
          // 文件上传成功时的钩子
          this.$message.success('文件上传成功')
        },
        handleError(err, file, fileList) {
          // 文件上传失败时的钩子
          this.$message.error('文件上传失败')
        },
        // 确认上传
        uploadFile() {
          if (this.fileList.length === 0) {
            this.$message.warning('请选择需要上传的文件')
          } else {
            let form = new FormData()
            this.fileList.map((element) => {
              form.append('file', element)
            })
            xiaoquYmData.importFactoryTargetExcel(form).then((val) => {
              if (val.status == 0) {
                if (val.data == true) {
                  this.$message({
                    type: 'success',
                    message: '导入成功!',
                  })
                  this.dialog03 = false
                } else {
                  this.showErrowInfor(val.data)
                }
              } else {
                this.$message({
                  type: 'success',
                  message: '导入失败,请重新操作!',
                })
              }
            })
          }
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
  • 相关阅读:
    Jenkins 发布 Gitee 上的 SpringBoot 项目全过程(详细)
    【工具】OCR方法|不用下载额外的软件,提取扫描中英文PDF的目录文本的最优解!(一)
    kaggle大模型竞赛优胜方案总结与思考
    Flink的六种物理分区策略
    如何排查SQL慢查询?
    想要精通算法和SQL的成长之路 - 行程和用户
    微信小程序 如何在组件中实现 上拉加载下一页和下拉触底
    EXCEL常用快捷键
    Sentinel安装与部署
    VS生成动态库(VS2022、CUDA、Lib)
  • 原文地址:https://blog.csdn.net/qq_45433217/article/details/125374708