zoukankan      html  css  js  c++  java
  • java实现动态Excle模板文件导入

    这里的动态Excle模板文件是有特指的,比如,用户导入一个Excle文件,第一次导入可能是"姓名、性别、年龄…",第二次导入可能是"姓名、身份证号、联系电话…",可以看到导入信息虽然发生了变化,但是总结起来都是人员的基本信息。前一篇文章介绍了Excle模板动态导出,动态导入其实是依赖上一步实现的,虽然是动态导出,但是用户只能在规定的大的字段范围里选取自己想要导出的字段,这样导入的时候只需要判断字段名,通过反射赋值给对象就行了,即使是模板不同,只要在字段范围内,都可以处理。核心步骤如下:

    1.导入maven依赖(maven依赖跟上一篇文章一样)

    2.前端js代码:

    	var danWeiId = $("#danWei").combobox("getValue");
    	//除了excle文件外,还有其他的信息,所以使用FormData创建序列化对象
    	var formData = new FormData();
    	formData.append("uploadfile", $("#uploadExcelFile").filebox("files")[0]);
    	formData.append("danWeiId", danWeiId);
    	// 还可以在前端列出excel的所有工作空间名称让用户选择需要导入具体导入哪一个或哪几个
    	formData.append("sheetNames", sn);
    	// 发送ajax请求
    	$.ajax({
    		url : baseurl + '/dengji/saveDengJiInfoByExcle.do',
    		type : "post",
    		data : formData,
    		processData : false,
    		contentType : false,
    		dataType : "json",
    		success : function(data) {
    		}
    	});
    

    3.声明字段枚举类:(字段固定,只能在这个范围里选取)

    public enum FieldEnum {
        /**
         * 姓名
         */
        XING_MING("姓名", false, "xingMing", "TR"),
        /**
         * 身份证号
         */
        SHEN_FEN_ZHENG_HAO("身份证号", false, "shenFenZhengHao", "TR"),
    
        /**
         * 性别
         */
        XING_BIE("性别", true, "xingBie", "TR"),
        /**
         * 出生日期
         */
        CHU_SHENG_RI_QI("出生日期", false, "chuShengRiQi", "TR"),
        /**
         * 年龄
         */
        NIAN_LING("年龄", false, "dengJiNianLing", "TS"),
        /**
         * 联系地址
         */
        LIAN_XI_DI_ZHI("联系地址", false, "lianXiDiZhi", "TS");
    
        /*省略其他可能的属性*/
    
        /**
         * 字段名称
         */
        private String name;
    
        /**
         * 是否是字典值
         */
        private boolean isZiDian;
    
        /**
         * 对应实体类字段属性名称
         */
        private String entityFieldName;
    
        /**
         * 实体类类型(用于标识是哪个实体类的字段)
         */
        private String type;
    
        private FieldEnum(String name, boolean isZiDian, String entityFieldName, String type) {
            this.name = name;
            this.isZiDian = isZiDian;
            this.entityFieldName = entityFieldName;
            this.type = type;
        }
    
        /**
         * 通过name获取枚举类
         * 
         * @param name
         * @return
         */
        public static FieldEnum getFieldEnum(String name) {
            FieldEnum[] values = FieldEnum.values();
            for (int i = 0; i < values.length; i++) {
                if (values[i].getName().equals(name)) {
                    return values[i];
                }
            }
            return null;
        }
    
        public String getName() {
            return name;
        }
    
        public boolean isZiDian() {
            return isZiDian;
        }
    
        public String getEntityFieldName() {
            return entityFieldName;
        }
    
        public String getType() {
            return type;
        }
    }
    

    4.导入Excle文件:(controller层)

    	@Autowired
        private HttpServletRequest request;
        /**
         * EXCEL文件导入登记
         * 
         * @param uploadfile 上传文件信息
         * @param danWeiId
         * @param sheetNames EXCEL工作表空间名称
         * @return
         */
        @RequestMapping(value = "/saveDengJiInfoByExcle.do", produces = "application/json;charset=UTF-8")
        @ResponseBody
        // 使用@RequestParam注解绑定参数,否则参数可能绑定失败
        public Map<String, Object> saveDengJiInfoByExcle(@RequestParam(value = "uploadfile") MultipartFile uploadfile,
            @RequestParam(value = "danWeiId") String danWeiId, @RequestParam(value = "sheetNames") String sheetNames) {
            Map<String, Object> resultMap = new HashMap<>();
            if (uploadfile != null) {
                if (!uploadfile.isEmpty()) {// 判断上传Excle文件对象是否为空
                    try {
                        TShenQingEntity tSq = new TShenQingEntity();
                        tSq.setDanWeiId(danWeiId);
                        // 模拟从request中获取条件,比如登录用户所属的科室等
                        // tSq.setCondition(request.getRequestURL().toString());
                        Map<String, Object> shenQingMap = ExcelImportMuBanUtil.getExcelInfo(uploadfile, tSq, sheetNames);
                        Boolean errorFlag = (Boolean)shenQingMap.get("errorFlag");
                        // 判断是否有错误,不合法的格式存在
                        if (errorFlag != null && errorFlag) {// 如果存在则在前端页面给出提示信息,你也可以保存获取的正确的信息
                            return shenQingMap;
                        }
                        // 保存到数据库中
                        resultMap = dengjiService.saveTuanTiShenQing(shenQingMap);
                    } catch (Exception e) {
                        e.printStackTrace();
                        logger.error("上传excel文件异常!", e);
                    }
                }
            }
            return resultMap;
        }
    

    5.处理Excle文件导入工具类:

    public class ExcelImportMuBanUtil {
        /**
         * 申请所有成员变量
         */
        private static final Field[] T_SHEN_QING_FIELD;
        /**
         * 人员所有成员变量
         */
        private static final Field[] T_USER_FIELD;
    
        static {
            T_SHEN_QING_FIELD = TShenQingEntity.class.getDeclaredFields();
            T_USER_FIELD = TUser.class.getDeclaredFields();
        }
    
        /**
         * 验证sheet页前几行没有数据,则当错误sheet处理
         */
        private static final int CHECK_SHEET_ROWNUM = 3;
    
        /**
         * 获取excel文件中有效的工作表空间名称
         * 
         * @param fileName 文件名
         * @param is 流
         * @param titleList 标题列表(判断是否存在不合法的sheet)
         * @return
         */
        public static Map<String, Object> listSheetName(String fileName, InputStream is, List<String> titleList)
            throws Exception {
            Map<String, Object> resultMap = new HashMap<>();
            List<String> errorSheetNames = new ArrayList<String>();
            List<String> correctSheetNames = new ArrayList<>();
            // 判断其兼容版本 调用了判断版本的方法
            Workbook workbook = ExcelCommonUtil.getWorkbook(fileName, is);
            int sheetNum = workbook.getNumberOfSheets();// 得到sheet的个数
            for (int i = 0; i < sheetNum; i++) {
                Sheet sheet = workbook.getSheetAt(i);
                if (!ExcelCommonUtil.isEmptySheet(sheet)) {// sheet存在有效数据
                    Row row = null;
                    boolean flag = true;
                    for (int m = 0; m < CHECK_SHEET_ROWNUM; m++) {
                        row = sheet.getRow(m);
                        if (m == 0) {// 验证标题是否有效
                            if (!isCorrectTitle(row, titleList)) {
                                break;
                            }
                        } else {// 判断row是否为空
                            flag = flag && ExcelCommonUtil.isRowEmpty(row);
                        }
                    }
                    if (flag) {
                        errorSheetNames.add(sheet.getSheetName());
                    } else {
                        correctSheetNames.add(sheet.getSheetName());
                    }
                }
            }
            // 不合法的sheet工作空间名称
            resultMap.put("errorSheetNames", errorSheetNames);
            // 合法的sheet工作空间名称
            resultMap.put("correctSheetNames", correctSheetNames);
            return resultMap;
        }
    
        /**
         * 检查是否是正确的标题行
         * 
         * @param row
         * @param titleList
         * @return
         */
        public static boolean isCorrectTitle(Row row, List<String> titleList) throws Exception {
            boolean flag = false;
            if (!ExcelCommonUtil.isRowEmpty(row)) {
                for (int i = row.getFirstCellNum(), len = row.getLastCellNum(); i <= len; i++) {
                    Cell cell = row.getCell(i);
                    if (cell != null && cell.getCellType() != Cell.CELL_TYPE_BLANK) {
                        String cellValue = ExcelCommonUtil.getValue(cell);
                        if (!titleList.contains(cellValue)) {
                            flag = false;
                            break;
                        } else {
                            flag = true;
                        }
                    }
                }
            }
            return flag;
        }
    
        /**
         * 获取上传EXCEL的信息
         * 
         * @param uploadfile
         * @param tiJianShenQing
         * @param sheetNames
         * @param jiGouBianMa
         * @return
         */
        @SuppressWarnings("unchecked")
        public static Map<String, Object> getExcelInfo(MultipartFile uploadfile, TShenQingEntity paramTShenQing,
            String sheetNames) throws Exception {
            Map<String, Object> resultMap = new HashMap<>();// 结果map
            List<TShenQingEntity> tShenQingList = null;// 申请list
            List<String> errorList = null; // EXCEL文件中存在错误的list
            Boolean globalErrorFlag = null;// EXCEL文件中是否出现了不符合要求格式的数据
            int total = 0;// 导入项总数
            if (!StringUtils.isBlank(sheetNames)) {
                List<String> sheetList = StringUtil.StringToList(sheetNames);
                Map<String, Object> rowMap = ExcelCommonUtil.getExcelRead(uploadfile.getOriginalFilename(),
                    uploadfile.getInputStream(), 1, sheetList);
                if (rowMap.size() != 0) {
                    // 查询条件
                    String conditon = paramTShenQing.getCondition();
                    // 得到必填字段
                    List<String> biTianList = ExcelDownloadUtil.listBiTianField(conditon);
                    boolean biTianValidFlag = (biTianList != null && biTianList.size() != 0);
                    tShenQingList = new ArrayList<>();
                    errorList = new ArrayList<>();
                    TShenQingEntity tShenQing = null;
                    TUser tUser = null;
                    // 存放错误提示
                    StringBuilder tips;
                    for (Map.Entry<String, Object> entry : rowMap.entrySet()) {
                        Map<String, Object> tempMap = (Map<String, Object>)entry.getValue();
                        String fenZuName = "[" + entry.getKey() + "]";// 得到sheet工作表空间名称,方便用于提示
                        List<String> titleList = (List<String>)tempMap.get("titleList");
                        List<Row> rowList = (List<Row>)tempMap.get("rowList");
                        for (int m = 0, lenx = rowList.size(); m < lenx; m++) {
                            tShenQing = new TShenQingEntity();
                            tUser = new TUser();
                            tips = null;
                            boolean rowFlag = true;// 行数据合法标识
                            Row dataRow = rowList.get(m);
                            boolean emptyRowFlag = ExcelCommonUtil.isRowEmpty(dataRow);
                            total = emptyRowFlag ? total : total + 1;// 如果是空行,直接+1进行下一行的数据解析
                            for (int i = 0, len = titleList.size(); i < len && !emptyRowFlag; i++) {
                                String title = titleList.get(i);
                                String value = ExcelCommonUtil.getValue(dataRow.getCell(i));
                                if (biTianValidFlag && biTianList.contains(title) && StringUtils.isBlank(value)) {// 如果必填项没有值直接进行下一次循环
                                    tips = tips == null ? new StringBuilder(fenZuName + "第" + (m + 1) + "行的数据:" + title + "未填")
                                            : tips.append("、" + title + "未填");
                                    rowFlag = false;
                                }
                                if (!StringUtils.isBlank(value)) {// 如果不为空
                                    FieldEnum tempEnum = FieldEnum.getFieldEnum(title);
                                    Field tempField = null;
                                    if ("TR".equals(tempEnum.getType())) {
                                        for (int n = 0; n < T_USER_FIELD.length; n++) {
                                            tempField = T_USER_FIELD[n];
                                            if (tempEnum.getEntityFieldName().equals(tempField.getName())) {
                                                tempField.setAccessible(true);
                                                if ("出生日期".equals(tempEnum.getName())) {
                                                    value = value.contains("-") ? value.replaceAll("-", "/") : (value.contains(".") ? value.replaceAll("\.", "/") : value);
                                                    try {
                                                        tempField.set(tUser,
                                                            new SimpleDateFormat("yyyy/MM/dd").parse(value));
                                                    } catch (Exception e) {// 出生日期转换异常
                                                        rowFlag = false;
                                                        tips = tips == null ? new StringBuilder( fenZuName + "第" + (m + 1) + "行的数据:" + title + "格式有误")
                                                            : tips.append("、" + title + "格式有误");
                                                    }
                                                } else {
                                                    // 这里直接调用set赋值,如果你setter方法里面有处理逻辑的话,可以通过反射调用字段的setter方法赋值
                                                    tempField.set(tUser, value);
                                                }
                                                break;
                                            }
                                        }
                                    } else if ("TS".equals(tempEnum.getType())) {
                                        for (int n = 0; n < T_SHEN_QING_FIELD.length; n++) {
                                            tempField = T_SHEN_QING_FIELD[n];
                                            if (tempEnum.getEntityFieldName().equals(tempField.getName())) {
                                                tempField.setAccessible(true);
                                                if ("年龄".equals(tempEnum.getName())) {
                                                    try {
                                                        value = value.endsWith("岁") ? value.substring(0, value.length() - 1) : value;
                                                        tempField.set(tShenQing, Integer.parseInt(value));
                                                    } catch (Exception e) {// 年龄转换异常
                                                        rowFlag = false;
                                                        tips = tips == null  ? new StringBuilder( fenZuName + "第" + (m + 1) + "行的数据:" + title + "格式有误(整数)")
                                                            : tips.append("、" + title + "格式有误(整数)");
                                                    }
                                                } else {
                                                    // 这里直接调用set赋值,如果你setter方法里面有处理逻辑的话,可以通过反射调用字段的setter方法赋值
                                                    tempField.set(tShenQing, value);
                                                }
                                                break;
                                            }
                                        }
                                    } else {
                                        // doSomthing
                                    }
                                }
                            }
                            // 赋值成功以后也可以进行其他的自定义验证:比如
                            // 如果姓名为空的话
                            if (StringUtils.isBlank(tUser.getXingMing())) {
                                rowFlag = false;
                                tips = tips == null ? new StringBuilder(fenZuName + "第" + (m + 1) + "行的数据:姓名为空")
                                    : tips.append("、姓名为空");
                            }
                            // 其他需要的验证
                            if (rowFlag) {// 通过验证行合法标识依然是true的话
                                tShenQing.setUser(tUser);// 把user对象设置进申请对象
                                tShenQingList.add(tShenQing);// 添加到合法列表中
                            } else {
                                globalErrorFlag = globalErrorFlag == null ? Boolean.TRUE : globalErrorFlag;
                                errorList.add(tips.toString());
                            }
                        }
                    } // end of rowMap
                }
            }
            resultMap.put("tShenQingList", tShenQingList);
            resultMap.put("errorList", errorList);
            resultMap.put("errorFlag", globalErrorFlag);
            resultMap.put("total", total);
            return resultMap;
        }
    }
    

    6.Excel通用工具类:

    public class ExcelCommonUtil {
    
        /**
         * 判断是否是2003的excel,返回true是2003
         * 
         * @param fileName
         * @return
         */
        public static boolean isExcel2003(String fileName) {
            return fileName.matches("^.+\.(?i)(xls)$");
        }
    
        /**
         * 判断是否是2007的excel,返回true是2007
         * 
         * @param fileName
         * @return
         */
        public static boolean isExcel2007(String fileName) {
            return fileName.matches("^.+\.(?i)(xlsx)$");
        }
    
        /**
         * 判断文件是否是Excel文件
         * 
         * @param fileName
         * @return
         */
        public static boolean validateExcel(String fileName) {
            if (fileName == null || !(isExcel2003(fileName) || isExcel2007(fileName))) {
                return false;
            }
            return true;
        }
    
        /**
         * 得到workbook
         * 
         * @param fileName
         * @param is
         * @return
         * @throws Exception
         */
        public static Workbook getWorkbook(String fileName, InputStream is) throws Exception {
            Workbook workbook = null;
            try {
                /** 判断文件的类型,是2003还是2007 */
                boolean isExcel2003 = true;
                if (isExcel2007(fileName)) {
                    isExcel2003 = false;
                }
    
                if (isExcel2003) {
                    workbook = new HSSFWorkbook(is);
                } else {
                    workbook = new XSSFWorkbook(is);
                }
            } catch (Exception e) {
                throw e;
            }
            return workbook;
        }
    
        /**
         * 得到Cell的值
         * 
         * @param cell
         * @return
         */
        public static String getValue(Cell cell) throws Exception {
            if (cell != null) {
                if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) {
                    return String.valueOf(cell.getBooleanCellValue());
                } else if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
                    if (HSSFDateUtil.isCellDateFormatted(cell)) {
                        Date date = HSSFDateUtil.getJavaDate(cell.getNumericCellValue());
                        return new SimpleDateFormat("yyyy-MM-dd").format(date);
                    } else {
                        double value = cell.getNumericCellValue();
                        return new BigDecimal(value).toString();
                    }
                } else if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
                    String value = String.valueOf(cell.getStringCellValue());
                    Pattern pattern = Pattern.compile("[0-9]{4}.[0-9]{1,2}.[0-9]{1,2}");
                    if (pattern.matcher(value).matches()) {
                        return value.replace(".", "-");
                    } else {
                        return value;
                    }
                } else {
                    return String.valueOf(cell.getStringCellValue());
                }
            }
            return "";
        }
    
        /**
         * 判断一个sheet是否有数据
         * 
         * @param sheet
         * @return 空的sheet返回true
         */
        public static boolean isEmptySheet(Sheet sheet) {
            boolean isEmpty = false;
            if ((sheet.getLastRowNum() == 0
                && (sheet.getPhysicalNumberOfRows() == 0 || sheet.getPhysicalNumberOfRows() == 1))) {
                isEmpty = true;
            }
            return isEmpty;
        }
    
        /**
         * 判断一行是否为空
         * 
         * @param row
         * @return
         */
        public static boolean isRowEmpty(Row row) {
            boolean isRowEmpty = true;
            if (row != null) {
                for (int i = row.getFirstCellNum(), len = row.getLastCellNum(); i <= len; i++) {
                    Cell cell = row.getCell(i);
                    if (cell != null && cell.getCellType() != Cell.CELL_TYPE_BLANK && !"".equals((cell + "").trim())) {
                        isRowEmpty = false;
                    }
                }
            }
            return isRowEmpty;
        }
    
        /**
         * 解析文件的sheet数据
         * 
         * @param fileName 文件名
         * @param is 流
         * @param startNum 开始行数(标题行)
         * @param sheetNameList 工作表空间名称为空时获取所有内容,不过空时获取指定内容
         * @return
         * @throws Exception
         */
        public static Map<String, Object> getExcelRead(String fileName, InputStream is, int startNum, List<String> sheetNameList) throws Exception {
            Map<String, Object> map = new HashMap<>();
            // 判断其兼容版本 调用了判断版本的方法
            Workbook workbook = getWorkbook(fileName, is);
            int sheetNum = workbook.getNumberOfSheets();// 得到sheet的个数
            List<Row> rowList = null;
            List<String> titleList = null;
            Map<String, Object> rowMap = null;
            boolean isEmptySheetNameList = (sheetNameList == null || sheetNameList.size() == 0);
            for (int n = 0; n < sheetNum; n++) {
                rowList = new ArrayList<Row>();
                titleList = new ArrayList<>();
                rowMap = new HashMap<>();
                Sheet sheet = workbook.getSheetAt(n);
                String sheetName = sheet.getSheetName();
                if ((isEmptySheetNameList || sheetNameList.contains(sheetName)) && !isEmptySheet(sheet)) {// sheetNames存在时要满足在此list集合中取值
                    Row row = null;
                    for (int i = sheet.getFirstRowNum(), len = sheet.getLastRowNum(); i <= len; i++) {
                        row = sheet.getRow(i);
                        if (i == startNum - 1) {
                            titleList = getRowValue(row);
                        }
                        if (i >= startNum) {
                            if (!isRowEmpty(row)) {
                                rowList.add(row);
                            }
                        }
                    }
                    rowMap.put("titleList", titleList);
                    rowMap.put("rowList", rowList);
                    map.put(sheetName, rowMap);
                }
            }
            is.close();
            return map;
        }
    
        /**
         * 获取一行的数据
         * 
         * @param row
         * @return
         */
        private static List<String> getRowValue(Row row) throws Exception {
            List<String> list = null;
            if (!isRowEmpty(row)) {
                list = new ArrayList<>();
                for (int i = row.getFirstCellNum(); i <= row.getLastCellNum(); i++) {
                    Cell cell = row.getCell(i);
                    if (cell != null && cell.getCellType() != Cell.CELL_TYPE_BLANK) {
                        String cellValue = ExcelCommonUtil.getValue(cell);
                        list.add(cellValue);
                    }
                }
            }
            return list;
        }
    }
    

    到这里Excel文件导入就完成了,在指定的字段范围内可以实现动态导入啦。

    一颗安安静静的小韭菜。文中如果有什么错误,欢迎指出。
  • 相关阅读:
    算法-第四版-练习1.3.2解答
    彻底理解线索二叉树(转载)
    C/C++——C++中new与malloc的10点区别(转载)
    C语言中的struct和typedef struct(转载)
    C语言实现贪吃蛇
    C语言实现2048小游戏
    案例开发准备
    WordCount单词计数
    MapReduce原理与实现
    HDFS简介
  • 原文地址:https://www.cnblogs.com/c-Ajing/p/13448380.html
Copyright © 2011-2022 走看看