最近,在写项目中需要用到 Excel
相关操作,所以写了一个工具类,现记录如下:
其中可能会涉及到的工具类:
- JAVA工具类——身份证校验
- JAVA工具类——电话号码校验
Excel
中所有的校验均将错误情况添加到最后一列,也可以根据需求改为抛出异常。
streamToWorkbook()
:根据文件后缀创建 Workbook 对象getNonNullRowCount()
:获取非空行数getCellCount()
:获取总列数 以表头为准verifyExcelTitle()
:校验 Excel 表头是否正常setCellToEmpty()
:将某列设置为空replaceExcelTitle()
:替换表头,方便返回返回给前端,防止乱码getExcelCellIndex()
:根据表头自适应获取列范围(不用自己数,避免出错)checkCellAreaNonNull()
:校验列区间非空 => 判断 [start, end] 列非空getIndexAccordingToTitleName()
:根据表头名得到列索引verifyTheCellLength()
:校验某一列的位数verifyMobileCell()
:校验某一列是否均为手机号verifyIdCardCell()
:校验某一列是否均为身份证号verifyDateCell()
:校验某一列是否均为日期resolveExcelToJson()
:将 Excel 解析为 Json => {“1”:{},“2”:{},…}isNonEmptyCell()
:判断单元格非空getCellObject()
:获取 row 行 第 cellNum 个单元格对象isNonEmptyRow()
:判断行非空getCellValue()
:得到 Excel 指定单元格的值 String 类型isEmptyCell()
:校验列非空
<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>
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;
}
}
欢迎关注,实现期间会经常发一些工作中遇到的问题。
欢迎随时留言讨论,与君共勉,知无不答!