JAVA工具类——Excel的读取和校验

目录

  • 一、问题场景
  • 二、方法概述
  • 三、相关代码
    • 3.1 工具类依赖
    • 3.2 工具类代码
  • 四、写在后面

一、问题场景

最近,在写项目中需要用到 Excel 相关操作,所以写了一个工具类,现记录如下:
其中可能会涉及到的工具类:

  1. JAVA工具类——身份证校验
  2. JAVA工具类——电话号码校验

二、方法概述

Excel 中所有的校验均将错误情况添加到最后一列,也可以根据需求改为抛出异常。

  1. streamToWorkbook():根据文件后缀创建 Workbook 对象
  2. getNonNullRowCount() :获取非空行数
  3. getCellCount():获取总列数 以表头为准
  4. verifyExcelTitle() :校验 Excel 表头是否正常
  5. setCellToEmpty() :将某列设置为空
  6. replaceExcelTitle() :替换表头,方便返回返回给前端,防止乱码
  7. getExcelCellIndex() :根据表头自适应获取列范围(不用自己数,避免出错)
  8. checkCellAreaNonNull() :校验列区间非空 => 判断 [start, end] 列非空
  9. getIndexAccordingToTitleName() :根据表头名得到列索引
  10. verifyTheCellLength() :校验某一列的位数
  11. verifyMobileCell() :校验某一列是否均为手机号
  12. verifyIdCardCell() :校验某一列是否均为身份证号
  13. verifyDateCell() :校验某一列是否均为日期
  14. resolveExcelToJson() :将 Excel 解析为 Json => {“1”:{},“2”:{},…}
  15. isNonEmptyCell() :判断单元格非空
  16. getCellObject() :获取 row 行 第 cellNum 个单元格对象
  17. isNonEmptyRow() :判断行非空
  18. getCellValue() :得到 Excel 指定单元格的值 String 类型
  19. isEmptyCell() :校验列非空

三、相关代码

3.1 工具类依赖


        
        <dependency>
            <groupId>joda-timegroupId>
            <artifactId>joda-timeartifactId>
            <version>2.10.14version>
        dependency>

        
        <dependency>
            <groupId>org.junit.jupitergroupId>
            <artifactId>junit-jupiterartifactId>
            <version>RELEASEversion>
            <scope>compilescope>
        dependency>

        
        <dependency>
            <groupId>cn.afterturngroupId>
            <artifactId>easypoi-spring-boot-starterartifactId>
            <version>4.2.0version>
        dependency>

        <dependency>
            <groupId>cn.afterturngroupId>
            <artifactId>easypoi-baseartifactId>
            <version>4.2.0version>
        dependency>

3.2 工具类代码

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.joda.time.DateTime;

import java.io.FileInputStream;
import java.util.Date;

import static org.apache.poi.ss.usermodel.CellType.BLANK;
import static org.apache.poi.ss.usermodel.CellType.STRING;

public class ExcelUtil {

    /**
     * 根据文件后缀创建 Workbook 对象
     */
    public static Workbook streamToWorkbook(String name, FileInputStream inputStream) throws Exception {
        // 1.得到一个工作簿
        Workbook workbook = null;
        // 2.判断 Excel 是 03版 还是 07版
        if (name.toLowerCase().endsWith("xls")) {
            workbook = new HSSFWorkbook(inputStream);
        } else if (name.toLowerCase().endsWith("xlsx")) {
            workbook = new XSSFWorkbook(inputStream);
        } else if (StringUtils.isEmpty(name)) {
            throw new Exception("未接收到文件");
        } else {
            throw new Exception("文件格式错误");
        }
        return workbook;
    }

    /**
     * 获取非空行数
     */
    public static int getNonNullRowCount(Workbook workbook) {
        int count = 0;
        // 1.得到工作表
        Sheet sheet = workbook.getSheetAt(0);
        // 2.得到总行数
        int rowCount = sheet.getLastRowNum();
        for (int rowNum = 0; rowNum < rowCount; rowNum++) {
            Row row = sheet.getRow(rowNum);
            if (isNonEmptyRow(row)) {
                count++;
            }
        }
        return count;
    }

    /**
     * 获取总列数 以表头为准
     */
    public static int getCellCount(Sheet sheet) {
        int count = 0;
        // 1.得到第0行
        Row row = sheet.getRow(0);
        if (isNonEmptyRow(row)) {
            return 0;
        } else {
            return row.getLastCellNum();
        }
    }

    /**
     * 校验 Excel 表头是否正常
     *
     * @param workbook
     * @param titleString 正确的表头顺序(即 实例化的对象 / 存入数据库 的顺序)
     */
    public static void verifyExcelTitle(Workbook workbook, String[] titleString) throws Exception {
        // 1.得到工作表
        Sheet sheet = workbook.getSheetAt(0);
        // 2.得到首行(表头)
        Row rowTitle = sheet.getRow(0);
        // 3.获得列的总数
        int cellCount = getCellCount(sheet);
        if (cellCount != titleString.length) {
            throw new Exception("模板列缺失");
        }
        // 4.遍历表头
        for (int cellNum = 0; cellNum < cellCount; cellNum++) {
            // 5.获取表头第 cellNum 个数据
            Cell cell = rowTitle.getCell(cellNum);
            // 6.判断 cell 中数据和默认表头是否对应
            // 为空 || 类型非字符串 || 和 titleString 不对应
            if (!isNonEmptyCell(cell)) {
                throw new Exception("请不要修改模板");
            }
        }
    }

    /**
     * 将某列设置为空
     *
     * @param workbook
     * @param cellNum
     */
    public static void setCellToEmpty(Workbook workbook, int cellNum) {
        Sheet sheet = workbook.getSheetAt(0);
        int rowCount = sheet.getLastRowNum();
        for (int rowNum = 1; rowNum <= rowCount; rowNum++) {
            Row row = sheet.getRow(rowNum);
            if (isNonEmptyRow(row)) {
                Cell cell = row.getCell(cellNum);
                if (isNonEmptyCell(cell)) {
                    cell.setCellType(BLANK);
                }
            }
        }
    }

    /**
     * 用 newTitleString 替换表头
     * 方便返回返回给前端,防止乱码
     *
     * @param workbook
     * @param newTitleString 一般为英文数组,方便前后端交互
     */
    public static void replaceExcelTitle(Workbook workbook, String[] newTitleString) throws Exception {
        // 1.得到工作表
        Sheet sheet = workbook.getSheetAt(0);
        // 2.得到首行(表头)
        Row rowTitle = sheet.getRow(0);
        // 3.获得列的总数
        int cellCount = rowTitle.getLastCellNum();
        // 4.遍历表头
        for (int cellNum = 0; cellNum < cellCount; cellNum++) {
            // 5.获取表头第 cellNum 个数据
            Cell cell = rowTitle.getCell(cellNum);
            // 6.更改为 newTitleString 的第 cellNum 个数据
            cell.setCellValue(newTitleString[cellNum]);
        }
    }


    /**
     * 根据表头自适应获取列范围(不用自己数,避免出错)
     *
     * @param startTitle 索引开始表头
     * @param endTitle   索引结束表头
     * @return [startTitle, endTitle] 所在索引
     */
    public static int[] getExcelCellIndex(Workbook workbook, String startTitle, String endTitle) throws Exception {
        int[] indexes = new int[2];
        // 1.得到工作表
        Sheet sheet = workbook.getSheetAt(0);
        // 2.得到首行(表头)
        Row rowTitle = sheet.getRow(0);
        // 3.获得列的总数
        int cellCount = rowTitle.getLastCellNum();
        // 4.遍历表头
        for (int cellNum = 0; cellNum < cellCount; cellNum++) {
            // 5.获取表头第 cellNum 个数据
            Cell cell = rowTitle.getCell(cellNum);
            // 6.校验数据是否相同
            if (cell.getStringCellValue().equals(startTitle)) {
                indexes[0] = cellNum;
            }
            if (cell.getStringCellValue().equals(endTitle)) {
                indexes[1] = cellNum;
            }
        }
        return indexes;
    }


    /**
     * 校验列区间非空 => 判断 start列 到 end列 是否非空 ,即 [start, end] 列非空 并将提示增加到最后一列
     *
     * @param start 包含该列 从 0 开始
     * @param end   不包含该列
     */
    public static void checkCellAreaNonNull(Workbook workbook, int start, int end, String[] promptTitleString) throws Exception {
        // 1.得到工作表
        Sheet sheet = workbook.getSheetAt(0);
        int cellWriteIndex = sheet.getRow(0).getLastCellNum();
        // 2.判断 start 列 到 end 列是否非空
        int rowCount = sheet.getLastRowNum();
        for (int rowNum = 1; rowNum <= rowCount; rowNum++) {
            Row row = sheet.getRow(rowNum);
            if (isNonEmptyRow(row)) {
                for (int cellNum = start; cellNum <= end; cellNum++) {
                    Cell cellWrite = getCellObject(row, cellNum);
                    cellWrite.setCellValue(getCellValue(cellWrite) + promptTitleString[cellNum] + "必填;");
                }
            }
        }
    }


    /**
     * 根据表头名得到列索引
     */
    public static int getIndexAccordingToTitleName(Row rowTitle, int cellCount, String titleName) throws Exception {
        int cellIndex = -1;
        // 遍历表头
        for (int cellNum = 0; cellNum < cellCount; cellNum++) {
            Cell cell = rowTitle.getCell(cellNum);
            if (titleName.equals(getCellValue(cell))) {
                cellIndex = cellNum;
                break;
            }
        }
        return cellIndex;
    }

    /**
     * 校验某一列的位数
     */
    public static void verifyTheCellLength(Workbook workbook, String titleName, int length) throws Exception {
        // 1.得到工作表
        Sheet sheet = workbook.getSheetAt(0);
        // 2.得到首行(表头)
        Row rowTitle = sheet.getRow(0);
        // 3.获得列的总数
        int cellCount = rowTitle.getLastCellNum();
        int cellIndex = getIndexAccordingToTitleName(rowTitle, cellCount, titleName);
        int rowCount = sheet.getLastRowNum();
        for (int rowNum = 1; rowNum <= rowCount; rowNum++) {
            Row row = sheet.getRow(rowNum);
            if (isNonEmptyRow(row)) {
                Cell cell = row.getCell(cellIndex);
                if (isNonEmptyCell(cell)) {
                    String cellValue = getCellValue(cell);
                    if (cellValue.length() != length) {
                        Cell cellWrite = getCellObject(row, cellCount);
                        cellWrite.setCellValue(getCellValue(cell) + titleName + "值错误;");
                    }
                }
            }
        }
    }


    /**
     * 校验某一列是否均为手机号
     */
    public static void verifyMobileCell(Workbook workbook, String titleName) throws Exception {
        // 1.得到工作表
        Sheet sheet = workbook.getSheetAt(0);
        // 2.得到首行(表头)
        Row rowTitle = sheet.getRow(0);
        // 3.获得列的总数
        int cellCount = rowTitle.getLastCellNum();
        int cellIndex = getIndexAccordingToTitleName(rowTitle, cellCount, titleName);
        int rowCount = sheet.getLastRowNum();
        for (int rowNum = 1; rowNum <= rowCount; rowNum++) {
            Row row = sheet.getRow(rowNum);
            if (isNonEmptyRow(row)) {
                Cell cell = row.getCell(cellIndex);
                if (isNonEmptyCell(cell)) {
                    String mobileNumberValue = getCellValue(cell);
                    if (!MobileUtil.isLegalMobileNumber(mobileNumberValue)) {
                        Cell cellWrite = getCellObject(row, cellCount);
                        cellWrite.setCellValue(getCellValue(cell) + titleName + "格式错误;");
                    }
                }
            }
        }
    }

    /**
     * 校验某一列是否均为身份证号
     */
    public static void verifyIdCardCell(Workbook workbook, String titleName) throws Exception {
        // 1.得到工作表
        Sheet sheet = workbook.getSheetAt(0);
        // 2.得到首行(表头)
        Row rowTitle = sheet.getRow(0);
        // 3.获得列的总数
        int cellCount = rowTitle.getLastCellNum();
        int cellIndex = getIndexAccordingToTitleName(rowTitle, cellCount, titleName);
        int rowCount = sheet.getLastRowNum();
        for (int rowNum = 1; rowNum <= rowCount; rowNum++) {
            Row row = sheet.getRow(rowNum);
            if (isNonEmptyRow(row)) {
                Cell cell = row.getCell(cellIndex);
                if (isNonEmptyCell(cell)) {
                    String idCardValue = getCellValue(cell);
                    if (!IdentityUtils.isLegalIdCard(idCardValue)) {
                        Cell cellWrite = getCellObject(row, cellCount);
                        cellWrite.setCellValue(getCellValue(cell) + titleName + "格式错误;");
                    }
                }
            }
        }
    }

    /**
     * 校验某一列是否均为日期
     */
    public static void verifyDateCell(Workbook workbook, String titleName) throws Exception {
        // 1.得到工作表
        Sheet sheet = workbook.getSheetAt(0);
        // 2.得到首行(表头)
        Row rowTitle = sheet.getRow(0);
        // 3.获得列的总数
        int cellCount = rowTitle.getLastCellNum();
        int cellIndex = getIndexAccordingToTitleName(rowTitle, cellCount, titleName);
        int rowCount = sheet.getLastRowNum();
        for (int rowNum = 1; rowNum <= rowCount; rowNum++) {
            Row row = sheet.getRow(rowNum);
            if (isNonEmptyRow(row)) {
                Cell cell = row.getCell(cellIndex);
                if (isNonEmptyCell(cell)) {
                    if (!DateUtil.isCellDateFormatted(cell)) {
                        Cell cellWrite = getCellObject(row, cellCount);
                        cellWrite.setCellValue(getCellValue(cell) + titleName + "格式错误;");
                    }
                }
            }
        }
    }

    /**
     * 将 Excel 解析为 Json =>  {"1":{},"2":{},...}
     */
    public static JSONObject resolveExcelToJson(Workbook workbook) throws Exception {
        JSONObject infos = new JSONObject();
        Sheet sheet = workbook.getSheetAt(0);
        Row rowTitle = sheet.getRow(0);
        int cellCount = rowTitle.getLastCellNum();
        String[] titleString = new String[cellCount];
        for (int titleNum = 0; titleNum < cellCount; titleNum++) {
            Cell cell = rowTitle.getCell(titleNum);
            if (isNonEmptyCell(cell)) {
                titleString[titleNum] = getCellValue(cell);
            }
        }
        int rowCount = sheet.getLastRowNum();
        for (int rowNum = 1; rowNum <= rowCount; rowNum++) {
            Row row = sheet.getRow(rowNum);
            JSONObject info = new JSONObject();
            if (isNonEmptyRow(row)) {
                for (int cellNum = 0; cellNum < cellCount; cellNum++) {
                    Cell cell = row.getCell(cellNum);
                    if (isNonEmptyCell(cell)) {
                        info.put(titleString[cellNum], getCellValue(cell));
                    }
                }
                infos.put(String.valueOf(rowNum), info);
            }
        }
        return infos;
    }

    /**
     * 判断单元格非空
     */
    public static boolean isNonEmptyCell(Cell cell) {
        return cell != null && cell.getCellType() != BLANK && !(cell.getCellType() == STRING && StringUtils.isEmpty(cell.getStringCellValue()));
    }

    /**
     * 获取 row 第 cellNum 个单元格对象
     */
    public static Cell getCellObject(Row row, int cellNum) {
        Cell cellObject = row.getCell(cellNum);
        return cellObject == null ? row.createCell(cellNum) : cellObject;
    }

    /**
     * 判断行非空
     */
    public static boolean isNonEmptyRow(Row row) {
        if (row == null) {
            return false;
        }
        int cellCount = row.getLastCellNum();
        for (int cellNum = 0; cellNum < cellCount; cellNum++) {
            Cell cell = row.getCell(cellNum);
            if (isNonEmptyCell(cell)) {
                return true;
            }
        }
        return true;
    }

    /**
     * 得到 Excel 指定单元格的值 String 类型
     */
    public static String getCellValue(Cell cell) throws Exception {
        CellType cellType = cell.getCellType();
        String cellValue = "";
        switch (cellType) {
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) { // 日期   可能无法识别
                    Date date = cell.getDateCellValue();
                    cellValue = new DateTime(date).toString("yyyy-MM-dd");
                } else {
                    // 不是日期格式 防止数字过长
                    cell.setCellType(STRING);
                    cellValue = cell.toString();
                }
                break;
            case FORMULA:
                cellValue = cell.getCellFormula();
                break;
            case STRING:
                cellValue = cell.getStringCellValue();
                break;
            case BOOLEAN: // 布尔
                cellValue = String.valueOf(cell.getBooleanCellValue());
                break;
            case BLANK: // 空
                break;
            case ERROR:
                throw new Exception("单元格类型异常");
        }
        return cellValue;
    }

    /**
     * 校验列非空
     */
    public static boolean isEmptyCell(Workbook workbook, int cellNum) throws Exception {
        // 1.得到工作表
        Sheet sheet = workbook.getSheetAt(0);
        // 2.判断 start 列 到 end 列是否非空
        int rowCount = sheet.getLastRowNum();
        for (int rowNum = 0; rowNum <= rowCount; rowNum++) {
            Row row = sheet.getRow(rowNum);
            if (isNonEmptyRow(row)) {
                Cell cell = row.getCell(cellNum);
                if (isNonEmptyCell(cell)) {
                    return false;
                }
            }
        }
        return true;
    }
}

四、写在后面

欢迎关注,实现期间会经常发一些工作中遇到的问题。

欢迎随时留言讨论,与君共勉,知无不答!

你可能感兴趣的:(Utils工具类大全,java,开发语言)