• Java实现Excel的导入以及导出,极其简单


    文章目录


    一、环境准备

    1、我这里使用的是Spring Boot开发的,创建工程自行创建
    2、导入相关依赖

             
                
                    org.springframework.boot
                    spring-boot-starter-web
                    2.3.6.RELEASE
                
    
              
                
                    org.apache.poi
                    poi-ooxml
                    4.1.2
                
                
                
                
                    cn.hutool
                    hutool-all
                    5.3.8
                
                
           	   
                
                    mysql
                    mysql-connector-java
                    8.0.22
                
                
                
                
                    org.projectlombok
                    lombok
                    1.18.16
                
                
              
                
                    commons-io
                    commons-io
                    2.11.0
                
    
    • 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

    3、yml配置数据库

    # 数据源配置
    spring:
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        url: jdbc:mysql://120.25.228.68:3306/ExcelTest?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
        username: root
        password: root
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4、导入Excel相关工具类
    如下四个
    在这里插入图片描述
    ExcelClassField

    package com.geesun.utils;
    
    import java.util.LinkedHashMap;
    
    /**
     * @author Mr.ZJW
     * @date 2021/12/17
     */
    public class ExcelClassField {
    
        /** 字段名称 */
        private String fieldName;
    
        /** 表头名称 */
        private String name;
    
        /** 映射关系 */
        private LinkedHashMap kvMap;
    
        /** 示例值 */
        private Object example;
    
        /** 排序 */
        private int sort;
    
        /** 是否为注解字段:0-否,1-是 */
        private int hasAnnotation;
    
        public String getFieldName() {
            return fieldName;
        }
    
        public void setFieldName(String fieldName) {
            this.fieldName = fieldName;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public LinkedHashMap getKvMap() {
            return kvMap;
        }
    
        public void setKvMap(LinkedHashMap kvMap) {
            this.kvMap = kvMap;
        }
    
        public Object getExample() {
            return example;
        }
    
        public void setExample(Object example) {
            this.example = example;
        }
    
        public int getSort() {
            return sort;
        }
    
        public void setSort(int sort) {
            this.sort = sort;
        }
    
        public int getHasAnnotation() {
            return hasAnnotation;
        }
    
        public void setHasAnnotation(int hasAnnotation) {
            this.hasAnnotation = hasAnnotation;
        }
    
    }
    
    • 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

    ExcelExport

    package com.geesun.utils;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * @author Mr.ZJW
     * @date 2021/12/17
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ExcelExport {
    
        /** 字段名称 */
        String value();
    
        /** 导出排序先后: 数字越小越靠前(默认按Java类字段顺序导出) */
        int sort() default 0;
    
        /** 导出映射,格式如:0-未知;1-男;2-女 */
        String kv() default "";
    
        /** 导出模板示例值(有值的话,直接取该值,不做映射) */
        String example() 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

    ExcelImport

    package com.geesun.utils;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * @author Mr.ZJW
     * @date 2021/12/17
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ExcelImport {
    
        /** 字段名称 */
        String value();
    
        /** 导出映射,格式如:0-未知;1-男;2-女 */
        String kv() default "";
    
        /** 是否为必填字段(默认为非必填) */
        boolean required() default false;
    
        /** 最大长度(默认255) */
        int maxLength() default 255;
    
        /** 导入唯一性验证(多个字段则取联合验证) */
        boolean unique() default 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

    ExcelUtils

    package com.geesun.utils;
    
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.lang.reflect.Field;
    import java.math.BigDecimal;
    import java.math.RoundingMode;
    import java.net.URL;
    import java.text.NumberFormat;
    import java.text.SimpleDateFormat;
    import java.util.*;
    import java.util.Map.Entry;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServletResponse;
    import org.apache.poi.hssf.usermodel.HSSFDataValidation;
    import org.apache.poi.hssf.usermodel.HSSFWorkbook;
    import org.apache.poi.poifs.filesystem.POIFSFileSystem;
    import org.apache.poi.ss.usermodel.Cell;
    import org.apache.poi.ss.usermodel.CellStyle;
    import org.apache.poi.ss.usermodel.CellType;
    import org.apache.poi.ss.usermodel.ClientAnchor.AnchorType;
    import org.apache.poi.ss.usermodel.DataValidation;
    import org.apache.poi.ss.usermodel.DataValidationConstraint;
    import org.apache.poi.ss.usermodel.DataValidationHelper;
    import org.apache.poi.ss.usermodel.Drawing;
    import org.apache.poi.ss.usermodel.FillPatternType;
    import org.apache.poi.ss.usermodel.HorizontalAlignment;
    import org.apache.poi.ss.usermodel.IndexedColors;
    import org.apache.poi.ss.usermodel.Row;
    import org.apache.poi.ss.usermodel.Sheet;
    import org.apache.poi.ss.usermodel.VerticalAlignment;
    import org.apache.poi.ss.usermodel.Workbook;
    import org.apache.poi.ss.util.CellRangeAddress;
    import org.apache.poi.ss.util.CellRangeAddressList;
    import org.apache.poi.xssf.streaming.SXSSFWorkbook;
    import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
    import org.apache.poi.xssf.usermodel.XSSFWorkbook;
    import org.springframework.web.multipart.MultipartFile;
    import com.alibaba.fastjson.JSONArray;
    import com.alibaba.fastjson.JSONObject;
    
    /**
     * Excel导入导出工具类
     * @author Mr.ZJW
     * @date 2021/12/17
     */
    public class ExcelUtils {
    
        private static final String XLSX = ".xlsx";
        private static final String XLS = ".xls";
        public static final String ROW_MERGE = "row_merge";
        public static final String COLUMN_MERGE = "column_merge";
        private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
        private static final String ROW_NUM = "rowNum";
        private static final String ROW_DATA = "rowData";
        private static final String ROW_TIPS = "rowTips";
        private static final int CELL_OTHER = 0;
        private static final int CELL_ROW_MERGE = 1;
        private static final int CELL_COLUMN_MERGE = 2;
        private static final int IMG_HEIGHT = 30;
        private static final int IMG_WIDTH = 30;
        private static final char LEAN_LINE = '/';
        private static final int BYTES_DEFAULT_LENGTH = 10240;
        private static final NumberFormat NUMBER_FORMAT = NumberFormat.getNumberInstance();
    
    
        public static  List readFile(File file, Class clazz) throws Exception {
            JSONArray array = readFile(file);
            return getBeanList(array, clazz);
        }
    
        public static  List readMultipartFile(MultipartFile mFile, Class clazz) throws Exception {
            JSONArray array = readMultipartFile(mFile);
            return getBeanList(array, clazz);
        }
    
        public static JSONArray readFile(File file) throws Exception {
            return readExcel(null, file);
        }
    
        public static JSONArray readMultipartFile(MultipartFile mFile) throws Exception {
            return readExcel(mFile, null);
        }
    
        private static  List getBeanList(JSONArray array, Class clazz) throws Exception {
            List list = new ArrayList<>();
            Map uniqueMap = new HashMap<>(16);
            for (int i = 0; i < array.size(); i++) {
                list.add(getBean(clazz, array.getJSONObject(i), uniqueMap));
            }
            return list;
        }
    
        /**
         * 获取每个对象的数据
         */
        private static  T getBean(Class c, JSONObject obj, Map uniqueMap) throws Exception {
            T t = c.newInstance();
            Field[] fields = c.getDeclaredFields();
            List errMsgList = new ArrayList<>();
            boolean hasRowTipsField = false;
            StringBuilder uniqueBuilder = new StringBuilder();
            int rowNum = 0;
            for (Field field : fields) {
                // 行号
                if (field.getName().equals(ROW_NUM)) {
                    rowNum = obj.getInteger(ROW_NUM);
                    field.setAccessible(true);
                    field.set(t, rowNum);
                    continue;
                }
                // 是否需要设置异常信息
                if (field.getName().equals(ROW_TIPS)) {
                    hasRowTipsField = true;
                    continue;
                }
                // 原始数据
                if (field.getName().equals(ROW_DATA)) {
                    field.setAccessible(true);
                    field.set(t, obj.toString());
                    continue;
                }
                // 设置对应属性值
                setFieldValue(t,field, obj, uniqueBuilder, errMsgList);
            }
            // 数据唯一性校验
            if (uniqueBuilder.length() > 0) {
                if (uniqueMap.containsValue(uniqueBuilder.toString())) {
                    Set rowNumKeys = uniqueMap.keySet();
                    for (Integer num : rowNumKeys) {
                        if (uniqueMap.get(num).equals(uniqueBuilder.toString())) {
                            errMsgList.add(String.format("数据唯一性校验失败,(%s)与第%s行重复)", uniqueBuilder, num));
                        }
                    }
                } else {
                    uniqueMap.put(rowNum, uniqueBuilder.toString());
                }
            }
            // 失败处理
            if (errMsgList.isEmpty() && !hasRowTipsField) {
                return t;
            }
            StringBuilder sb = new StringBuilder();
            int size = errMsgList.size();
            for (int i = 0; i < size; i++) {
                if (i == size - 1) {
                    sb.append(errMsgList.get(i));
                } else {
                    sb.append(errMsgList.get(i)).append(";");
                }
            }
            // 设置错误信息
            for (Field field : fields) {
                if (field.getName().equals(ROW_TIPS)) {
                    field.setAccessible(true);
                    field.set(t, sb.toString());
                }
            }
            return t;
        }
    
        private static  void setFieldValue(T t, Field field, JSONObject obj, StringBuilder uniqueBuilder, List errMsgList) {
            // 获取 ExcelImport 注解属性
            ExcelImport annotation = field.getAnnotation(ExcelImport.class);
            if (annotation == null) {
                return;
            }
            String cname = annotation.value();
            if (cname.trim().length() == 0) {
                return;
            }
            // 获取具体值
            String val = null;
            if (obj.containsKey(cname)) {
                val = getString(obj.getString(cname));
            }
            if (val == null) {
                return;
            }
            field.setAccessible(true);
            // 判断是否必填
            boolean require = annotation.required();
            if (require && val.isEmpty()) {
                errMsgList.add(String.format("[%s]不能为空", cname));
                return;
            }
            // 数据唯一性获取
            boolean unique = annotation.unique();
            if (unique) {
                if (uniqueBuilder.length() > 0) {
                    uniqueBuilder.append("--").append(val);
                } else {
                    uniqueBuilder.append(val);
                }
            }
            // 判断是否超过最大长度
            int maxLength = annotation.maxLength();
            if (maxLength > 0 && val.length() > maxLength) {
                errMsgList.add(String.format("[%s]长度不能超过%s个字符(当前%s个字符)", cname, maxLength, val.length()));
            }
            // 判断当前属性是否有映射关系
            LinkedHashMap kvMap = getKvMap(annotation.kv());
            if (!kvMap.isEmpty()) {
                boolean isMatch = false;
                for (String key : kvMap.keySet()) {
                    if (kvMap.get(key).equals(val)) {
                        val = key;
                        isMatch = true;
                        break;
                    }
                }
                if (!isMatch) {
                    errMsgList.add(String.format("[%s]的值不正确(当前值为%s)", cname, val));
                    return;
                }
            }
            // 其余情况根据类型赋值
            String fieldClassName = field.getType().getSimpleName();
            try {
                if ("String".equalsIgnoreCase(fieldClassName)) {
                    field.set(t, val);
                } else if ("boolean".equalsIgnoreCase(fieldClassName)) {
                    field.set(t, Boolean.valueOf(val));
                } else if ("int".equalsIgnoreCase(fieldClassName) || "Integer".equals(fieldClassName)) {
                    try {
                        field.set(t, Integer.valueOf(val));
                    } catch (NumberFormatException e) {
                        errMsgList.add(String.format("[%s]的值格式不正确(当前值为%s)", cname, val));
                    }
                } else if ("double".equalsIgnoreCase(fieldClassName)) {
                    field.set(t, Double.valueOf(val));
                } else if ("long".equalsIgnoreCase(fieldClassName)) {
                    field.set(t, Long.valueOf(val));
                } else if ("BigDecimal".equalsIgnoreCase(fieldClassName)) {
                    field.set(t, new BigDecimal(val));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        private static JSONArray readExcel(MultipartFile mFile, File file) throws IOException {
            boolean fileNotExist = (file == null || !file.exists());
            if (mFile == null && fileNotExist) {
                return new JSONArray();
            }
            // 解析表格数据
            InputStream in;
            String fileName;
            if (mFile != null) {
                // 上传文件解析
                in = mFile.getInputStream();
                fileName = getString(mFile.getOriginalFilename()).toLowerCase();
            } else {
                // 本地文件解析
                in = new FileInputStream(file);
                fileName = file.getName().toLowerCase();
            }
            Workbook book;
            if (fileName.endsWith(XLSX)) {
                book = new XSSFWorkbook(in);
            } else if (fileName.endsWith(XLS)) {
                POIFSFileSystem poifsFileSystem = new POIFSFileSystem(in);
                book = new HSSFWorkbook(poifsFileSystem);
            } else {
                return new JSONArray();
            }
            JSONArray array = read(book);
            book.close();
            in.close();
            return array;
        }
    
        private static JSONArray read(Workbook book) {
            // 获取 Excel 文件第一个 Sheet 页面
            Sheet sheet = book.getSheetAt(0);
            return readSheet(sheet);
        }
    
        private static JSONArray readSheet(Sheet sheet) {
            // 首行下标
            int rowStart = sheet.getFirstRowNum();
            // 尾行下标
            int rowEnd = sheet.getLastRowNum();
            // 获取表头行
            Row headRow = sheet.getRow(rowStart);
            if (headRow == null) {
                return new JSONArray();
            }
            int cellStart = headRow.getFirstCellNum();
            int cellEnd = headRow.getLastCellNum();
            Map keyMap = new HashMap<>();
            for (int j = cellStart; j < cellEnd; j++) {
                // 获取表头数据
                String val = getCellValue(headRow.getCell(j));
                if (val != null && val.trim().length() != 0) {
                    keyMap.put(j, val);
                }
            }
            // 如果表头没有数据则不进行解析
            if (keyMap.isEmpty()) {
                return (JSONArray) Collections.emptyList();
            }
            // 获取每行JSON对象的值
            JSONArray array = new JSONArray();
            // 如果首行与尾行相同,表明只有一行,返回表头数据
            if (rowStart == rowEnd) {
                JSONObject obj = new JSONObject();
                // 添加行号
                obj.put(ROW_NUM, 1);
                for (int i : keyMap.keySet()) {
                    obj.put(keyMap.get(i), "");
                }
                array.add(obj);
                return array;
            }
            for (int i = rowStart + 1; i <= rowEnd; i++) {
                Row eachRow = sheet.getRow(i);
                JSONObject obj = new JSONObject();
                // 添加行号
                obj.put(ROW_NUM, i + 1);
                StringBuilder sb = new StringBuilder();
                for (int k = cellStart; k < cellEnd; k++) {
                    if (eachRow != null) {
                        String val = getCellValue(eachRow.getCell(k));
                        // 所有数据添加到里面,用于判断该行是否为空
                        sb.append(val);
                        obj.put(keyMap.get(k), val);
                    }
                }
                if (sb.length() > 0) {
                    array.add(obj);
                }
            }
            return array;
        }
    
        private static String getCellValue(Cell cell) {
            // 空白或空
            if (cell == null || cell.getCellTypeEnum() == CellType.BLANK) {
                return "";
            }
            // String类型
            if (cell.getCellTypeEnum() == CellType.STRING) {
                String val = cell.getStringCellValue();
                if (val == null || val.trim().length() == 0) {
                    return "";
                }
                return val.trim();
            }
            // 数字类型
            if (cell.getCellTypeEnum() == CellType.NUMERIC) {
                // 科学计数法类型
                return NUMBER_FORMAT.format(cell.getNumericCellValue()) + "";
            }
            // 布尔值类型
            if (cell.getCellTypeEnum() == CellType.BOOLEAN) {
                return cell.getBooleanCellValue() + "";
            }
            // 错误类型
            return cell.getCellFormula();
        }
    
        public static  void exportTemplate(HttpServletResponse response, String fileName, Class clazz) {
            exportTemplate(response, fileName, fileName, clazz, false);
        }
    
        public static  void exportTemplate(HttpServletResponse response, String fileName, String sheetName,
                                              Class clazz) {
            exportTemplate(response, fileName, sheetName, clazz, false);
        }
    
        public static  void exportTemplate(HttpServletResponse response, String fileName, Class clazz,
                                              boolean isContainExample) {
            exportTemplate(response, fileName, fileName, clazz, isContainExample);
        }
    
        public static  void exportTemplate(HttpServletResponse response, String fileName, String sheetName,
                                              Class clazz, boolean isContainExample) {
            // 获取表头字段
            List headFieldList = getExcelClassFieldList(clazz);
            // 获取表头数据和示例数据
            List> sheetDataList = new ArrayList<>();
            List headList = new ArrayList<>();
            List exampleList = new ArrayList<>();
            Map> selectMap = new LinkedHashMap<>();
            for (int i = 0; i < headFieldList.size(); i++) {
                ExcelClassField each = headFieldList.get(i);
                headList.add(each.getName());
                exampleList.add(each.getExample());
                LinkedHashMap kvMap = each.getKvMap();
                if (kvMap != null && kvMap.size() > 0) {
                    selectMap.put(i, new ArrayList<>(kvMap.values()));
                }
            }
            sheetDataList.add(headList);
            if (isContainExample) {
                sheetDataList.add(exampleList);
            }
            // 导出数据
            export(response, fileName, sheetName, sheetDataList, selectMap);
        }
    
        private static  List getExcelClassFieldList(Class clazz) {
            // 解析所有字段
            Field[] fields = clazz.getDeclaredFields();
            boolean hasExportAnnotation = false;
            Map> map = new LinkedHashMap<>();
            List sortList = new ArrayList<>();
            for (Field field : fields) {
                ExcelClassField cf = getExcelClassField(field);
                if (cf.getHasAnnotation() == 1) {
                    hasExportAnnotation = true;
                }
                int sort = cf.getSort();
                if (map.containsKey(sort)) {
                    map.get(sort).add(cf);
                } else {
                    List list = new ArrayList<>();
                    list.add(cf);
                    sortList.add(sort);
                    map.put(sort, list);
                }
            }
            Collections.sort(sortList);
            // 获取表头
            List headFieldList = new ArrayList<>();
            if (hasExportAnnotation) {
                for (Integer sort : sortList) {
                    for (ExcelClassField cf : map.get(sort)) {
                        if (cf.getHasAnnotation() == 1) {
                            headFieldList.add(cf);
                        }
                    }
                }
            } else {
                headFieldList.addAll(map.get(0));
            }
            return headFieldList;
        }
    
        private static ExcelClassField getExcelClassField(Field field) {
            ExcelClassField cf = new ExcelClassField();
            String fieldName = field.getName();
            cf.setFieldName(fieldName);
            ExcelExport annotation = field.getAnnotation(ExcelExport.class);
            // 无 ExcelExport 注解情况
            if (annotation == null) {
                cf.setHasAnnotation(0);
                cf.setName(fieldName);
                cf.setSort(0);
                return cf;
            }
            // 有 ExcelExport 注解情况
            cf.setHasAnnotation(1);
            cf.setName(annotation.value());
            String example = getString(annotation.example());
            if (!example.isEmpty()) {
                if (isNumeric(example)) {
                    cf.setExample(Double.valueOf(example));
                } else {
                    cf.setExample(example);
                }
            } else {
                cf.setExample("");
            }
            cf.setSort(annotation.sort());
            // 解析映射
            String kv = getString(annotation.kv());
            cf.setKvMap(getKvMap(kv));
            return cf;
        }
    
        private static LinkedHashMap getKvMap(String kv) {
            LinkedHashMap kvMap = new LinkedHashMap<>();
            if (kv.isEmpty()) {
                return kvMap;
            }
            String[] kvs = kv.split(";");
            if (kvs.length == 0) {
                return kvMap;
            }
            for (String each : kvs) {
                String[] eachKv = getString(each).split("-");
                if (eachKv.length != 2) {
                    continue;
                }
                String k = eachKv[0];
                String v = eachKv[1];
                if (k.isEmpty() || v.isEmpty()) {
                    continue;
                }
                kvMap.put(k, v);
            }
            return kvMap;
        }
    
        /**
         * 导出表格到本地
         *
         * @param file      本地文件对象
         * @param sheetData 导出数据
         */
        public static void exportFile(File file, List> sheetData) {
            if (file == null) {
                System.out.println("文件创建失败");
                return;
            }
            if (sheetData == null) {
                sheetData = new ArrayList<>();
            }
            export(null, file, file.getName(), file.getName(), sheetData, null);
        }
    
        /**
         * 导出表格到本地
         *
         * @param       导出数据类似,和K类型保持一致
         * @param filePath 文件父路径(如:D:/doc/excel/)
         * @param fileName 文件名称(不带尾缀,如:学生表)
         * @param list     导出数据
         * @throws IOException IO异常
         */
        public static  File exportFile(String filePath, String fileName, List list) throws IOException {
            File file = getFile(filePath, fileName);
            List> sheetData = getSheetData(list);
            exportFile(file, sheetData);
            return file;
        }
    
        /**
         * 获取文件
         *
         * @param filePath filePath 文件父路径(如:D:/doc/excel/)
         * @param fileName 文件名称(不带尾缀,如:用户表)
         * @return 本地File文件对象
         */
        private static File getFile(String filePath, String fileName) throws IOException {
            String dirPath = getString(filePath);
            String fileFullPath;
            if (dirPath.isEmpty()) {
                fileFullPath = fileName;
            } else {
                // 判定文件夹是否存在,如果不存在,则级联创建
                File dirFile = new File(dirPath);
                if (!dirFile.exists()) {
                    dirFile.mkdirs();
                }
                // 获取文件夹全名
                if (dirPath.endsWith(String.valueOf(LEAN_LINE))) {
                    fileFullPath = dirPath + fileName + XLSX;
                } else {
                    fileFullPath = dirPath + LEAN_LINE + fileName + XLSX;
                }
            }
            System.out.println(fileFullPath);
            File file = new File(fileFullPath);
            if (!file.exists()) {
                file.createNewFile();
            }
            return file;
        }
    
        private static  List> getSheetData(List list) {
            // 获取表头字段
            List excelClassFieldList = getExcelClassFieldList(list.get(0).getClass());
            List headFieldList = new ArrayList<>();
            List headList = new ArrayList<>();
            Map headFieldMap = new HashMap<>();
            for (ExcelClassField each : excelClassFieldList) {
                String fieldName = each.getFieldName();
                headFieldList.add(fieldName);
                headFieldMap.put(fieldName, each);
                headList.add(each.getName());
            }
            // 添加表头名称
            List> sheetDataList = new ArrayList<>();
            sheetDataList.add(headList);
            // 获取表数据
            for (T t : list) {
                Map fieldDataMap = getFieldDataMap(t);
                Set fieldDataKeys = fieldDataMap.keySet();
                List rowList = new ArrayList<>();
                for (String headField : headFieldList) {
                    if (!fieldDataKeys.contains(headField)) {
                        continue;
                    }
                    Object data = fieldDataMap.get(headField);
                    if (data == null) {
                        rowList.add("");
                        continue;
                    }
                    ExcelClassField cf = headFieldMap.get(headField);
                    // 判断是否有映射关系
                    LinkedHashMap kvMap = cf.getKvMap();
                    if (kvMap == null || kvMap.isEmpty()) {
                        rowList.add(data);
                        continue;
                    }
                    String val = kvMap.get(data.toString());
                    if (isNumeric(val)) {
                        rowList.add(Double.valueOf(val));
                    } else {
                        rowList.add(val);
                    }
                }
                sheetDataList.add(rowList);
            }
            return sheetDataList;
        }
    
        private static  Map getFieldDataMap(T t) {
            Map map = new HashMap<>();
            Field[] fields = t.getClass().getDeclaredFields();
            try {
                for (Field field : fields) {
                    String fieldName = field.getName();
                    field.setAccessible(true);
                    Object object = field.get(t);
                    map.put(fieldName, object);
                }
            } catch (IllegalArgumentException | IllegalAccessException e) {
                e.printStackTrace();
            }
            return map;
        }
    
        public static void exportEmpty(HttpServletResponse response, String fileName) {
            List> sheetDataList = new ArrayList<>();
            List headList = new ArrayList<>();
            headList.add("导出无数据");
            sheetDataList.add(headList);
            export(response, fileName, sheetDataList);
        }
    
        public static void export(HttpServletResponse response, String fileName, List> sheetDataList) {
            export(response, fileName, fileName, sheetDataList, null);
        }
    
        public static void export(HttpServletResponse response, String fileName, String sheetName,
                                  List> sheetDataList) {
            export(response, fileName, sheetName, sheetDataList, null);
        }
    
        public static void export(HttpServletResponse response, String fileName, String sheetName,
                                  List> sheetDataList, Map> selectMap) {
            export(response, null, fileName, sheetName, sheetDataList, selectMap);
        }
    
        public static  void export(HttpServletResponse response, String fileName, List list, Class template) {
            // list 是否为空
            boolean lisIsEmpty = list == null || list.isEmpty();
            // 如果模板数据为空,且导入的数据为空,则导出空文件
            if (template == null && lisIsEmpty) {
                exportEmpty(response, fileName);
                return;
            }
            // 如果 list 数据,则导出模板数据
            if (lisIsEmpty) {
                exportTemplate(response, fileName, template);
                return;
            }
            // 导出数据
            List> sheetDataList = getSheetData(list);
            export(response, fileName, sheetDataList);
        }
    
        public static void export(HttpServletResponse response, String fileName, List> sheetDataList, Map> selectMap) {
            export(response, fileName, fileName, sheetDataList, selectMap);
        }
    
        private static void export(HttpServletResponse response, File file, String fileName, String sheetName,
                                   List> sheetDataList, Map> selectMap) {
            // 整个 Excel 表格 book 对象
            SXSSFWorkbook book = new SXSSFWorkbook();
            // 每个 Sheet 页
            Sheet sheet = book.createSheet(sheetName);
            Drawing patriarch = sheet.createDrawingPatriarch();
            // 设置表头背景色(灰色)
            CellStyle headStyle = book.createCellStyle();
            headStyle.setFillForegroundColor(IndexedColors.GREY_80_PERCENT.index);
            headStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            headStyle.setAlignment(HorizontalAlignment.CENTER);
            headStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.index);
            // 设置表身背景色(默认色)
            CellStyle rowStyle = book.createCellStyle();
            rowStyle.setAlignment(HorizontalAlignment.CENTER);
            rowStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            // 设置表格列宽度(默认为15个字节)
            sheet.setDefaultColumnWidth(15);
            // 创建合并算法数组
            int rowLength = sheetDataList.size();
            int columnLength = sheetDataList.get(0).size();
            int[][] mergeArray = new int[rowLength][columnLength];
            for (int i = 0; i < sheetDataList.size(); i++) {
                // 每个 Sheet 页中的行数据
                Row row = sheet.createRow(i);
                List rowList = sheetDataList.get(i);
                for (int j = 0; j < rowList.size(); j++) {
                    // 每个行数据中的单元格数据
                    Object o = rowList.get(j);
                    int v = 0;
                    if (o instanceof URL) {
                        // 如果要导出图片的话, 链接需要传递 URL 对象
                        setCellPicture(book, row, patriarch, i, j, (URL) o);
                    } else {
                        Cell cell = row.createCell(j);
                        if (i == 0) {
                            // 第一行为表头行,采用灰色底背景
                            v = setCellValue(cell, o, headStyle);
                        } else {
                            // 其他行为数据行,默认白底色
                            v = setCellValue(cell, o, rowStyle);
                        }
                    }
                    mergeArray[i][j] = v;
                }
            }
            // 合并单元格
            mergeCells(sheet, mergeArray);
            // 设置下拉列表
            setSelect(sheet, selectMap);
            // 写数据
            if (response != null) {
                // 前端导出
                try {
                    write(response, book, fileName);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                // 本地导出
                FileOutputStream fos;
                try {
                    fos = new FileOutputStream(file);
                    ByteArrayOutputStream ops = new ByteArrayOutputStream();
                    book.write(ops);
                    fos.write(ops.toByteArray());
                    fos.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
        /**
         * 合并当前Sheet页的单元格
         *
         * @param sheet      当前 sheet 页
         * @param mergeArray 合并单元格算法
         */
        private static void mergeCells(Sheet sheet, int[][] mergeArray) {
            // 横向合并
            for (int x = 0; x < mergeArray.length; x++) {
                int[] arr = mergeArray[x];
                boolean merge = false;
                int y1 = 0;
                int y2 = 0;
                for (int y = 0; y < arr.length; y++) {
                    int value = arr[y];
                    if (value == CELL_COLUMN_MERGE) {
                        if (!merge) {
                            y1 = y;
                        }
                        y2 = y;
                        merge = true;
                    } else {
                        merge = false;
                        if (y1 > 0) {
                            sheet.addMergedRegion(new CellRangeAddress(x, x, (y1 - 1), y2));
                        }
                        y1 = 0;
                        y2 = 0;
                    }
                }
                if (y1 > 0) {
                    sheet.addMergedRegion(new CellRangeAddress(x, x, (y1 - 1), y2));
                }
            }
            // 纵向合并
            int xLen = mergeArray.length;
            int yLen = mergeArray[0].length;
            for (int y = 0; y < yLen; y++) {
                boolean merge = false;
                int x1 = 0;
                int x2 = 0;
                for (int x = 0; x < xLen; x++) {
                    int value = mergeArray[x][y];
                    if (value == CELL_ROW_MERGE) {
                        if (!merge) {
                            x1 = x;
                        }
                        x2 = x;
                        merge = true;
                    } else {
                        merge = false;
                        if (x1 > 0) {
                            sheet.addMergedRegion(new CellRangeAddress((x1 - 1), x2, y, y));
                        }
                        x1 = 0;
                        x2 = 0;
                    }
                }
                if (x1 > 0) {
                    sheet.addMergedRegion(new CellRangeAddress((x1 - 1), x2, y, y));
                }
            }
        }
    
        private static void write(HttpServletResponse response, SXSSFWorkbook book, String fileName) throws IOException {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            String name = new String(fileName.getBytes("GBK"), "ISO8859_1") + XLSX;
            response.addHeader("Content-Disposition", "attachment;filename=" + name);
            ServletOutputStream out = response.getOutputStream();
            book.write(out);
            out.flush();
            out.close();
        }
    
        private static int setCellValue(Cell cell, Object o, CellStyle style) {
            // 设置样式
            cell.setCellStyle(style);
            // 数据为空时
            if (o == null) {
                cell.setCellType(CellType.STRING);
                cell.setCellValue("");
                return CELL_OTHER;
            }
            // 是否为字符串
            if (o instanceof String) {
                String s = o.toString();
                if (isNumeric(s)) {
                    cell.setCellType(CellType.NUMERIC);
                    cell.setCellValue(Double.parseDouble(s));
                    return CELL_OTHER;
                } else {
                    cell.setCellType(CellType.STRING);
                    cell.setCellValue(s);
                }
                if (s.equals(ROW_MERGE)) {
                    return CELL_ROW_MERGE;
                } else if (s.equals(COLUMN_MERGE)) {
                    return CELL_COLUMN_MERGE;
                } else {
                    return CELL_OTHER;
                }
            }
            // 是否为字符串
            if (o instanceof Integer || o instanceof Long || o instanceof Double || o instanceof Float) {
                cell.setCellType(CellType.NUMERIC);
                cell.setCellValue(Double.parseDouble(o.toString()));
                return CELL_OTHER;
            }
            // 是否为Boolean
            if (o instanceof Boolean) {
                cell.setCellType(CellType.BOOLEAN);
                cell.setCellValue((Boolean) o);
                return CELL_OTHER;
            }
            // 如果是BigDecimal,则默认3位小数
            if (o instanceof BigDecimal) {
                cell.setCellType(CellType.NUMERIC);
                cell.setCellValue(((BigDecimal) o).setScale(3, RoundingMode.HALF_UP).doubleValue());
                return CELL_OTHER;
            }
            // 如果是Date数据,则显示格式化数据
            if (o instanceof Date) {
                cell.setCellType(CellType.STRING);
                cell.setCellValue(formatDate((Date) o));
                return CELL_OTHER;
            }
            // 如果是其他,则默认字符串类型
            cell.setCellType(CellType.STRING);
            cell.setCellValue(o.toString());
            return CELL_OTHER;
        }
    
        private static void setCellPicture(SXSSFWorkbook wb, Row sr, Drawing patriarch, int x, int y, URL url) {
            // 设置图片宽高
            sr.setHeight((short) (IMG_WIDTH * IMG_HEIGHT));
            // (jdk1.7版本try中定义流可自动关闭)
            try (InputStream is = url.openStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
                byte[] buff = new byte[BYTES_DEFAULT_LENGTH];
                int rc;
                while ((rc = is.read(buff, 0, BYTES_DEFAULT_LENGTH)) > 0) {
                    outputStream.write(buff, 0, rc);
                }
                // 设置图片位置
                XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, y, x, y + 1, x + 1);
                // 设置这个,图片会自动填满单元格的长宽
                anchor.setAnchorType(AnchorType.MOVE_AND_RESIZE);
                patriarch.createPicture(anchor, wb.addPicture(outputStream.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        private static String formatDate(Date date) {
            if (date == null) {
                return "";
            }
            SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT);
            return format.format(date);
        }
    
        private static void setSelect(Sheet sheet, Map> selectMap) {
            if (selectMap == null || selectMap.isEmpty()) {
                return;
            }
            Set>> entrySet = selectMap.entrySet();
            for (Entry> entry : entrySet) {
                int y = entry.getKey();
                List list = entry.getValue();
                if (list == null || list.isEmpty()) {
                    continue;
                }
                String[] arr = new String[list.size()];
                for (int i = 0; i < list.size(); i++) {
                    arr[i] = list.get(i);
                }
                DataValidationHelper helper = sheet.getDataValidationHelper();
                CellRangeAddressList addressList = new CellRangeAddressList(1, 65000, y, y);
                DataValidationConstraint dvc = helper.createExplicitListConstraint(arr);
                DataValidation dv = helper.createValidation(dvc, addressList);
                if (dv instanceof HSSFDataValidation) {
                    dv.setSuppressDropDownArrow(false);
                } else {
                    dv.setSuppressDropDownArrow(true);
                    dv.setShowErrorBox(true);
                }
                sheet.addValidationData(dv);
            }
        }
    
        private static boolean isNumeric(String str) {
            if ("0.0".equals(str)) {
                return true;
            }
            for (int i = str.length(); --i >= 0; ) {
                if (!Character.isDigit(str.charAt(i))) {
                    return false;
                }
            }
            return true;
        }
    
        private static String getString(String s) {
            if (s == null) {
                return "";
            }
            if (s.isEmpty()) {
                return s;
            }
            return s.trim();
        }
    
    }
    
    • 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
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
    • 424
    • 425
    • 426
    • 427
    • 428
    • 429
    • 430
    • 431
    • 432
    • 433
    • 434
    • 435
    • 436
    • 437
    • 438
    • 439
    • 440
    • 441
    • 442
    • 443
    • 444
    • 445
    • 446
    • 447
    • 448
    • 449
    • 450
    • 451
    • 452
    • 453
    • 454
    • 455
    • 456
    • 457
    • 458
    • 459
    • 460
    • 461
    • 462
    • 463
    • 464
    • 465
    • 466
    • 467
    • 468
    • 469
    • 470
    • 471
    • 472
    • 473
    • 474
    • 475
    • 476
    • 477
    • 478
    • 479
    • 480
    • 481
    • 482
    • 483
    • 484
    • 485
    • 486
    • 487
    • 488
    • 489
    • 490
    • 491
    • 492
    • 493
    • 494
    • 495
    • 496
    • 497
    • 498
    • 499
    • 500
    • 501
    • 502
    • 503
    • 504
    • 505
    • 506
    • 507
    • 508
    • 509
    • 510
    • 511
    • 512
    • 513
    • 514
    • 515
    • 516
    • 517
    • 518
    • 519
    • 520
    • 521
    • 522
    • 523
    • 524
    • 525
    • 526
    • 527
    • 528
    • 529
    • 530
    • 531
    • 532
    • 533
    • 534
    • 535
    • 536
    • 537
    • 538
    • 539
    • 540
    • 541
    • 542
    • 543
    • 544
    • 545
    • 546
    • 547
    • 548
    • 549
    • 550
    • 551
    • 552
    • 553
    • 554
    • 555
    • 556
    • 557
    • 558
    • 559
    • 560
    • 561
    • 562
    • 563
    • 564
    • 565
    • 566
    • 567
    • 568
    • 569
    • 570
    • 571
    • 572
    • 573
    • 574
    • 575
    • 576
    • 577
    • 578
    • 579
    • 580
    • 581
    • 582
    • 583
    • 584
    • 585
    • 586
    • 587
    • 588
    • 589
    • 590
    • 591
    • 592
    • 593
    • 594
    • 595
    • 596
    • 597
    • 598
    • 599
    • 600
    • 601
    • 602
    • 603
    • 604
    • 605
    • 606
    • 607
    • 608
    • 609
    • 610
    • 611
    • 612
    • 613
    • 614
    • 615
    • 616
    • 617
    • 618
    • 619
    • 620
    • 621
    • 622
    • 623
    • 624
    • 625
    • 626
    • 627
    • 628
    • 629
    • 630
    • 631
    • 632
    • 633
    • 634
    • 635
    • 636
    • 637
    • 638
    • 639
    • 640
    • 641
    • 642
    • 643
    • 644
    • 645
    • 646
    • 647
    • 648
    • 649
    • 650
    • 651
    • 652
    • 653
    • 654
    • 655
    • 656
    • 657
    • 658
    • 659
    • 660
    • 661
    • 662
    • 663
    • 664
    • 665
    • 666
    • 667
    • 668
    • 669
    • 670
    • 671
    • 672
    • 673
    • 674
    • 675
    • 676
    • 677
    • 678
    • 679
    • 680
    • 681
    • 682
    • 683
    • 684
    • 685
    • 686
    • 687
    • 688
    • 689
    • 690
    • 691
    • 692
    • 693
    • 694
    • 695
    • 696
    • 697
    • 698
    • 699
    • 700
    • 701
    • 702
    • 703
    • 704
    • 705
    • 706
    • 707
    • 708
    • 709
    • 710
    • 711
    • 712
    • 713
    • 714
    • 715
    • 716
    • 717
    • 718
    • 719
    • 720
    • 721
    • 722
    • 723
    • 724
    • 725
    • 726
    • 727
    • 728
    • 729
    • 730
    • 731
    • 732
    • 733
    • 734
    • 735
    • 736
    • 737
    • 738
    • 739
    • 740
    • 741
    • 742
    • 743
    • 744
    • 745
    • 746
    • 747
    • 748
    • 749
    • 750
    • 751
    • 752
    • 753
    • 754
    • 755
    • 756
    • 757
    • 758
    • 759
    • 760
    • 761
    • 762
    • 763
    • 764
    • 765
    • 766
    • 767
    • 768
    • 769
    • 770
    • 771
    • 772
    • 773
    • 774
    • 775
    • 776
    • 777
    • 778
    • 779
    • 780
    • 781
    • 782
    • 783
    • 784
    • 785
    • 786
    • 787
    • 788
    • 789
    • 790
    • 791
    • 792
    • 793
    • 794
    • 795
    • 796
    • 797
    • 798
    • 799
    • 800
    • 801
    • 802
    • 803
    • 804
    • 805
    • 806
    • 807
    • 808
    • 809
    • 810
    • 811
    • 812
    • 813
    • 814
    • 815
    • 816
    • 817
    • 818
    • 819
    • 820
    • 821
    • 822
    • 823
    • 824
    • 825
    • 826
    • 827
    • 828
    • 829
    • 830
    • 831
    • 832
    • 833
    • 834
    • 835
    • 836
    • 837
    • 838
    • 839
    • 840
    • 841
    • 842
    • 843
    • 844
    • 845
    • 846
    • 847
    • 848
    • 849
    • 850
    • 851
    • 852
    • 853
    • 854
    • 855
    • 856
    • 857
    • 858
    • 859
    • 860
    • 861
    • 862
    • 863
    • 864
    • 865
    • 866
    • 867
    • 868
    • 869
    • 870
    • 871
    • 872
    • 873
    • 874
    • 875
    • 876
    • 877
    • 878
    • 879
    • 880
    • 881
    • 882
    • 883
    • 884
    • 885
    • 886
    • 887
    • 888
    • 889
    • 890
    • 891
    • 892
    • 893
    • 894
    • 895
    • 896
    • 897
    • 898
    • 899
    • 900
    • 901
    • 902
    • 903
    • 904
    • 905
    • 906
    • 907
    • 908
    • 909
    • 910
    • 911
    • 912
    • 913
    • 914
    • 915
    • 916
    • 917
    • 918
    • 919
    • 920
    • 921
    • 922
    • 923
    • 924
    • 925
    • 926
    • 927
    • 928
    • 929
    • 930
    • 931
    • 932
    • 933
    • 934
    • 935
    • 936
    • 937
    • 938
    • 939
    • 940
    • 941
    • 942
    • 943
    • 944
    • 945
    • 946
    • 947
    • 948
    • 949
    • 950
    • 951
    • 952
    • 953
    • 954
    • 955
    • 956
    • 957
    • 958
    • 959
    • 960
    • 961
    • 962

    5、Excel表格数据,这里简单测试,所以属性都较简单
    在这里插入图片描述

    6、User类,对应Excel表

    package com.geesun.pojo.entity;
    
    import com.geesun.utils.ExcelImport;
    import lombok.Data;
    
    /**
     * Description:
     * @Author: Mr.ZJW
     * DateTime: 2022/2/23 11:23
     */
    @Data
    public class User {
    
        @ExcelImport("姓名")
        private String name;
    
        @ExcelImport("年龄")
        private Integer age;
    
        @ExcelImport("性别")
        private String sex;
    
        @ExcelImport("电话")
        private String phone;
    
        @ExcelImport("城市")
        private String city;
    
    }
    
    • 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

    二、Excel的导入测试

    1、Controller

    @RestController
    @RequestMapping("/excel")
    public class ExcelController {
    
        /**
         * excel数据导入
         * @param file
         * @return
         * @throws Exception
         */
        @PostMapping("/excelImport")
        public void excelImport(@RequestPart("excelImport")MultipartFile file) throws Exception {
            List users = ExcelUtils.readMultipartFile(file, User.class);
            users.forEach(System.out::println);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2请求,用ApiPost请求
    在这里插入图片描述

    测试结果:
    在这里插入图片描述
    3、导入解析为对象(字段自动映射)
    对于有的枚举数据,通常我们导入的时候,表格中的数据是值,而在数据保存时,往往用的是键,比如:我们用sex=1可以表示为男,sex=2表示为女,那么我们通过配置也可以达到导入时,数据的自动映射。

    那么,我们只需要将Java实体中的对象sex字段的类型改为对应的数字类型Integer,然后再注解中配置好 kv 属性(属性格式为:键1-值1;键2-值2;键3-值3;…)
    在这里插入图片描述
    测试效果:
    在这里插入图片描述
    4、获取Excel的行号:
    在User类上添加多一个属性
    在这里插入图片描述
    测试效果:
    在这里插入图片描述
    5、获取原始数据:
    在做页面数据导入的时候,如果某行存在错误,一般我们会将原始的数据拿出来分析,为什么会造成数据错误。那么,我们在实体类中,增加一个 String 类型的 rowData 字段即可。
    在这里插入图片描述
    测试效果:
    在这里插入图片描述
    6、获取错误提示
    当我们在导入数据的时候,如果某行数据存在,字段类型不正确,长度超过最大限制(详见1.2.7),必填字段验证(1.2.8),数据唯一性验证(1.2.9)等一些错误时候,我们可以往对象中添加一个 String 类型的 rowTips 字段,则可以直接拿到对应的错误信息。
    在这里插入图片描述
    比如,我们将表格中李四的性别改为F(F并不是映射数据),将王五的年龄改为二十(不能转换为Integer类型数据)。
    在这里插入图片描述
    测试效果:可以看到,我们可以通过 rowTips 直接拿到对应的错误数据提示。
    在这里插入图片描述
    7、限制字段长度
    比如,我们手机通常为11为长度,那么不妨限制电话的最大长度位数为11位。
    对应的做法,就是在 @ExcelImport 注解中,设置 maxLength = 11 即可。
    在这里插入图片描述

    比如,我们将张三的电话长度设置为超过11位数的一个字符串**测试效果:**
    测试效果:
    在这里插入图片描述
    8、必填字段验证
    我们在做数据导入的时候,往往还会有一些必填字段,比如用户的名称,电话。

    那么,我们只需要在 @ExcelImport 注解属性中,加上 required = true 即可。
    在这里插入图片描述
    我们将张三的电话去除为空,进行测试。
    在这里插入图片描述
    测试效果:
    在这里插入图片描述
    9、数据唯一性验证
    (1) 单字段唯一性验证

    我们在导入数据的时候,某个字段是具有唯一性的,比如我们这里假设规定姓名不能重复,那么则可以在对应字段的 @ExcelImport 注解上加上 unique = true 属性。
    在这里插入图片描述

    构建2条姓名和电话号码一样的数据进行测试。在这里插入图片描述

    测试效果:
    在这里插入图片描述
    (2)多字段唯一性验证

    如果你导入的数据存在多字段唯一性验证这种情况,只需要将每个对应字段的 @ExcelImport 注解属性中,都加上 required = true 即可。

    比如:我们将姓名和电话两个字段进行联合唯一性验证(即不能存在有名称和电话都一样的数据,单个字段属性重复允许)。

    在这里插入图片描述
    首先,我们将刚刚的Excel的数据进行导入。
    在这里插入图片描述
    测试效果:可以看到,虽然名称有相同,但电话不相同,所以这里并没有提示唯一性验证错误。
    在这里插入图片描述
    现在,我们将最后一行的电话也改为和第1行一样的,于是,现在就存在了违背唯一性的两条数据。
    在这里插入图片描述
    测试效果:可以看到,我们的联合唯一性验证生效了。:
    在这里插入图片描述

    三、Excel的导出测试

    1、我们在做数据导入的时候,往往首先会提供一个模版供其下载,这样用户在导入的时候才知道如何去填写数据。导出模板除了可以用上面的动态导出,这里还提供了一种更加便捷的写法。只需要创建一个类,然后再对应字段上打上 @ExcelExport 注解类即可。
    在这里插入图片描述

    @Data
    public class User {
    
        @ExcelExport(value = "姓名")
        private String name;
    
        @ExcelExport("年龄")
        private Integer age;
    
        @ExcelExport(value = "性别")
        private String sex;
    
        @ExcelExport(value = "电话")
        private String phone;
    
        @ExcelExport("城市")
        private String city;
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    Controller 代码:

        /**
         * 导出Excel表
         * @param response
         */
        @RequestMapping("/excelPort")
        public void excelPort(HttpServletResponse response){
            ExcelUtils.exportTemplate(response,"用户表",User.class);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    测试效果:
    在这里插入图片描述
    在这里插入图片描述
    2、导出模板(附示例数据)
    我们在做模版下载时候,有时往往会携带一条样本数据,好提示用户数据格式是什么,那么我们只需要在对应字段上进行配置即可。
    在这里插入图片描述
    Controller代码:

    在这里插入图片描述
    测试效果:
    在这里插入图片描述
    3、按对象导出
    我们还可以通过 List 对象,对数据直接进行导出。首先,同样需要在对应类的字段上,设置导出名称。
    在这里插入图片描述

    Controller 代码:

    @RestController
    @RequestMapping("/excel")
    public class ExcelController {
    
        /**
         * 导出Excel表
         * @param response
         */
        @RequestMapping("/excelPort")
        public void excelPort(HttpServletResponse response){
            //创建ArrayList
            List userList = new ArrayList<>();
            //实例用户对象
            User user1 = new User();
            //设置用户1信息
            user1.setName("张三");
            user1.setAge(20);
            user1.setSex("男");
            user1.setPhone("110");
            user1.setCity("北京");
            User user2 = new User();
            //设置用户2信息
            user2.setName("李四");
            user2.setAge(30);
            user2.setSex("女");
            user2.setPhone("120");
            user2.setCity("上海");
            //添加到List
            userList.add(user1);
            userList.add(user2);
            ExcelUtils.export(response,"用户表",userList,User.class);
        }
    
    }
    
    • 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

    测试效果:
    在这里插入图片描述
    4、从数据库获取数据导出
    4.1、sql表结构
    在这里插入图片描述
    4.2、实体类

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @TableName(value = "`User`")
    public class User implements Serializable {
        /**
         * 用户id
         */
        @TableId(value = "id", type = IdType.INPUT)
        @ExcelExport(value = "用户id")
        private Long id;
    
        /**
         * 用户名
         */
        @TableField(value = "name")
        @ExcelExport(value = "用户名")
        private String name;
    
        /**
         * 性别
         */
        @TableField(value = "sex")
        @ExcelExport(value = "性别")
        private String sex;
    
        /**
         * 年龄
         */
        @TableField(value = "age")
        @ExcelExport(value = "年龄")
        private Long age;
    
        /**
         * 城市
         */
        @TableField(value = "city")
        @ExcelExport(value = "城市")
        private String city;
    
        /**
         * 手机号
         */
        @TableField(value = "phone")
        @ExcelExport(value = "手机号")
        private String phone;
    
        private static final long serialVersionUID = 1L;
    }
    
    • 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

    4.3Controller代码:

    @RequestMapping("/excel")
    @RestController
    public class ExcelPortController {
    
        @Autowired
        private UserService userService;
    
        @RequestMapping("/excelPort")
        public void excelPort(HttpServletResponse response){
            List list = userService.list();
            ExcelUtils.export(response,"用户信息表",list,User.class);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    4.5测试结果:
    访问然后会跳出一:

    在这里插入图片描述

    测试效果:
    在这里插入图片描述
    在这里插入图片描述

    先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦

  • 相关阅读:
    python数据库连接池的正确用法
    校园二手物品交易平台
    Error:(10, 32) java: 程序包org.springframework.http不存在
    交叉熵损失CrossEntropyLoss
    JAVA学习笔记
    海关 瑞数5.5 找后缀加密入口解析
    IDEA常用插件
    大佬的职场经验
    动态gif图片如何操作?简单三步前年公司操作
    c++ || mutable_explicit_volatile关键字
  • 原文地址:https://blog.csdn.net/begefefsef/article/details/126106771