前言

做OA管理系统的时候,刚好有个需求:数据批量导入数据库功能,一般都是用Excel文件导入,这里就以Excel为例

工具及插件

项目框架:SpringBoot + Mybatis + MySQL

第三方插件:Lombok

项目引用的是Apache poi导入Excel文件

导入的Excel 样式,如图:

注意:这里Excel中的sheet有几个个硬性要求

    1. sheet的名字无所谓,但位置一定要是放在第一个

    2. 列名顺序绝对不能乱!!!后台是获根据每个列号来获取数据的!!

java从excel表格导入数据 java实现excel导入数据库_poi

一、前端调用

使用ajax调用后台接口,上传Excel文件

二、后端接口

代码中引用了lombok插件,直接使用注解的方式

Result类 是我自己封装的一个返回结果类

Maven

<!-- poi -->
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi</artifactId>
	<version>3.17</version>
</dependency>
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi-ooxml</artifactId>
	<version>3.17</version>
</dependency>
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi-scratchpad</artifactId>
	<version>3.17</version>
</dependency>

控制层Controller

import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Map;

@RestController
@RequestMapping("excel")
public class ExcelController {

	@Autowired
    private ExcelService excelService;

    /**
     * 批量导入
     */
    @RequestMapping("/importExcel")
    public Result<?> importExcel(@RequestParam(value = "file") MultipartFile file) {
        try {
            if (file != null){
                String result = personService.importExcel(file);
                if ("200".equals(result)){
                    return Result.succeed("导入成功");
                }else {
                    return Result.failed("导入失败");
                }
            }else {
                return Result.failed("表格为空");
            }
        }catch (Exception e){
            e.printStackTrace();
            return Result.failed("导入异常");
        }
    }

}

业务逻辑层

/**
 * 业务逻辑 接口
 */
public interface ExcelService {

	public String importExcel(MultipartFile file) throws IOException;
	
}

数据库数据处理的时候,逻辑上可能会比较繁琐

读取excel文件,然后一行一行的新增入库

获取Excel的时候,这里用到工具类自动分析数据类型,虽然工具类的容错率比较高,但是还会出现一些“诡异”的异常,这就需要自己手动去判断了

例如,日期格式

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 业务逻辑 实现类
 */
@Service
public class excelServiceImpl implements HrInterviewService {
	
	// 数据库调用接口
	@Autowired
    private PersonDao personDao;

    @Override
    public String importExcel(MultipartFile file) throws IOException {
        InputStream in = file.getInputStream();
        XSSFWorkbook wb = new XSSFWorkbook(in);
        XSSFSheet sheet = wb.getSheetAt(0);
        int lastRowNum = sheet.getLastRowNum();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        for (int i = 1; i <= lastRowNum; i++){
            XSSFRow row = sheet.getRow(i);
            /** excel取值 */
			//取日期
            Date nowDate = null;
            if (row.getCell(0) != null) {
                if (row.getCell(0).getCellType() == Cell.CELL_TYPE_STRING) {
                    String nowDateStr = row.getCell(0).getStringCellValue();
                    try {
                        nowDate = sdf.parse(nowDateStr);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                } else {
                    nowDate = row.getCell(0).getDateCellValue();
                }
            }
			//取城市
            String city = ExcelUtils.getCell(row.getCell(1));
			//取街道
            String street = ExcelUtils.getCell(row.getCell(2));
			//取姓名
            String userName = ExcelUtils.getCell(row.getCell(3));
			//取性别
            String sex = ExcelUtils.getCell(row.getCell(4));
			//取年龄
            String age = ExcelUtils.getCell(row.getCell(5));
			//取联系方式
            String telephone = null;
            if (row.getCell(6) != null){
                telephone = row.getCell(6).getRawValue();
            }
            /** Excel获取到的数据封装入库 */
            Person item = new Person();
            item.setNowDate(nowDate);
            item.setUserName(userName);
            if(sex != null){
                if ("女".equals(sex)){
                    item.setSex(0);
                }else if ("男".equals(sex)){
                    item.setSex(1);
                }
            }
            if (age != null && !"".equals(age)){
                item.setAge(Integer.valueOf(age));
            }
            item.setTelephone(telephone);
			//调用保存接口,数据添加的代码我就不提供了
			personDao.save(item);
        }
        return "200";
    }

}

实体类层

import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;

@Data
public class Person implements Serializable{
    private static final long serialVersionUID = 1L;
    // id
    private Integer id;
	// 日期
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
    private Date nowDate;
	// 城市
    private String city;
	// 街道
    private String street;
	// 姓名
    private String userName;
	// 性别
    private Integer sex;
	// 年龄
    private Integer age;
	// 联系方式
    private String telephone;
}

工具类

这里提供了两种单元格类型分析方法,我用的第一种,当然也可以用第二种

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.prefs.BackingStoreException;

/**
 * Excel工具类
 */
public class ExcelUtils {

    /**
     * 批量导入时 判断单元格类型1
     */
    public static String getCell(XSSFCell cell) {
        if (cell == null){
            return "";
        }else {
            DecimalFormat df = new DecimalFormat("#");
            switch (cell.getCellType()) {
				// 数字
                case XSSFCell.CELL_TYPE_NUMERIC:
                    return new Double(cell.getNumericCellValue()).intValue() + "";
				// 字符串
                case XSSFCell.CELL_TYPE_STRING:
                    return cell.getStringCellValue();
				// 函数
                case XSSFCell.CELL_TYPE_FORMULA:
                    return cell.getCellFormula();
				// 空值
                case XSSFCell.CELL_TYPE_BLANK:
                    return "";
				// 布尔类型
                case XSSFCell.CELL_TYPE_BOOLEAN:
                    return cell.getBooleanCellValue() + "";
				// 异常
                case XSSFCell.CELL_TYPE_ERROR:
                    return cell.getErrorCellValue() + "";
                default:
                    return "";
            }
        }
    }
	/**
     * 批量导入时 判断单元格类型2
     */
	public static String getCell2(XSSFCell cell) {
        String cellValue = "";
        // 以下是判断数据的类型
        switch (cell.getCellTypeEnum()) {
			// 数字
            case NUMERIC: 
                if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) {
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                    cellValue = sdf.format(org.apache.poi.ss.usermodel.DateUtil.getJavaDate(cell.getNumericCellValue())).toString();
                } else {
                    DataFormatter dataFormatter = new DataFormatter();
                    cellValue = dataFormatter.formatCellValue(cell);
                }
                break;
			// 字符串
            case STRING: 
                cellValue = cell.getStringCellValue();
                break;
			// Boolean
            case BOOLEAN: 
                cellValue = cell.getBooleanCellValue() + "";
                break;
			// 公式
            case FORMULA: 
                cellValue = cell.getCellFormula() + "";
                break;
			// 空值
            case BLANK: 
                cellValue = "";
                break;
			// 故障
            case ERROR: 
                cellValue = "非法字符";
                break;
            default:
                cellValue = "未知类型";
                break;
        }
        return cellValue;
    }

}