通过java将Excel表格导入数据到数据库

一、首先。我们使用到的是apache的开源框架《poi》

1、导入相应的依赖包
2、连接数据库的框架可自行选择,下文使用的是mybatis-plus
Maven


<dependency>
    <groupId>org.apache.poigroupId>
    <artifactId>poiartifactId>
    <version>4.1.2version>
dependency>
<dependency>
    <groupId>org.apache.poigroupId>
    <artifactId>poi-ooxmlartifactId>
    <version>4.1.2version>
dependency>
<dependency>
    <groupId>org.apache.poigroupId>
    <artifactId>poi-ooxml-schemasartifactId>
    <version>4.1.2version>
dependency>

Gradle

    compile 'org.apache.poi:poi:4.1.2'
    compile 'org.apache.poi:poi-ooxml:4.1.2'
    compile 'org.apache.poi:poi-ooxml-schemas:4.1.2'

excel导入数据到数据库原理。

  1. 当我们拿到excel表格,我们第一步应该先读取excel里面的数据信息。
  2. 通过特定的方法将读出来的数据封装到对象中。
  3. 每一行表示一个对象,每一列表示一个对象中的每一个字段属性。
  4. 当有多行时我们需要使用List(Object是对应excel表格数据的实体类对象)来存取对象
  5. 拿到对象数组后,我们可以通过遍历得到,每一个对象,再通过mybatis将对象导入到数据库
  6. 知道了原理,有了思路。我们就可以开始干活了。
    1、先拿到excel文件,我们使用MultipartFile接受文件。
    2、拿到文件后。通过文件得到一个输入流
    3、通过poi对excel进行解析,将表格中的每个数据通过for循环得到。

    demo案例:(内附注释)

    先了解到我们需要保存哪些字段。
    根据字段。创建对应的实体类。

    实体类

    public class BuiPatientInfo{
    
    private static final long serialVersionUID = 1L;
    
    
        /**
         * 患者姓名
         */
        @TableField("patient_name")
            private String patientName;
    
    
        /**
         * 加密存储,不可反编译、列表不显示
         */
        @TableField("patient_identity")
            private String patientIdentity;
    
    
        /**
         * 就诊卡号
         */
        @TableField("healing_Id")
            private String healingId;
    
    
        /**
         * (性别)自动从身份证中截取
         */
        @TableField("patient_sex")
            private Integer patientSex;
    
    
        /**
         * (出生年月)自动从身份证中截取
         */
        @TableField("patient_birthDate")
            private LocalDate patientBirthdate;
    
    
        /**
         * 其他信息说明
         */
        @TableField("else_Info")
            private String elseInfo;
    
    
        /**
         * 创建人ID
         */
        @TableField("create_id")
            private Long createId;
    
    
        /**
         * 创建时间
         */
        @TableField("create_time")
            private LocalDateTime createTime;
    
    
        /**
         * 最后修改时间
         */
        @TableField("update_time")
            private LocalDateTime updateTime;
    
    
    
        @TableField("patient_state")
        private Integer patientState;
    
    }
    
    • 以下代码包含了对excel文件的检验是否合法。excel是哪年版的。

    数据导入解析工具类

    package com.mosukj.util;
    
    import com.mosukj.manage.entity.BuiPatientInfo;
    import com.spire.ms.System.DateTime;
    import org.apache.poi.hssf.usermodel.HSSFCell;
    import org.apache.poi.hssf.usermodel.HSSFWorkbook;
    import org.apache.poi.ss.usermodel.*;
    import org.apache.poi.xssf.usermodel.XSSFWorkbook;
    import org.springframework.web.multipart.MultipartFile;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.text.DecimalFormat;
    import java.time.LocalDate;
    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @author xjt
     * @version 1.0
     */
    public class ReadPatientExcelUtil {
        //总行数
        private static int totalRows = 0;
        //总条数
        private static int totalCells = 0;
        //错误信息接收器
        private static String errorMsg;
    
        /**
         * 读EXCEL文件,获取信息集合
         * @return
         */
        public static List<BuiPatientInfo> getExcelInfo(MultipartFile mFile) {
            String fileName = mFile.getOriginalFilename();//获取文件名
            try {
                if (!validateExcel(fileName)) {// 验证文件名是否合格
                    return null;
                }
                boolean isExcel2003 = true;// 根据文件名判断文件是2003版本还是2007版本
                if (isExcel2007(fileName)) {
                    isExcel2003 = false;
                }
                List<BuiPatientInfo> userList = createExcel(mFile.getInputStream(), isExcel2003);
                return userList;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
        /**
         * 根据excel里面的内容读取客户信息
         * @param is 输入流
         * @param isExcel2003 excel是2003还是2007版本
         * @return
         * @throws IOException
         */
        public static List<BuiPatientInfo> createExcel(InputStream is, boolean isExcel2003) {
            try{
                Workbook wb = null;
                if (isExcel2003) {// 当excel是2003时,创建excel2003
                    wb = new HSSFWorkbook(is);
                } else {// 当excel是2007时,创建excel2007
                    wb = new XSSFWorkbook(is);
                }
                List<BuiPatientInfo> userList = readExcelValue(wb);// 读取Excel里面客户的信息
                return userList;
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
        /**
         * 读取Excel里面客户的信息
         * @param wb
         * @return
         */
        private static List<BuiPatientInfo> readExcelValue(Workbook wb) {
        //默认会跳过第一行标题
            // 得到第一个shell
            Sheet sheet = wb.getSheetAt(0);
            // 得到Excel的行数
            totalRows = sheet.getPhysicalNumberOfRows();
            // 得到Excel的列数(前提是有行数)
            if (totalRows > 1 && sheet.getRow(0) != null) {
                totalCells = sheet.getRow(0).getPhysicalNumberOfCells();
            }
            List<BuiPatientInfo> userList = new ArrayList<BuiPatientInfo>();
            // 循环Excel行数
            for (int r = 1; r < totalRows; r++) {
                Row row = sheet.getRow(r);
                if (row == null){
                    continue;
                }
                BuiPatientInfo user = new BuiPatientInfo();
                // 循环Excel的列
                for (int c = 0; c < totalCells-1; c++) {
                    Cell cell = row.getCell(c);
                    if (null != cell) {
                        if (c == 0) {           //第一列
                            //如果是纯数字,将单元格类型转为String
                            if(cell.getCellTypeEnum()  == CellType.NUMERIC){
                                cell.setCellType(CellType.STRING);
                            }
                            user.setPatientName(cell.getStringCellValue());//将单元格数据赋值给user
                        }
                        else if (c == 1){
                            if(cell.getCellTypeEnum()  == CellType.NUMERIC){
                                cell.setCellType(CellType.STRING);
                            }
                            user.setPatientIdentity(cell.getStringCellValue());
                        }
                        else if (c == 2){
                            if(cell.getCellTypeEnum()  == CellType.NUMERIC){
                                cell.setCellType(CellType.STRING);
                            }
                            String stringCellValue = cell.getStringCellValue();
                            user.setHealingId(stringCellValue);
                        }
                        else if (c == 3){
                            if(cell.getCellTypeEnum()  == CellType.NUMERIC){
                                cell.setCellType(CellType.STRING);
                            }
                            user.setElseInfo(String.valueOf(cell.getStringCellValue()));
                        }
                    }
                }
                //将excel解析出来的数据赋值给对象添加到list中
                user.setUpdateTime(LocalDateTime.now());
                user.setPatientBirthdate(IdentityUtil.getPatientBirth(user.getPatientIdentity()));		//拿到身份中好通过已经写好的通过身份证信息获取出生年月工具类
                user.setPatientSex(IdentityUtil.getPatientSex(user.getPatientIdentity()));			//通过省份证号,获取男女信息工具类
                user.setPatientState(1);			//当前实体类字段是固定的,不是excel数据中的。每个对象都可以再遍历完后增加固定属性值
                user.setCreateId(2L);
                user.setCreateTime(LocalDateTime.now());
                // 添加到list
                userList.add(user);
            }
            return userList;
        }
        /**
         * 验证EXCEL文件
         *
         * @param filePath
         * @return
         */
        public static boolean validateExcel(String filePath) {
            if (filePath == null || !(isExcel2003(filePath) || isExcel2007(filePath))) {
                errorMsg = "文件名不是excel格式";
                return false;
            }
            return true;
        }
        // @描述:是否是2003的excel,返回true是2003
        public static boolean isExcel2003(String filePath)  {
            return filePath.matches("^.+\\.(?i)(xls)$");
        }
        //@描述:是否是2007的excel,返回true是2007
        public static boolean isExcel2007(String filePath)  {
            return filePath.matches("^.+\\.(?i)(xlsx)$");
        }
    }
    

    调用getExcelInfo可以得到一个对象数组。

    之后就方便导入数据库了

    我拿到数组对象后的处理方式:

    实例业务接口如下

    @PostMapping("/excelExport")
        public void test(HttpServletRequest request,HttpServletResponse response,@RequestParam(value="file",required = false) MultipartFile file){
            long startTime = System.currentTimeMillis();
            List<String> list = new ArrayList();
            Map<String,Object> res = new HashMap<>();
            int row=1;
            int rowSuccess=0;
            Integer errorCount=0;
            QueryWrapper<BuiPatientInfo> wrapper;
    //        ReadExcel readExcel = new ReadExcel();
            List<BuiPatientInfo> excelInfo = ReadPatientExcelUtil.getExcelInfo(file);
            for (BuiPatientInfo patientInfo : excelInfo) {
    //            System.out.println(patientInfo);
                wrapper=new QueryWrapper<>();
                row++;
                patientInfo.setHealingId(patientInfo.getHealingId());
                wrapper.eq("healing_Id", patientInfo.getHealingId());
                wrapper.ne("patient_state", 9);
                //业务代码,通过患者id查询数据库中式否有该患者,如果已存在,则不保存,跳过该患者
                int patientCount = buiPatientInfoService.getBaseMapper().getPatientCount(wrapper);
                if (patientCount>0){
                    list.add("在第"+row+"行的<"+patientInfo.getHealingId()+">患者已存在!!");
                    errorCount++;
                }else {
                    boolean save = buiPatientInfoService.save(patientInfo);
                    if (save){
                        rowSuccess++;
                    }
                }
            }
            if (list.size()>0){
                res.put("log", list);
            }
            res.put("success", "导入数据成功条数:"+rowSuccess);
            res.put("error", "导入数据失败条数:"+errorCount);
            long endTime = System.currentTimeMillis();
            String time = String.valueOf((endTime - startTime) / 1000);
            res.put("time", "导入数据用时:"+time+"秒");
            renderResult(response, res);
        }
    

    renderResult()是封装好的返回前端数据的一个工具类,如需了解,请异步我的另一篇文章
    封装好的返回前端数据工具类详情(传送门)

    excel模板
    通过java将Excel表格导入数据到数据库_第1张图片

    以上从excel获取数据导入到数据库为静态的导入,动态获取字段导入到数据库请移步笔者其他文章链接:动态导入数据到数据库。(注意,excel模板为固定字段,每一列对应工具类里面的获取第1/2/3…)

    1. 调用成功后返回。导入失败数据所在的行号,并注释姓名(根据需要可修改)。
    2. 成功导入条数。
    3. 导入用时
    4. 导入成功数、导入失败数

    另外。如有需要,以上用到的根据身份证号获取出生年月日与性别的工具类。请通知,可另附。
    有疑问欢迎大家评论区讨论交流!乐意解答。

    你可能感兴趣的:(java,io,poi,excel,java,数据库)