【Java】【46】导入Excel到数据库

前言:

业务场景:用户提供Excel表,在页面上点击“导入按钮”,系统读取Excel中的数据,存到对应的数据库

注:

1,目前仅提供导入简单的Excel表,没有合并单元格,只能读取单页sheet

2,方法里用到了具体业务场景的实体类,所以适用性不是很强,其他场景要用的话,还需要修改代码。但是也具有一定的参考性,所以先记录下来。我的后续思路是:在 工具类(ReadExcelUtil) 里根据导入的Excel表头确定要处理的字段名,然后拼成json格式的数据,传到Service层,再做处理。之后再做更新 //TODO

3,用的jar包:POI

正文:

html:

<div>
    <span><input type="file" id="upfile" name="upfile" placeholder=""/></span>
    <button onclick="importExp();">导入</button>
    <span>格式:.xls</span>
</div>

JS:

function importExp() {
    var name = $("#upfile").val();
    var file =  $("#upfile")[0].files[0];
    // ajax...
}

Java:

Controller层

@ApiOperation(value = "导入Excel")
@RequestMapping(value="excel/import", method = RequestMethod.POST)
public void importExcel(MultipartFile file) {
    return this.theService.importExcel(file);
}

Service层

public void importExcel(MultipartFile file) {
    if(file.isEmpty()){
        //请先选择Excel文件。是否把报错等信息返回到前端,视情况而定。
        return;
    }

    Result readResult = ReadExcelUtil.readExcel(file);  //Result是封装了返回值的类,相当于实体类

    if(readResult.getCode() != 0){ 
        //错误:readResult.msg
        return;
    }
    List<Award> list = (List<Award>) readResult.getData(); //Award是数据库表对应的实体类 

    //获取了list之后,insert到数据库... 
}

工具类:

ReadExcelUtil

package com.bf.base.utils;

import com.bf.base.entity.DripAward;
import com.bf.base.params.Result;
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.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

public class ReadExcelUtil {

    /**
     * 读取 单页sheet,返回一个集合
     * @return
     */
    public static Result<?> readDripAwardExcel(MultipartFile file) {
        Result result = new Result<>();
        InputStream is = null;
        Workbook wb = null;
        String fileName = file.getOriginalFilename();
        String fileType = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());

        try {
            is = file.getInputStream();

            if (fileType.equals("xls")) {
                wb = new HSSFWorkbook(is);
            } else if (fileType.equals("xlsx")) {
                wb = new XSSFWorkbook(is);
            } else {
                return new Result<>(Result.FAIL, "读取的不是excel文件", null, null);
            }

            int sheetSize = wb.getNumberOfSheets();//有多少sheet页
            if(sheetSize >= 2){
                return new Result<>(Result.FAIL, "请核对Excel的页数", null, null);
            }

            Sheet sheet = wb.getSheetAt(0);
            result = sheetData2List(sheet); //关键,sheet表数据 转 集合

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

        return result;
    }

    //获取数据
    private static Result sheetData2List(Sheet sheet) {
        Result result = new Result<>();
        List<Award> awards = new ArrayList<>();
        int CELL_SIZE = 3; //excel固定三列(编码、金额)       
        int rowSize = sheet.getLastRowNum() + 1;

        for (int j = 0; j < rowSize; j++) { //读取每一行
            Row row = sheet.getRow(j);
            if (row == null) {
                continue;
            }

            if(row.getLastCellNum() != CELL_SIZE){
                result.setCode(2);
                result.setMsg("第"+ j +"行数据异常,请核对后再上传!");
                return result;
            }

            if (j == 0) {
                continue;
            } else {
                DripAward rowObj = new DripAward();
                for (int k = 0; k < CELL_SIZE; k++) { //获取列的数据
                    Cell cell = row.getCell(k);
                    String value = getCellFormatValue(cell);
                    switch (k) {
                        case 0:
                            rowObj.setCode(AESUtil.encrypt(value));
                            break;
                        case 1:
                            rowObj.setAmount(Double.parseDouble(value));
                            break;
                        case 2:
                            rowObj.setClassify(Integer.parseInt(value));
                            break;
                        default:
                            break;
                    }
                }
                awards.add(rowObj);
            }            
        }

        result.setCode(0);
        result.setData(awards);
        return result;
    }

    //获取列的数据
    private static String getCellFormatValue(Cell cell) {
        String cellvalue = "";
        if (cell != null) {
            CellType cellType = cell.getCellTypeEnum();
            switch (cellType) {
                case NUMERIC: {
                    if(String.valueOf(cell.getNumericCellValue()).indexOf("E") == -1){
                        cellvalue =  String.valueOf(cell.getNumericCellValue());
                    }else {
                        cellvalue =  new DecimalFormat("#").format(cell.getNumericCellValue());
                    }
                    break;
                }
                case STRING:
                    cellvalue = cell.getRichStringCellValue().getString();
                    break;
                default:
                    cellvalue = "-";
            }
        }

        return cellvalue;
    }
}

其他:

Result (封装了返回值的类,相当于实体类)

package com.bf.base.params;

import org.apache.commons.lang.StringUtils;

/**
 * 传给前端数据的统一格式
 * code = 0时,表示调用成功
 * 其余code均表示调用接口异常,异常时,标明异常码,并给出msg和detail注释,同步文档
 */
public class Result<T> {
    
    private int code;//状态返回码
    
    private String msg;//返回码描述
    
    private String detail;//错误详细描述或返回码对应处理方案
    
    private T data;//返回的主体数据

    public static final int FAIL = -1;

    public static final int SUCCESS = 0;

    @Override
    public String toString() {
        return "Result [code=" + code + ", msg=" + msg + ", detail=" + detail + ", data=" + data + "]";
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public String getDetail() {
        return detail;
    }

    public void setDetail(String detail) {
        this.detail = detail;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
    
}

Award(数据库表对应的实体类)

public class Award {
    private String code;

    private Double amount;

    private int classify;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public Double getAmount() {
        return amount;
    }

    public void setAmount(Double amount) {
        this.amount = amount;
    }

    public int getClassify() {
        return classify;
    }

    public void setClassify(int classify) {
        this.classify = classify;
    }
}

 

posted @ 2019-08-16 22:13  花生喂龙  阅读(295)  评论(0编辑  收藏  举报