ExcelImportHelper.java

package com.mycim.webapp.utils;

import com.mycim.framework.utils.exception.UtilException;
import com.mycim.framework.utils.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
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 org.apache.struts.upload.FormFile;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author shijie.deng
 * @version 6.0.0
 * @date 2019/9/8
 **/
public class ExcelImportHelper {


    private static final String XLS_TYPE = "XLS";                             // Excel 2007 之前,后缀为.xls

    private static final String XLSX_TYPE = "XLSX";                            // Excel 2007 之后,后缀为.xlsx

    private String excelType = null;                              // XLS_TYPE or XLSX_TYPE Excel类型

    private Workbook workbook = null;

    private Sheet sheet = null;

    private Row row = null;

    private Cell cell = null;

    private int totalRows = 0;                                 // 总行数

    private short totalCells = 0;                                 // 总列数

    private Map<String, String> stringMapData = null;                              // 存储字符串Map

    private List<String[]> stringArrayList = null;                              // 存储字符串数组List

    private SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd"); // 日期格式yyyy-mm-dd

    /**
     * 读取Excel
     *
     * @param filePath   文件路径
     * @param sheetIndex 表索引,第一个表为0
     * @throws IOException
     */
    public ExcelImportHelper(String filePath, int sheetIndex, FormFile upFile) {
        try {
            setExcelType(filePath);
            if (XLSX_TYPE.equals(excelType)) {
                initXLSX(upFile, sheetIndex);
            } else if (XLS_TYPE.equals(excelType)) {
                initXLS(upFile, sheetIndex);
            }
        } catch (Exception e) {
            //TODO: csv
            throw new UtilException("excel.unsupport_file", "Unsupported file format!", e);
        }
    }

    private void initXLS(FormFile upFile, int sheetIndex) throws IOException {
        this.workbook = getHssfWorkbook(upFile.getInputStream());
        this.sheet = getHssfSheet(sheetIndex);

        setTotalRows(sheet);
    }

    private void initXLSX(FormFile upFile, int sheetIndex) throws IOException {
        // 获取Excel引用
        this.workbook = getXssfWorkbook(upFile.getInputStream());
        // 获取Excel引用的第几张表
        this.sheet = getXssfSheet(sheetIndex);
        // 获取总行数
        setTotalRows(sheet);
    }

    // ---------- Private Methods

    /**
     * 设置当前读取Excel文件类型
     *
     * @param filePath 文件路径
     */
    private void setExcelType(String filePath) {
        this.excelType = "X".equals(StringUtils.substringAfter(filePath.toUpperCase(), ".XLS")) ? XLSX_TYPE : XLS_TYPE;
    }

    /**
     * 获取当前读取Excel文件类型
     *
     * @return XLS_TYPE or XLSX_TYPE
     */
    public String getExcelType() {
        return excelType;
    }

    /**
     * 获取文件字节流
     *
     * @param filePath 文件路径
     * @return FileInputStream
     * @throws FileNotFoundException
     */
    private FileInputStream getFile(String filePath) throws FileNotFoundException {
        return new FileInputStream(new File(filePath));
    }

    // ----- For XLS

    /**
     * XLS类型的Excel引用
     *
     * @param file 文件字节流
     * @return HSSFWorkbook
     * @throws IOException
     */
    private HSSFWorkbook getHssfWorkbook(InputStream file) throws IOException {
        return new HSSFWorkbook(file);
    }

    /**
     * XLS类型的Excel表单
     *
     * @param sheetIndex 表单索引,第一个表为0
     * @return HSSFSheet
     */
    private HSSFSheet getHssfSheet(int sheetIndex) {
        return (HSSFSheet) this.workbook.getSheetAt(sheetIndex);
    }

    /**
     * XLS类型的Excel表单中的行
     *
     * @param rowNum 行号
     * @return HSSFRow
     */
    private HSSFRow getHSSFRow(int rowNum) {
        return (HSSFRow) sheet.getRow(rowNum);
    }

    /**
     * XLS类型的Excel表单中的列
     *
     * @param rowNum  行号
     * @param cellNum 列号
     * @return HSSFCell
     */
    private HSSFCell getHSSFCell(int rowNum, int cellNum) {
        return getHSSFRow(rowNum).getCell(cellNum);
    }

    // ----- For XLSX

    /**
     * XLSX类型的Excel引用
     *
     * @param file 文件字节流
     * @return XSSFWorkbook
     * @throws IOException
     */
    private XSSFWorkbook getXssfWorkbook(InputStream file) throws IOException {
        return new XSSFWorkbook(file);
    }

    /**
     * XLSX类型的Excel表单
     *
     * @param sheetIndex 表单索引
     * @return XSSFSheet
     */
    private XSSFSheet getXssfSheet(int sheetIndex) {
        return (XSSFSheet) this.workbook.getSheetAt(sheetIndex);
    }

    /**
     * XLSX类型的Excel表单中的行
     *
     * @param rowNum 行号
     * @return XSSFRow
     */
    private XSSFRow getXSSFRow(int rowNum) {
        return (XSSFRow) sheet.getRow(rowNum);
    }

    /**
     * XLSX类型的Excel表单中的列
     *
     * @param rowNum  行号
     * @param cellNum 列号
     * @return XSSFCell
     */
    private XSSFCell getXSSFCell(int rowNum, int cellNum) {
        return getXSSFRow(rowNum).getCell(cellNum);
    }

    /**
     * 设置总行数
     *
     * @param sheet 表单引用 HSSFSheet or XSSFSheet
     */
    private void setTotalRows(Sheet sheet) {
        this.totalRows = sheet.getLastRowNum() + 1;
    }

    /**
     * 设置某行的总列数
     *
     * @param row 行引用 HSSFRow or XSSFRow
     */
    private void setTotalCells(Row row) {
        this.totalCells = row.getLastCellNum();
    }

    // ---------- Public Methods

    /**
     * 获取Excel引用
     *
     * @return HSSFWorkbook or XSSFWorkbook
     */
    public Workbook getWorkbook() {
        return workbook;
    }

    /**
     * 获取Excel表单
     *
     * @return HSSFSheet or XSSFSheet
     */
    public Sheet getSheet() {
        return sheet;
    }

    /**
     * 获取Excel的行
     *
     * @param i 行号
     * @return HSSFRow or XSSFRow
     */
    public Row getRow(int i) {
        return XLSX_TYPE.equals(excelType) ? getXSSFRow(i) : getHSSFRow(i);
    }

    /**
     * 获取Excel的列
     *
     * @param i 行号
     * @param j 列号
     * @return HSSFCell or XSSFCell
     */
    public Cell getCell(int i, int j) {
        return XLSX_TYPE.equals(excelType) ? getXSSFCell(i, j) : getHSSFCell(i, j);
    }

    /**
     * 检查第i行是否为空行
     *
     * @param i 行号
     * @return boolean ? true : false
     */
    public boolean isRowNotNull(int i) {
        row = getRow(i);

        if (row != null) {
            setTotalCells(row);
            return true;
        }

        return false;
    }

    /**
     * 获取第i行第j列的单元格的值 除日期类型,其他类型全处理为文本,与表格内容一致
     *
     * @param i 行号
     * @param j 列号
     * @return String 单元格中的数据
     */
    public String getCellStringValue(int i, int j) {

        String val = null;

        cell = getCell(i, j);

        if (cell != null) {
            if (cell.getCellTypeEnum().equals(CellType.NUMERIC) && DateUtil.isCellDateFormatted(cell)) {
                val = new SimpleDateFormat("yyyy-MM-dd").format(cell.getDateCellValue());
            } else {
                cell.setCellType(CellType.STRING);
                val = cell.toString().trim();
            }
        }
        return val == null ? "" : val.trim();

    }

    /**
     * Map类型的数据集合<br>
     *
     * @return Map<br> key: R + i + C + j <br> R代表行,i行号,C代表列,j列号<br> e.g: map.get("R11C12")<br>
     * 第11行第12列的单元格中的值
     */
    public Map<String, String> getStringMapData() {
        stringMapData = new HashMap<>();
        for (int i = 0; i < totalRows; i++) {
            if (isRowNotNull(i)) {
                for (int j = 0; j < totalCells; j++) {
                    stringMapData.put("R" + i + "C" + j, getCellStringValue(i, j));
                }
            }
        }
        return stringMapData;
    }

    /**
     * String类型数组的List集合<br>
     *
     * @return List<br> Row,String[]: List.get(i) <br> Cell,String: List.get(i)[j]<br> e.g:
     * list.get(11)[12]<br> 第11行第12列的单元格中的值
     */
    public List<String[]> getStringArrayList() {
        stringArrayList = new ArrayList<>();
        for (int i = 0; i < totalRows; i++) {
            if (isRowNotNull(i)) {
                String[] strings = new String[totalCells];
                for (int j = 0; j < totalCells; j++) {
                    strings[j] = getCellStringValue(i, j);
                }
                stringArrayList.add(strings);
            }
        }
        return stringArrayList;
    }

    /**
     * 关闭流
     *
     * @throws IOException
     */
    public void closeExcel() throws IOException {
        if (workbook != null) {
            workbook.close();
        }
    }


}