Springboot 整合导入Excel文件读取数据,支持windows和linux

参考博客:https://blog.csdn.net/rexueqingchun/article/details/82586950

备注:基于参考博客调整方法在windows和linux都可使用

1.导入的excel所在目录为D:/cs/test.xls,测试数据如下图所示

2.创建与excel表头对应的xml模版,文件名import_job_number.xml

<?xml version="1.0" encoding="UTF-8"?>

<!-- 导入的模版校验文件 -->
<execelImport>
    <field>姓名</field>
    <field>工号</field>
</execelImport>

3.目录结构

 

创建导入数据对应实体类

package com.gandong.etcm.manager.controller.params;


public class SevBankUserParams {


    /**
     * 用户名
     */
    private String realName;
    /**
     * 工号
     */
    private String username;



    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getRealName() {
        return realName;
    }

    public void setRealName(String realName) {
        this.realName = realName;
    }

    public void setValues(String[] values) throws Exception{
         //必须与配置文件对应
        this.realName = values[0] ==null?"":values[0].trim();
        this.username = values[1] ==null?"":values[1].trim();

    }




}

 

控制层

 /**
     * 批量导入工号
     * @return
     * @throws Exception
     */
    @PostMapping("/recordJobNumber")
    public Result recordJobNumber(@RequestParam("file")MultipartFile file)throws Exception{
        log.info("==========================");
        return sevBankUserService.recordJobNumber(file);
    }

业务层

  Result recordJobNumber(MultipartFile file)throws Exception;

 @Override
    public Result recordJobNumber(MultipartFile file) throws Exception{
       InputStream is = file.getInputStream() ;
       //读取数据
        ExecelUtil eu = new ExecelUtil(is, "import_job_number.xml", SevBankUserParams.class,".xls",env);
        SevBankUserParams cp = null;
        List<SevBankUser>   userList=new ArrayList<>();
     //循环遍历
        while (eu.hasNext()) {
            if (eu.validate()) {
                cp = (SevBankUserParams) eu.getObjectBean();
                //取到数据后需要处理的业务逻辑 
                SevBankUser user=SevBankUser
                        .builder()
                        .id( UUID.randomUUID().toString().replaceAll("-", ""))
                        .username(cp.getUsername())
                        .userPwd(commonUtil.sha1Encrypt("233688"))
                        .bankCode(cp.getUsername().substring(0,2))
                        .realName(cp.getRealName())
                        .createTime(new Date())
                        .build();
                //查询是否有重复工号
                Integer  number=    sevBankUserMapper.selectSevBankUserByUsernameNumber(cp.getUsername());
                if (number>0){
                    userList.add(user);
                }else {
                    //插入数据库
                    sevBankUserMapper.saveSevBankUser(user);

                }
                log.info(cp.getUsername()+"/"+cp.getRealName());
            }
        }
        //返回前台工号重复数据
    return Result.success(userList);
    }

工具类

package com.gandong.etcm.manager.util.common.excelUtil;

import java.io.*;
import java.net.URLDecoder;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

import com.gandong.etcm.manager.controller.params.SevBankUserParams;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.core.io.ClassPathResource;
import org.springframework.expression.EvaluationException;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;

@Slf4j
public class ExecelUtil {

    private String description = "";// 如果校验失败,将会给出详细提示信息
    private Sheet sheet;// execel 对象
    private List<String> fieldList;//从xml读取到的execel表格信息
    private int rowIndex = 0;//当前操作行
    private Object objectBean;//每一行数据封装
    private Cell cellStart;// 数据的开始单元格
    private Class clazz; //需要封装的类
    private Validator validator; //hibernate 的校验器
    private String[] fieldVals ; //从execel读到的某一行的数据
    private int fieldSize = 0;  //有效数据的列数
    private DateFormat format = new SimpleDateFormat("yyyy-MM-dd"); // 针对日期的默认转换形式
    private Expression exp ;//EL 解析器
    private ExpressionParser parser;

    private DecimalFormat df = new DecimalFormat("#");

    public String getDescription() {
        return description;
    }

    public Object getObjectBean() {
        return objectBean;
    }



    /**
     *
     * @param
     *
     * @param xmlFilename
     *
     * @param env : dev-本地  test-测试  prod-生产
     */
    public ExecelUtil(InputStream execelIS,String xmlFilename,Class clazz,String suffix,String env) throws Exception{
        // 打开execel工作簿
        Workbook wb = null;
        try {
            if(suffix.equals(".xls")){
                wb = new HSSFWorkbook(execelIS);
            }else if(suffix.equals(".xlsx")){
                wb = new XSSFWorkbook(execelIS);
            }
            execelIS.close();
        } catch (IOException e) {
            log.error(""+e);
            throw new Exception("加载文件失败,请确保是否是Execel表格");
        }
        sheet = wb.getSheetAt(0);// 默认取第一个工作簿
        //读配置文件,获取所有的属性列描述
        if (env.equals("dev")){

            fieldList = this.readFieldsFromXML(getAbsolutePath(xmlFilename),env);
        }else {

            fieldList = this.readFieldsFromXML(xmlFilename,env);
        }
        //个数
        fieldSize = fieldList.size();

        //找到有效数据的开始单元格
        cellStart = this.findStartCell();
        if(cellStart == null){
            throw new Exception(this.description);
        }

        //每次读取一行execel数据,rowIndex每次增1
        rowIndex = cellStart.getRowIndex()+1;

        //需要封装的对象类
        this.clazz = clazz;
        //初始化校验器
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        validator = factory.getValidator();
        //初始化EL解析器
        parser = new SpelExpressionParser();
        exp = parser.parseExpression("values");
    }

    //是否还有数据
    public boolean hasNext(){
        Row row = sheet.getRow(rowIndex++);
        if(row == null)
            return false;
        fieldVals = this.getRowValues(row, cellStart.getColumnIndex());
        if(Arrays.asList(fieldVals).indexOf("") != -1){
            for(String s :fieldVals)//如果每个字段都是空的,则返回false 否则true
                if(!s.equals(""))
                    return true;
            return false;
        }
        return true;
    }
    //校验
    public boolean validate(){
        try {
            objectBean = Class.forName(clazz.getName()).newInstance();
        } catch (Exception e) {
            log.error(""+e);
        }

        try{
            exp.setValue(objectBean, fieldVals);// 给objectBean的属性赋值

        }catch(EvaluationException e){//由于所有的数据类型转换都有objectBean里面来处理,故可能有异常,需要进行相应的处理
            System.out.println(e);
            List exList = Arrays.asList("ParseException","NumberFormatException");//一般可能发生的异常
            Throwable t = e.getCause();
            while(t!=null){
                String causeClazz = t.getClass().getSimpleName();
                if(exList.contains(causeClazz)){
                    this.description = "第" +rowIndex+"行,类型转换失败:"+t.getMessage();
                    return false;
                }else if(causeClazz.equals("Exception")){//自定义异常
                    this.description = "第" +rowIndex+"行,"+t.getMessage();
                    return false;
                }else
                    t = t.getCause();
            }
            //this.description = parser.parseExpression("sales").getValue(objectBean,String.class);
            this.description = "数据错误";
            return false;
        }
        //校验,校验规则是配置在objectBean对象里面
        Set<ConstraintViolation<Object>> constraintViolations = validator.validate(objectBean);

        if(constraintViolations.size() >0){//校验失败时,提示相应信息
            this.description = "第" +rowIndex+"行,校验出错:";
            for (ConstraintViolation<Object> vl : constraintViolations) {
                this.description = this.description + vl.getMessage()+" ;  ";
            }
            return false;
        }
        return true;
    }

    private String[] getRowValues(Row row,int columnStartIndex){
        String[] values = new String[fieldSize];
        for(int j = columnStartIndex,t=0;t<fieldSize;j++,t++){
            Cell c = row.getCell(j);
            if(c==null){
                values[t] = "";
                continue;
            }
            switch(c.getCellType()){
                case Cell.CELL_TYPE_BLANK:
                    values[t] = "";
                    break;
                case Cell.CELL_TYPE_BOOLEAN:
                    values[t] = String.valueOf(c.getBooleanCellValue());
                    break;
                case Cell.CELL_TYPE_NUMERIC:

                    if (HSSFDateUtil.isCellDateFormatted(c)) {
                        values[t] = format.format(c.getDateCellValue());
                    } else if(c.getCellStyle().getDataFormat() == 58) {
                        // 处理自定义日期格式:m月d日(通过判断单元格的格式id解决,id的值是58)
                        SimpleDateFormat sdf = new SimpleDateFormat("MM/dd");
                        double value = c.getNumericCellValue();
                        Date date = org.apache.poi.ss.usermodel.DateUtil
                                .getJavaDate(value);

                        values[t] = sdf.format(date);
                    }
                    else {
                        values[t] = new DecimalFormat("#").format(c.getNumericCellValue());
                    }
                    break;
                case Cell.CELL_TYPE_STRING:
                    values[t] = String.valueOf(c.getStringCellValue());
                    break;

                default:
                    values[t] = "";
                    break;
            }
        }
        return values;
    }
    // 根据某一个单元格,得到更人性化的显示,例如“A4”
    private String getCellRef(Cell cell) {
        return CellReference.convertNumToColString(cell.getColumnIndex()) + (cell.getRowIndex() + 1);
    }
    private  String getAbsolutePath(String file) throws Exception {
        try {
            file="src/main/resources/"+file;
          log.info("file==========="+file);
        } catch (NullPointerException e) {
            throw new Exception(file+", 文件不存在");
        }
        try {
            // 解决当出现中文路径时不能解析的bug
            file = URLDecoder.decode(file, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new Exception(file+",解码失败");
        }
        return file;
    }
    private List<String> readFieldsFromXML(String xmlFilename,String env)throws Exception{
        SAXReader reader = new SAXReader();
        Document document = null;

        try {

            if (env.equals("dev")){
                document = reader.read(new File(xmlFilename));// 加载配置文件
            }else {
                ClassPathResource classPathResource = new ClassPathResource(xmlFilename);
                document = reader.read(classPathResource.getInputStream());// 加载配置文件
            }
        } catch (DocumentException e) {
            e.printStackTrace();
            this.description = "IO 异常,读取配置文件失败";
            throw new Exception(xmlFilename+",IO 异常,读取配置文件失败");
        }

        Element root = document.getRootElement();
        List<String> fields = new ArrayList<String>();
        for (Iterator iter = root.elementIterator("field"); iter.hasNext();) {
            Element field = (Element) iter.next();
            fields.add(field.getTextTrim());
        }

        return fields;
    }
    /**
     * 从execel表中找到数据开始的单元格
     * @return
     */
    private  Cell findStartCell(){
        String firstFieldDesc = this.fieldList.get(0);
        int endRow = sheet.getLastRowNum()>100?100:sheet.getLastRowNum();
        for(int i = 0;i<=endRow;i++){
            Row r = sheet.getRow(i);
            if (r == null)
                continue;
            for(int j = 0;j < r.getLastCellNum();j++){
                Cell c = r.getCell(j);
                if( c == null)
                    continue;
                if(c.getCellType() == Cell.CELL_TYPE_STRING){
                    if(c.getStringCellValue().trim().equals(firstFieldDesc)){//找到第一个符合要求的字段,接下来判断它相邻的字段是否都符合要求
                        if(fieldList.size()>r.getLastCellNum()-j){
                            this.description = "execel表格与所给配置描述不符,请下载模板文件";
                            return null;
                        }
                        for(int k=j+1,t=1;k<=j+fieldList.size()-1;k++,t++){
                            Cell c2 = r.getCell(k);
                            if(c2 == null){
                                this.description = "请确保单元格"+this.getCellRef(c2)+"内容是\""+fieldList.get(t)+"\"";
                                return null;
                            }
                            if(c2.getCellType() == Cell.CELL_TYPE_STRING){
                                if(c2.getStringCellValue().contains(fieldList.get(t)))
                                    continue;
                                else{
                                    this.description = "请确保单元格"+this.getCellRef(c2)+"内容是\""+fieldList.get(t)+"\"";
                                    return null;
                                }
                            }

                        }
                        return c;
                    }else
                        continue;
                }else
                    continue;
            }
        }
        this.description = "找不到\""+fieldList.get(0)+"\"这一列";
        return null;
    }

    public int getRowIndex() {
        return rowIndex;
    }

    public DateFormat getFormat() {
        return format;
    }


    public String createExcelIncludeFailReason(InputStream execelIS,String path,String newExcelName, HashMap<Integer,String> errHash) {
        FileOutputStream file;
        try {
            file = new FileOutputStream(path+"/"+newExcelName);
            Workbook workbook=this.getWorkbook(execelIS);
            Sheet s=workbook.getSheetAt(0);

            //int endRow = sheet.getLastRowNum()>100?100:sheet.getLastRowNum();
            int endRow = sheet.getLastRowNum();
            for(int i=1;i<=endRow;i++){
                if(errHash.get(i)!=null){
                    Row rowkk = s.getRow(i);
                    Cell error_cell = rowkk.createCell(fieldList.size());
                    error_cell.setCellValue(errHash.get(i));
                }
            }
            workbook.write(file);
            file.close();
        } catch (FileNotFoundException e) {

            e.printStackTrace();
        } catch (IOException e) {

            e.printStackTrace();
        } catch (Exception e) {

            e.printStackTrace();
        }

        return newExcelName;
    }


    public String getFile(InputStream execelIS,String path,String appPath, List<Integer> listF, boolean b) {
        FileOutputStream file;
        try {
            file = new FileOutputStream(path+"/"+appPath);
            Workbook workbook=this.getWorkbook(execelIS);
            Sheet s=workbook.getSheetAt(0);
            Row row=null;
            //int endRow = sheet.getLastRowNum()>100?100:sheet.getLastRowNum();
            int endRow = sheet.getLastRowNum();
            for(int i=1;i<=endRow;i++){

                Row rowkk = s.getRow(i);
                Cell info_cell = rowkk.createCell(fieldList.size());
                info_cell.setCellValue("sss");

                //删除错误行
                if(b&& listF.contains(i)){
                    row=s.getRow(i);
                    //System.out.println("错误行删除"+i);
                    if(row!=null)s.removeRow(row);
                }
                //删除正确行
                if(!b && !listF.contains(i)){
                    row=s.getRow(i);
                    //System.out.println("正确行删除"+i);
                    if(row!=null)s.removeRow(row);
                }
            }
            workbook.write(file);
            file.close();
        } catch (FileNotFoundException e) {

            e.printStackTrace();
        } catch (IOException e) {

            e.printStackTrace();
        } catch (Exception e) {

            e.printStackTrace();
        }

        return appPath;
    }
    public  Workbook  getWorkbook(InputStream execelIS) throws Exception{
        Workbook wb = null;
        try {
            wb = new HSSFWorkbook(execelIS);
        } catch (IOException e) {
            log.error(""+e);
            throw new Exception("加载文件失败,请确保是否是Execel表格");
        }
        return wb;
    }

    /**
     * 测试
     * @param args
     * @throws Exception
     */
/*    public static void main(String[] args) throws Exception {
        InputStream is = new FileInputStream("C:\\Users\\Administrator\\Desktop\\test.xls");
        ExecelUtil eu = new ExecelUtil(is, "/import_job_number.xml", Persion.class,".xls");
        Persion cp = null;
        List<Persion> list=new ArrayList<>();
        while (eu.hasNext()) {
            if (eu.validate()) {
                cp = (Persion) eu.getObjectBean();
                list.add(cp);
                System.out.println(cp.getName()+"/"+cp.getSex()+"/"+cp.getPhone()+"/"+cp.getEmail()+"/"+cp.getAddress());
            }
        }
        System.out.println(list.get(0).getName());

    }*/


   /**
     * 测试 
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        InputStream is = new FileInputStream("C:\\Users\\Administrator\\Desktop\\test.xls");
        ExecelUtil eu = new ExecelUtil(is, "/import_job_number.xml", SevBankUserParams.class,".xls","dev");
        SevBankUserParams cp = null;
        List<SevBankUserParams> list=new ArrayList<>();
        while (eu.hasNext()) {
            if (eu.validate()) {
                cp = (SevBankUserParams) eu.getObjectBean();
                list.add(cp);
                System.out.println(cp.getUsername()+"/"+cp.getRealName());
            }
        }
        System.out.println(list.get(0).getRealName());

    }
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值