package com.dstcar.common.utils.excel.common;
import org.springframework.util.StringUtils;
/**
* Description : Excel异常类
*
Created By : liu wei ping
*
Creation Time : 2022年5月10日 下午6:52:58
*/
public class ExcelException extends RuntimeException {
private static final long serialVersionUID = 8834681166062539688L;
private String sheetName;
private Integer sheetIndex;
private Integer rowIndex;
private String columnIndex;
private ExcelExceptionEnum errorCode;
private String errorMessage;
public ExcelException() {
}
public ExcelException(ExcelExceptionEnum errorCode, String errorMessage) {
this.errorCode = errorCode;
this.errorMessage = errorMessage;
}
public String getSheetName() {
return this.sheetName;
}
public void setSheetName(String sheetName) {
this.sheetName = sheetName;
}
public Integer getSheetIndex() {
return this.sheetIndex;
}
public void setSheetIndex(Integer sheetIndex) {
this.sheetIndex = sheetIndex;
}
public Integer getRowIndex() {
return this.rowIndex;
}
public void setRowIndex(Integer rowIndex) {
this.rowIndex = rowIndex;
}
public String getColumnIndex() {
return this.columnIndex;
}
public void setColumnIndex(String columnIndex) {
this.columnIndex = columnIndex;
}
public ExcelExceptionEnum getErrorCode() {
return this.errorCode;
}
public void setErrorCode(ExcelExceptionEnum errorCode) {
this.errorCode = errorCode;
}
public String getErrorMessage() {
return this.errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
public String getMessage() {
StringBuffer buffer = new StringBuffer();
buffer.append("Excel解析错误类型:");
buffer.append(ExcelExceptionEnum.codeToMessage(this.errorCode));
buffer.append(";");
buffer.append("详细描述:");
buffer.append(this.errorMessage);
if (!StringUtils.isEmpty(this.sheetName)) {
buffer.append("Sheet名称:");
buffer.append(this.sheetName);
buffer.append(";");
}
if (!StringUtils.isEmpty(this.rowIndex)) {
buffer.append(this.rowIndex);
buffer.append("行;");
}
if (!StringUtils.isEmpty(this.columnIndex)) {
buffer.append(this.columnIndex);
buffer.append("列;");
}
return buffer.toString();
}
}
package com.dstcar.common.utils.excel.common;
/**
* Description : Excel错误枚举类
*
Created By : liu wei ping
*
Creation Time : 2022年5月14日 上午11:23:12
*/
public enum ExcelExceptionEnum {
//Excel 读取错误代码
ER00001("文件读取错误"),
ER00002("工作区读取错误"),
ER00003("Sheet读取错误"),
ER00004("行读取错误"),
ER00005("单元格读取错误"),
ER00006("实例化对象错误"),
ER00007("对象属性赋值错误"),
//Excel 写入错误代码
EW00001("数据类型转换写入错误!"),
EW00002("创建工作区错误!"),
EW00003("数据类型转换错误!"),
//Excel通用错误代码
EC00001("参数不匹配");
private String message;
private ExcelExceptionEnum() {
}
private ExcelExceptionEnum(String message) {
this.message = message;
}
public String message() {
return this.message;
}
/**
* Description : 错误代码转错误信息
*
Created By : liu wei ping
*
Creation Time : 2022年5月10日 下午6:55:30
*
* @param errorCode
* @return
*/
public static String codeToMessage(ExcelExceptionEnum errorCode) {
for (ExcelExceptionEnum tag : values()) {
if (errorCode.name().equals(tag.name())) {
return tag.message;
}
}
return "";
}
}
package com.dstcar.common.utils.excel.common;
/**
* Description : Excel文件类型枚举类
*
Created By : liu wei ping
*
Creation Time : 2022年5月10日 下午6:13:26
*/
public enum ExcelType {
XLS, XLSX;
}
package com.dstcar.common.utils.excel.common;
import java.beans.PropertyDescriptor;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.util.StringUtils;
import com.dstcar.common.utils.excel.read.ExcelReadConfig;
import com.dstcar.common.utils.excel.read.ExcelUserReadConfig;
import com.dstcar.common.utils.excel.write.ExcelWriteConfig;
/**
* Description : Excel辅助通用类
*
Created By : liu wei ping
*
Creation Time : 2022年5月10日 下午6:56:03
*/
public class ExcelUtil {
//时间格式化
public static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
/**
* Description : Excel导航转索引
*
Created By : [email protected]
*
Creation Time : 2018年5月10日 下午6:56:31
*
* @param columnNav
* @return
*/
public static int convertNavToIndex(String columnNav) {
columnNav = columnNav.toUpperCase();
int result = 0;
int valLength = columnNav.length();
for (int i = 0; i < valLength; i++) {
int num = 0;
char ch = columnNav.charAt(valLength - i - 1);
Validate.isTrue((ch < 'A') || (ch > 'Z'), new StringBuilder().append("非法值:").append(columnNav).toString());
num = ch - 'A' + 1;
num = (int) (num * Math.pow(26.0D, i));
result += num;
}
return result - 1;
}
/**
* Description : Excel索引转导航
*
Created By : [email protected]
*
Creation Time : 2018年5月10日 下午6:56:52
*
* @param index
* @return
*/
public static String convertIndexToNav(int index) {
StringBuilder buffer = new StringBuilder();
for (int i = 0; index >= 0; i++) {
Character c = null;
if (i != 0)
c = Character.valueOf((char) (index % 26 + 65));
else {
c = Character.valueOf((char) (index % 26 + 65 - 1));
}
buffer.insert(0, c);
index = index / 26 - 1;
}
return buffer.toString();
}
/**
* Description : Excel用户输入的配置文件转程序可读配置文件
*
Created By : liu wei ping
*
Creation Time : 2022年5月10日 下午6:57:18
*
* @param userConfig
* @param workbook
* @return
*/
public static ExcelReadConfig converConfig(ExcelUserReadConfig userConfig, Workbook workbook) {
ExcelReadConfig config = new ExcelReadConfig();
//校验
Validate.isTrue(userConfig.getSheetIndex().intValue() < 0, "Sheet值不能小于或等于0!");
//判断用户输入的Sheet索引并转化程序可读的Sheet索引值
if (userConfig.getSheetIndex().intValue() != 0) {
//如果输入的Sheet索引值不为0的话,则由输入的值-1得到程序可读下标
config.setSheetIndex(userConfig.getSheetIndex().intValue() - 1);
} else if (!StringUtils.isEmpty(userConfig.getSheetName())) {
//如果用户没有针对Sheet索引输入的话则根据用户输入的Sheet名称获取Sheet索引
int sheetIndex = workbook.getSheetIndex(userConfig.getSheetName());
if (sheetIndex < 0) {
ExcelException e = new ExcelException();
e.setSheetName(userConfig.getSheetName());
e.setErrorCode(ExcelExceptionEnum.ER00003);
e.setErrorMessage("该Sheet名称不存在!");
throw e;
}
config.setSheetIndex(sheetIndex);
} else {
config.setSheetIndex(userConfig.getSheetIndex());
}
//判断是否有输入起始行
boolean hasStartRowIndex = false;
//校验用户输入的起始行数, 并转化为程序可读的起始行
Validate.isTrue(userConfig.getStartRowIndex().intValue() < 0, "读取Excel的开始行的值不能小于或等于0!");
if (userConfig.getStartRowIndex().intValue() != 0) {
//如果输入的起始行索引值不为0的话,则由输入的值-1得到程序可读下标
config.setStartRowIndex(userConfig.getStartRowIndex().intValue() - 1);
hasStartRowIndex = true;
}
//标识是否存在要读取的结束行
boolean hasEndRowIndex = false;
//校验用户输入要读取的行数, 并转化为程序可读取的行数
if (!StringUtils.isEmpty(userConfig.getEndRowIndex())) {
Validate.isTrue(userConfig.getEndRowIndex().intValue() < 0, "读取Excel的结束行的值不能小于0!");
Validate.isTrue(userConfig.getEndRowIndex().intValue() - 1 < config.getStartRowIndex().intValue(), "读取Excel的结束行值不能小于开始行值!");
config.setEndRowIndex(userConfig.getEndRowIndex().intValue() - 1);
hasEndRowIndex = true;
}
//如果读取行数的参数不为空,则设置结束行 = 其实行 + 读取的行数
if (!StringUtils.isEmpty(userConfig.getReadRowNumber()) && userConfig.getReadRowNumber().intValue() > 0) {
config.setEndRowIndex((userConfig.getStartRowIndex() - 1) + (userConfig.getReadRowNumber() - 1));
hasEndRowIndex = true;
}
//标识用户是否输入了要读取的固定行数
boolean hasReadRowArray = false;
if (null != userConfig.getReadRowIndexArray() && userConfig.getReadRowIndexArray().length > 0) {
config.setReadRowIndexArray(userConfig.getReadRowIndexArray());
hasReadRowArray = true;
}
//判断用户输入的没有起始行
if (!hasStartRowIndex) {
//判断没有结束行
if (!hasEndRowIndex) {
//判断用户也没有输入要读取的固定行
if (!hasReadRowArray) {
//取默认值
config.setStartRowIndex(userConfig.getStartRowIndex());
config.setEndRowIndex(workbook.getSheetAt(config.getSheetIndex().intValue()).getLastRowNum());
}
} else {
//取默认值
config.setStartRowIndex(userConfig.getStartRowIndex());
}
} else {
//如果没有结束行的话,则取结束行的默认值
if (!hasEndRowIndex) {
//取默认值
config.setEndRowIndex(workbook.getSheetAt(config.getSheetIndex().intValue()).getLastRowNum());
}
}
//判断用户读取的列,并转化为程序可识别的参数
Validate.isTrue((null == userConfig.getColumnIndex()) || (userConfig.getColumnIndex().isEmpty()), "读取Excel的列不能为空!");
Map columnIndex = new HashMap();
for (Map.Entry columnKey : userConfig.getColumnIndex().entrySet()) {
Validate.isNotNull(columnKey.getKey(), "列值不能为空!");
columnIndex.put(convertNavToIndex((String) columnKey.getKey()), columnKey.getValue());
}
config.setColumnIndex(columnIndex);
//判断接收实体是否为空
Validate.isTrue(null == userConfig.getTargetClass(), "对象实体类不能为空!");
config.setTargetClass(userConfig.getTargetClass());
return config;
}
/**
* Description : 转化Cell值为Object
*
Created By : liu wei ping
*
Creation Time : 2022年5月10日 下午7:08:25
*
* @param cell
* @return
*/
public static Object convertCell(Cell cell) {
if (cell == null) {
return null;
}
CellType cellType = cell.getCellType();
Object value = null;
switch (cellType) {
case NUMERIC:
Object inputValue = null;
double doubleVal = cell.getNumericCellValue();
if (DateUtil.isCellDateFormatted(cell)) {
inputValue = DateUtil.getJavaDate(doubleVal);
} else {
long longVal = Math.round(cell.getNumericCellValue());
if (Double.parseDouble(longVal + ".0") == doubleVal) {
inputValue = longVal;
} else {
inputValue = doubleVal;
}
}
value = inputValue;
break;
case STRING:
value = cell.getStringCellValue();
break;
case FORMULA:
value = cell.getCellFormula();
break;
case BLANK:
value = null;
break;
case BOOLEAN:
boolean bool = cell.getBooleanCellValue();
value = Boolean.valueOf(bool);
break;
case ERROR:
ExcelException e = new ExcelException();
e.setSheetName(cell.getSheet().getSheetName());
e.setSheetIndex(cell.getSheet().getWorkbook().getSheetIndex(cell.getSheet()));
e.setRowIndex(cell.getRowIndex());
e.setColumnIndex(convertIndexToNav(cell.getColumnIndex()));
e.setErrorCode(ExcelExceptionEnum.ER00005);
e.setErrorMessage("单元格类型错误!无法识别的单元格类型!");
throw e;
default:
throw new ExcelException(ExcelExceptionEnum.ER00001, "不支持的Excel类型:" + cellType);
}
return value;
}
/**
* Description : 验证Excel写入配置文件的有效性
*
Created By : liu wei ping
*
Creation Time : 2022年5月10日 下午7:17:21
*
* @param useExcelTemplate
* @param excelWriteConfig
*/
public static void validateWriteConfig(boolean useExcelTemplate, ExcelWriteConfig excelWriteConfig) {
Validate.isNotNull(excelWriteConfig, "未配置Excel写入信息!");
if (useExcelTemplate) {
Validate.isTrue(StringUtils.isEmpty(excelWriteConfig.getSheetIndex()) && (StringUtils.isEmpty(excelWriteConfig.getSheetName())), "有使用Excel模板,则Sheet索引或Sheet名称不能为空!");
}
Validate.isNotNull(excelWriteConfig.getStartRow(), "开始行索引不能为空!");
Validate.isTrue(excelWriteConfig.getFieldMap().size() < 1, "字段映射不能为空!");
// Validate.isTrue((null == excelWriteConfig.getDataList()) || (excelWriteConfig.getDataList().isEmpty()), "写入Excel的数据不能为空!");
}
/**
* Description : 反射赋值属性
*
Created By : [email protected]
*
Creation Time : 2018年5月10日 下午7:20:09
*
* @param clazz
* @param propertyName
* @return
*/
public static PropertyDescriptor getPropertyDescriptor(Class> clazz, String propertyName) {
return BeanUtils.getPropertyDescriptor(clazz, propertyName);
}
/**
* 获取Cell值
* @param cell
* @return
*/
public static String getCellValue(Cell cell) {
String value = "";
if(cell != null) {
cell.setCellType(CellType.STRING);
value = cell.getStringCellValue();
}
return value.trim();
}
}
package com.dstcar.common.utils.excel.common;
import org.springframework.util.StringUtils;
/**
* Description : 基础校验
*
Created By : liu wei ping
*
Creation Time : 2022年5月10日 下午6:11:20
*/
public class Validate {
/**
* Description : 校验:数据不为空
*
Created By : [email protected]
*
Creation Time : 2018年5月10日 下午6:11:30
*
* @param object
* @param message
* @throws IllegalArgumentException
*/
public static void isNotNull(Object object, String message) throws IllegalArgumentException {
if (StringUtils.isEmpty(object))
throw new IllegalArgumentException(message);
}
/**
* Description : 校验表达式为真
*
Created By : [email protected]
*
Creation Time : 2018年5月10日 下午6:11:44
*
* @param express
* @param message
* @throws IllegalArgumentException
*/
public static void isTrue(boolean express, String message) throws IllegalArgumentException {
if (express)
throw new IllegalArgumentException(message);
}
}
读源码:
package com.dstcar.common.utils.excel.read;
import java.util.Map;
/**
* Description : Read Excel的相关配置
*
Created By : liu wei ping
*
Creation Time : 2022年5月11日 上午9:29:54
*/
public class ExcelReadConfig {
//读取的Sheet索引
private Integer sheetIndex;
//开始行索引
private Integer startRowIndex;
//结束行索引
private Integer endRowIndex;
//固定选择读取的行
private Integer[] readRowIndexArray;
//列索引:Excel列转换后的索引, 属性名
private Map columnIndex;
//返回的实体类
private Class targetClass;
public Integer getSheetIndex() {
return this.sheetIndex;
}
public void setSheetIndex(Integer sheetIndex) {
this.sheetIndex = sheetIndex;
}
public Integer getStartRowIndex() {
return this.startRowIndex;
}
public void setStartRowIndex(Integer startRowIndex) {
this.startRowIndex = startRowIndex;
}
public Integer getEndRowIndex() {
return this.endRowIndex;
}
public void setEndRowIndex(Integer endRowIndex) {
this.endRowIndex = endRowIndex;
}
public Integer[] getReadRowIndexArray() {
return this.readRowIndexArray;
}
public void setReadRowIndexArray(Integer[] readRowIndexArray) {
int length = readRowIndexArray.length;
this.readRowIndexArray = new Integer[length];
for (int i = 0; i < length; i++) {
this.readRowIndexArray[i] = readRowIndexArray[i] - 1;
}
}
public Map getColumnIndex() {
return this.columnIndex;
}
public void setColumnIndex(Map columnIndex) {
this.columnIndex = columnIndex;
}
public Class getTargetClass() {
return this.targetClass;
}
public void setTargetClass(Class targetClass) {
this.targetClass = targetClass;
}
}
package com.dstcar.common.utils.excel.read;
import java.beans.PropertyDescriptor;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.ss.usermodel.WorkbookFactory;
import org.springframework.util.StringUtils;
import com.alibaba.fastjson.util.TypeUtils;
import com.dstcar.common.utils.excel.common.ExcelException;
import com.dstcar.common.utils.excel.common.ExcelExceptionEnum;
import com.dstcar.common.utils.excel.common.ExcelUtil;
import com.dstcar.common.utils.excel.common.Validate;
/**
* Description : 读取Excel相关方法
*
Created By : liu wei ping
*
Creation Time : 2022年5月11日 上午9:32:37
*/
public class ExcelReadValue {
/**
* Description : 读取Excel
*
Created By : [email protected]
*
Creation Time : 2018年5月11日 上午9:34:12
*
* @param file
* @param readConfig
* @return
* @throws ExcelException
*/
public static List readExcel(InputStream file, ExcelUserReadConfig readConfig) throws ExcelException {
//判断文件是否存在
Validate.isTrue(null == file, "未读取到文件!");
//获取工作区
Workbook workbook = getExcelWorkBook(file);
//转换用户输入的Config
ExcelReadConfig excelConfig = ExcelUtil.converConfig(readConfig, workbook);
//读取Sheet
Sheet sheet = getExcelSheet(workbook, excelConfig.getSheetIndex().intValue());
//返回实体
return readExcelValue(sheet, excelConfig);
}
/**
* Description : 获取Excel的工作区
*
Created By : liu wei ping
*
Creation Time : 2022年5月11日 上午9:36:17
*
* @param workbookStream
* @return
* @throws ExcelException
*/
private static Workbook getExcelWorkBook(InputStream workbookStream) throws ExcelException {
Workbook workbook = null;
try {
workbook = WorkbookFactory.create(workbookStream);
} catch (Exception e) {
throw new ExcelException(ExcelExceptionEnum.ER00002, "创建WorkbookFactory失败!");
}
Validate.isTrue(null == workbook, "未读取到工作区!");
return workbook;
}
/**
* Description : 获取Sheet
*
Created By : liu wei ping
*
Creation Time : 2022年5月11日 上午9:36:47
*
* @param workbook
* @param sheetIndex
* @return
*/
private static Sheet getExcelSheet(Workbook workbook, int sheetIndex) {
Sheet sheet = workbook.getSheetAt(sheetIndex);
Validate.isTrue(null == sheet, "未读取到Sheet!");
return sheet;
}
/**
* Description : 读取Excel的数据
*
Created By : liu wei ping
*
Creation Time : 2022年5月11日 上午9:37:28
*
* @param sheet
* @param excelConfig
* @return
* @throws ExcelException
*/
private static List readExcelValue(Sheet sheet, ExcelReadConfig excelConfig) throws ExcelException {
List dataList = new ArrayList();
Row row = null;
//判断起始行及结束行是否有值
if (null != excelConfig.getStartRowIndex() && null != excelConfig.getEndRowIndex()) {
// 循环要读取的行
for (int i = excelConfig.getStartRowIndex(); i <= excelConfig.getEndRowIndex(); i++) {
Map fieldMapping = new HashMap();
//获取行
row = sheet.getRow(i);
if (null != row) {
//循环每一列
for (Map.Entry columnField : excelConfig.getColumnIndex().entrySet()) {
//获取Cell的值
Cell cell = getCellValue(row, columnField.getKey());
fieldMapping.put(columnField.getValue(), cell);
}
//转换为实体数据
T tValue = convertJavaBeanValue(excelConfig.getTargetClass(), fieldMapping);
//检验数据的有效性
if (valueIsEffect(tValue, fieldMapping)) {
dataList.add(tValue);
}
}
}
} else {
//如果没有值的话说明用户需要读取固定的行数
//循环要读取的固定行数
for (Integer index : excelConfig.getReadRowIndexArray()) {
Map fieldMapping = new HashMap();
//获取行
row = sheet.getRow(index);
if (null != row) {
//循环每一列的值
for (Map.Entry columnField : excelConfig.getColumnIndex().entrySet()) {
//读取Cell值
Cell cell = getCellValue(row, (Integer) columnField.getKey());
fieldMapping.put(columnField.getValue(), cell);
}
//转换为实体数据
T tValue = convertJavaBeanValue(excelConfig.getTargetClass(), fieldMapping);
//检验数据的有效性
if (valueIsEffect(tValue, fieldMapping)) {
dataList.add(tValue);
}
}
}
}
return dataList;
}
/**
* Description : 获取Cell的值
*
Created By : liu wei ping
*
Creation Time : 2022年5月11日 上午11:09:24
*
* @param row
* @param columnIndex
* @return
*/
private static Cell getCellValue(Row row, Integer columnIndex) {
Validate.isTrue(null == row, "读取的Row为空!");
Validate.isTrue(null == columnIndex, "索引列无效:" + columnIndex);
//判断获取的Cell值是否为空
if (null == row.getCell(columnIndex)) {
return null;
}
return row.getCell(columnIndex);
}
/**
* Description : 将数据转换为实体对象数据
*
Created By : liu wei ping
*
Creation Time : 2022年5月11日 上午11:09:54
*
* @param targetClazz
* @param excelValue
* @return
* @throws ExcelException
*/
private static T convertJavaBeanValue(Class targetClazz, Map excelValue) throws ExcelException {
T tClass = null;
try {
tClass = targetClazz.newInstance();
} catch (Exception e) {
throw new ExcelException(ExcelExceptionEnum.ER00006, "目标对象反射实例化过程出错!");
}
//循环映射该实体对象的数据
for (Map.Entry column : excelValue.entrySet()) {
//获取属性
PropertyDescriptor property = ExcelUtil.getPropertyDescriptor(targetClazz, column.getKey());
//获取参数类型
Class> paramType = property.getWriteMethod().getParameterTypes()[0];
//转换并返回
Object value = TypeUtils.cast(ExcelUtil.convertCell(column.getValue()), paramType, null);
try {
//写入
property.getWriteMethod().invoke(tClass, value);
} catch (Exception e) {
throw new ExcelException(ExcelExceptionEnum.ER00007, "目标对象属性反射赋值过程出错!");
}
}
return tClass;
}
/**
* Description : 判断数据是否有效
* 既判断不为空的对象其属性也不包含不为空的数据
*
Created By : liu wei ping
*
Creation Time : 2022年5月11日 下午3:23:46
*
* @param valueClass
* @param excelValue
* @return
* @throws ExcelException
*/
private static boolean valueIsEffect(T valueClass, Map excelValue) throws ExcelException {
//获取该数据实体类的类
Class> clazz = valueClass.getClass();
//标识数据是否有效, 有效的依据为该实体中只要存在一个不为空的属性既有效
boolean isEffect = false;
//循环要判断的属性
for (Map.Entry column : excelValue.entrySet()) {
PropertyDescriptor property = ExcelUtil.getPropertyDescriptor(clazz, column.getKey());
try {
//获取该属性的值
Object obj = property.getReadMethod().invoke(valueClass);
//判断该值是否为空
if (!StringUtils.isEmpty(obj)) {
isEffect = true;
return isEffect;
}
} catch (Exception e) {
throw new ExcelException(ExcelExceptionEnum.ER00007, "目标对象属性反射赋值过程出错!");
}
}
return isEffect;
}
}
package com.dstcar.common.utils.excel.read;
import java.util.Map;
/**
* Description : 读取Excel用户输入的相关配置
* 优先级顺序如下:
* SheetIndex > SheetName
* endRowIndex > readRowNumber && readRowIndexArray
* null == endRowIndex -> [readRowNumber > readRowIndexArray]
* null == endRowIndex && null == readRowNumber && null == readRowIndexArray -> [startRowIndex = 0 && endRowIndex = data.lastRow]
*
*
Created By : liu wei ping
*
Creation Time : 2022年5月11日 上午9:53:11
*/
public class ExcelUserReadConfig {
//Sheet名称
private String sheetName;
//Sheet索引
private Integer sheetIndex = 0;
//开始行索引
private Integer startRowIndex = 0;
//结束行索引
private Integer endRowIndex;
//读取行数
private Integer readRowNumber;
//读取的固定行
private Integer[] readRowIndexArray;
//列:Excel列, 属性名; 例:Map<"A", "name">
private Map columnIndex;
//选择接收返回数据的实体类
private Class targetClass;
public String getSheetName() {
return this.sheetName;
}
public void setSheetName(String sheetName) {
this.sheetName = sheetName;
}
public Integer getSheetIndex() {
return this.sheetIndex;
}
public void setSheetIndex(Integer sheetIndex) {
this.sheetIndex = sheetIndex;
}
public Integer getStartRowIndex() {
return this.startRowIndex;
}
public void setStartRowIndex(Integer startRowIndex) {
this.startRowIndex = startRowIndex;
}
public Integer getEndRowIndex() {
return this.endRowIndex;
}
public void setEndRowIndex(Integer endRowIndex) {
this.endRowIndex = endRowIndex;
}
public Integer getReadRowNumber() {
return this.readRowNumber;
}
public void setReadRowNumber(Integer readRowNumber) {
this.readRowNumber = readRowNumber;
}
public Integer[] getReadRowIndexArray() {
return this.readRowIndexArray;
}
public void setReadRowIndexArray(Integer[] readRowIndexArray) {
this.readRowIndexArray = readRowIndexArray;
}
public Map getColumnIndex() {
return this.columnIndex;
}
public void setColumn(Map columnIndex) {
this.columnIndex = columnIndex;
}
public Class getTargetClass() {
return this.targetClass;
}
public void setTargetClass(Class targetClass) {
this.targetClass = targetClass;
}
}
写源码:
package com.dstcar.common.utils.excel.write;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.util.StringUtils;
import com.dstcar.common.utils.excel.common.ExcelUtil;
import com.dstcar.common.utils.excel.common.Validate;
import com.dstcar.common.utils.excel.write.ExcelWriteFieldMapping.ExcelWriteFieldAttribute;
/**
* Description : Excel 写入配置
*
Created By : liu wei ping
*
Creation Time : 2022年5月11日 上午11:21:24
*/
public class ExcelWriteConfig {
//Sheet索引
private Integer sheetIndex;
//Sheet名称
private String sheetName;
//开始行
private Integer startRow;
//头部:转换后的索引, 标题名称
private Map headsMap = new HashMap();
//字段:转换后的索引, 字段名
private Map fieldMap = new HashMap();
//数据
private List dataList;
public Integer getSheetIndex() {
return this.sheetIndex;
}
public void setSheetIndex(Integer sheetIndex) {
sheetIndex = sheetIndex - 1;
Validate.isTrue(sheetIndex.intValue() < 0, "Sheet索引值不能小于1");
this.sheetIndex = sheetIndex;
}
public String getSheetName() {
return this.sheetName;
}
public void setSheetName(String sheetName) {
this.sheetName = sheetName;
}
public Integer getStartRow() {
return this.startRow;
}
public void setStartRow(Integer startRow) {
startRow = startRow - 1;
Validate.isTrue(startRow.intValue() < 0, "开始行数值不能小于1");
this.startRow = startRow;
}
public Map getHeadsMap() {
return this.headsMap;
}
public Map getFieldMap() {
return this.fieldMap;
}
public List getDataList() {
return this.dataList;
}
public void setDataList(List dataList) {
this.dataList = dataList;
}
public void setExcelWriteFieldMapping(ExcelWriteFieldMapping excelWriteFieldMapping) {
Validate.isTrue(null == excelWriteFieldMapping, "字段映射不可为空!");
Map> userInputFieldMapping = excelWriteFieldMapping.getFieldMapping();
//解析Head及列
for (Map.Entry> inputMap : userInputFieldMapping.entrySet()) {
Map fieldMapping = inputMap.getValue();
for (Map.Entry fieldMap : fieldMapping.entrySet()) {
String headValue = fieldMap.getValue().getHeadName();
if (!StringUtils.isEmpty(headValue)) {
this.headsMap.put(ExcelUtil.convertNavToIndex(inputMap.getKey()), headValue);
}
this.fieldMap.put(ExcelUtil.convertNavToIndex(inputMap.getKey()),fieldMap.getKey());
}
}
}
}
package com.dstcar.common.utils.excel.write;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang.Validate;
/**
* Description : 写入Excel的字段及头部
*
Created By : liu wei ping
*
Creation Time : 2022年5月11日 上午11:49:08
*/
public class ExcelWriteFieldMapping {
//Map>
private Map> fieldMapping = new HashMap>();
/**
* Description : 设置映射字段及Head标题
*
Created By : [email protected]
*
Creation Time : 2018年5月11日 下午1:04:15
*
* @param columnIndex
* @param fieldName
* @return
*/
public ExcelWriteFieldAttribute put(String columnIndex, String fieldName) {
Validate.notNull(columnIndex, "索引列不能为空!");
Validate.notNull(fieldName, "字段不能为空!");
//存放字段名称及标题名称
Map attrMap = this.fieldMapping.get(columnIndex);
if ((null == attrMap) || (attrMap.size() < 1)) {
attrMap = new HashMap();
this.fieldMapping.put(columnIndex, attrMap);
}
//相信很多人看不懂这里. 我在这里稍微的解释一下
//声明后的变量在内存中的地址是不会变的.当我们初始化好一个Map时, 他在内存中的地址是已经固定的.
//当第二个Map声明出来后, 他在内存中的地址也是已经固定了.
//当我们吧第二个Map放入第一个Map的时候实际是第一个Map记录了第二个Map的内存地址
//因此我们在给第二个Map赋值的时候, 放入第一个Map里的Map是不用做任何更改的.
ExcelWriteFieldAttribute attr = new ExcelWriteFieldAttribute();
attrMap.put(fieldName, attr);
return attr;
}
public Map> getFieldMapping() {
return this.fieldMapping;
}
/**
* Description : Head名称
*
Created By : [email protected]
*
Creation Time : 2018年5月11日 上午11:48:24
*/
public class ExcelWriteFieldAttribute {
private String headName;
public String getHeadName() {
return this.headName;
}
public void setHeadName(String headName) {
this.headName = headName;
}
}
}
package com.dstcar.common.utils.excel.write;
import com.dstcar.common.utils.excel.common.ExcelException;
import com.dstcar.common.utils.excel.common.ExcelExceptionEnum;
import com.dstcar.common.utils.excel.common.ExcelType;
import com.dstcar.common.utils.excel.common.ExcelUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.Validate;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.util.StringUtils;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* Description : Excel写入
*
Created By : liu wei ping
*
Creation Time : 2022年5月11日 下午1:04:47
*/
public class ExcelWriteValue {
/**
* Description : 创建Excel并写入数据
*
Created By : [email protected]
*
Creation Time : 2018年5月11日 下午1:05:04
*
* @param excelType
* @param outputStream
* @param excelWriteConfig
* @throws IOException
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws ExcelException
*/
public static void writeExcel(ExcelType excelType, OutputStream outputStream, ExcelWriteConfig excelWriteConfig) throws ExcelException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException {
Validate.notNull(excelType, "文件类型不能为空!");
Validate.notNull(outputStream, "文件路径参数无效!");
//根据用户输入的文件类型创建不同类型的工作区
Workbook workbook = null;
if (excelType == ExcelType.XLS) {
workbook = new HSSFWorkbook();
} else {
workbook = new XSSFWorkbook();
}
//写入Excel的Sheet
writeExcelSheet(false, workbook, outputStream, excelWriteConfig);
}
/**
* Description : 根据用户提供的模板信息填写Excel数据
*
Created By : liu wei ping
*
Creation Time : 2022年5月11日 下午1:08:04
*
* @param excelTemplate
* @param outputStream
* @param excelWriteConfig
* @throws ExcelException
* @throws IOException
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public static void writeExcel(InputStream excelTemplate, OutputStream outputStream, ExcelWriteConfig excelWriteConfig) throws ExcelException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException {
Validate.notNull(excelTemplate, "模板文件无效!");
Validate.notNull(outputStream, "文件路径参数无效!");
Workbook workbook = null;
try {
//根据用户提供的模板数据创建工作空间
workbook = WorkbookFactory.create(excelTemplate);
} catch (Exception e) {
throw new ExcelException(ExcelExceptionEnum.EW00002, "使用Excel模板创建Excel工作空间失败:" + e.getMessage());
}
//写入Excel的Sheet
writeExcelSheet(true, workbook, outputStream, excelWriteConfig);
}
/**
* Description : 写入Excel的Sheet
*
Created By : [email protected]
*
Creation Time : 2018年5月11日 下午1:09:15
*
* @param useExcelTemplate
* @param workbook
* @param outputStream
* @param excelWriteConfig
* @throws IOException
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws ExcelException
*/
private static void writeExcelSheet(boolean useExcelTemplate, Workbook workbook, OutputStream outputStream, ExcelWriteConfig excelWriteConfig) throws ExcelException, IOException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Sheet sheet = null;
//如果使用的是Excel模板的话,则根据Sheet名称获取Sheet
if (useExcelTemplate) {
if (null == excelWriteConfig.getSheetIndex()) {
Validate.isTrue(StringUtils.isEmpty(excelWriteConfig.getSheetName()), "使用Excel模板时,Sheet索引或Sheet名称不能为空!");
sheet = workbook.getSheet(excelWriteConfig.getSheetName());
} else {
sheet = workbook.getSheetAt(excelWriteConfig.getSheetIndex());
}
}
//如果Sheet为空,则创建一个
if (null == sheet) {
String sheetName = StringUtils.isEmpty(excelWriteConfig.getSheetName()) ? "未命名" : excelWriteConfig.getSheetName();
sheet = workbook.createSheet(sheetName);
}
//获取开始行的索引值
Integer startRow = excelWriteConfig.getStartRow();
if (excelWriteConfig.getHeadsMap().size() > 0) {
//如果用户填入的有头部标题,则根据用户提供的索引值判断该行是否存在,如果存在则直接写入数据,不存在则创建一行, 并返回下一行的索引值
Row headerRow = sheet.getRow(excelWriteConfig.getStartRow());
if (null == headerRow) {
headerRow = sheet.createRow(excelWriteConfig.getStartRow());
}
Integer rowIndex = writeExcelHead(headerRow, excelWriteConfig.getHeadsMap());
startRow = rowIndex + 1;
}
if (!CollectionUtils.isEmpty(excelWriteConfig.getDataList())) {
//写入Excel数据
writeExcelValue(sheet, excelWriteConfig.getFieldMap(), excelWriteConfig.getDataList(), startRow);
}
//输出文件
workbook.write(outputStream);
}
/**
* Description : 写入头部标题
*
Created By : liu wei ping
*
Creation Time : 2022年5月11日 下午1:13:24
*
* @param row
* @param headerMapping
* @return
*/
private static Integer writeExcelHead(Row row, Map headerMapping) {
Cell cell = null;
//循环头部标题,并写入对应的单元格
for (Map.Entry headerValue : headerMapping.entrySet()) {
//判断获取的单元格是否存在, 如果不存在则创建一个. 存在则直接写入数据
cell = row.getCell(headerValue.getKey());
if (null == cell) {
cell = row.createCell(headerValue.getKey());
}
//单元格写入数据
writeExcelCellValue(cell, headerValue.getValue());
}
//返回当前所在的行索引
if(cell != null){
return cell.getRowIndex();
}
return 0;
}
/**
* Description : Excel数据写入
*
Created By : liu wei ping
*
Creation Time : 2022年5月11日 下午1:19:34
*
* @param sheet
* @param fieldMapping
* @param datas
* @param dataStartRow
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws ExcelException
*/
private static void writeExcelValue(Sheet sheet, Map fieldMapping, List datas, Integer dataStartRow) throws ExcelException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Validate.notNull(dataStartRow, "起始行计算错误!");
Validate.notNull(sheet, "Sheet创建错误!");
//循环写入数据
for (int i = 0; i < datas.size(); i++) {
Row valueRow = sheet.getRow(dataStartRow + i);
if (null == valueRow) {
valueRow = sheet.createRow(dataStartRow + i);
}
Object t = datas.get(i);
writeExcelRowValue(valueRow, fieldMapping, t);
}
}
/**
* Description : Excel行数据写入
*
Created By : liu wei ping
*
Creation Time : 2022年5月11日 下午1:21:32
*
* @param row
* @param fieldMapping
* @param tclass
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws ExcelException
*/
private static void writeExcelRowValue(Row row, Map fieldMapping, T tclass) throws ExcelException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Validate.notNull(row, "创建写入行出错!");
Class> clazz = tclass.getClass();
//循环写入每一列的值
for (Map.Entry fieldMap : fieldMapping.entrySet()) {
Cell cell = row.getCell(fieldMap.getKey());
if (null == cell) {
cell = row.createCell(fieldMap.getKey());
}
//利用反射获取该类的数据
PropertyDescriptor property = ExcelUtil.getPropertyDescriptor(clazz, fieldMap.getValue());
//通过反射调用该公共方法的数据并写入单元格
writeExcelCellValue(cell, property.getReadMethod().invoke(tclass));
}
}
/**
* Description : 根据数据类型写入单元格数据
*
Created By : liu wei ping
*
Creation Time : 2022年5月11日 下午1:23:27
*
* @param cell
* @param value
*/
public static void writeExcelCellValue(Cell cell, Object value) {
if (null != value) {
if (value instanceof String || value instanceof BigDecimal) {
cell.setCellValue(value.toString());
} else if (value instanceof Boolean) {
cell.setCellValue(((Boolean) value).booleanValue());
} else if ((value instanceof Double)) {
cell.setCellValue(((Double) value).doubleValue());
} else if ((value instanceof Float)) {
cell.setCellValue(((Float) value).floatValue());
} else if ((value instanceof Long)) {
cell.setCellValue(((Long) value).longValue());
} else if ((value instanceof Integer)) {
cell.setCellValue(((Integer) value).intValue());
} else if ((value instanceof Date)) {
cell.setCellValue(ExcelUtil.dateFormat.format((Date) value));
} else if ((value instanceof Short)) {
cell.setCellValue(((Short) value).shortValue());
} else if ((value instanceof Byte)) {
cell.setCellValue(((Byte) value).byteValue());
} else {
throw new ExcelException(ExcelExceptionEnum.EW00003, "写入的值类型转换错误!坐标:" + (cell.getRowIndex() + 1) + "," + ExcelUtil.convertIndexToNav(cell.getColumnIndex() + 1) + "value:" + value);
}
}
}
}
工具类使用源码:
package com.dstcar.common.utils.excel;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import org.apache.commons.lang.Validate;
import com.dstcar.common.utils.excel.common.ExcelException;
import com.dstcar.common.utils.excel.common.ExcelType;
import com.dstcar.common.utils.excel.common.ExcelUtil;
import com.dstcar.common.utils.excel.read.ExcelReadValue;
import com.dstcar.common.utils.excel.read.ExcelUserReadConfig;
import com.dstcar.common.utils.excel.write.ExcelWriteConfig;
import com.dstcar.common.utils.excel.write.ExcelWriteValue;
/**
* Description : Excel读写工具类
*
Created By : liu wei ping
*
Creation Time : 2022年5月14日 上午11:35:38
*/
public class ExcelTools {
/**
* Description : Excel读取
*
Created By : [email protected]
*
Creation Time : 2018年5月11日 下午1:35:51
*
* @param file
* @param readConfig
* @return
* @throws ExcelException
* @throws FileNotFoundException
*/
public static List readExcel(InputStream fileStream, ExcelUserReadConfig readConfig) throws Exception {
return ExcelReadValue.readExcel(fileStream, readConfig);
}
/**
* Description : Excel写入
*
Created By : [email protected]
*
Creation Time : 2018年5月11日 下午1:38:25
*
* @param excelType
* @param filePath
* @param fileName
* @param excelWriteConfig
* @throws Exception
*/
public static boolean writeExcel(ExcelType excelType, OutputStream outputStream, ExcelWriteConfig excelWriteConfig) throws Exception {
Validate.notNull(excelType, "文件类型不能为空!");
//校验配置信息
ExcelUtil.validateWriteConfig(false, excelWriteConfig);
//写入
ExcelWriteValue.writeExcel(excelType, outputStream, excelWriteConfig);
return true;
}
}
package com.dstcar.common.utils.excel;
import com.dstcar.common.utils.poi.ExcelImport;
import com.dstcar.common.utils.poi.ExcelImportFiled;
import com.dstcar.common.utils.string.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* excel导入工具 liu wei ping
*/
@Slf4j
public class ImportExcelUtil {
private final static String excel2003L = ".xls"; // 2003- 版本的excel
private final static String excel2007U = ".xlsx"; // 2007+ 版本的excel
/**
* 描述:获取IO流中的数据,组装成List>对象
*
* @param in,fileName
* @return
* @throws IOException
*/
public static List getBankListByExcel(InputStream in, String fileName, Class clazz, String[] pros,
String pattern) throws Exception {
Workbook work = getWorkbook(in, fileName);
// 创建Excel工作薄
if (null == work) {
throw new Exception("创建Excel工作薄为空!");
}
try {
return getBankListByExcel(work, clazz, pros, pattern, -1);
} finally {
work.close();
}
}
/**
* 描述:获取IO流中的数据,组装成List>对象
*
* @param in,fileName
* @return
* @throws IOException
*/
public static List getBankListByExcel(InputStream in, String fileName, Class clazz,
String pattern) throws Exception {
Workbook work = getWorkbook(in, fileName);
// 创建Excel工作薄
if (null == work) {
throw new Exception("创建Excel工作薄为空!");
}
if(clazz.getDeclaredAnnotation(ExcelImport.class) == null){
throw new RuntimeException("该对象不符合使用条件");
}
try {
Field[] fields = clazz.getDeclaredFields();
List
导入使用:
/**
* 车辆车架号数据导入,修改最近一次入库时间,拿采购入库时间
*
* @param file 文件
* @return Results
*/
@PostMapping("/importVinCodeData")
public Results importVinCodeData(@RequestBody MultipartFile file) throws Exception {
try (
InputStream in = file.getInputStream()
) {
ExcelUserReadConfig config = new ExcelUserReadConfig<>();
config.setSheetIndex(1);
config.setStartRowIndex(2);
config.setTargetClass(VinCodeDatas.class);
Map fieldMap = new HashMap<>();
// 车架号
fieldMap.put("A", "vinCode");
config.setColumn(fieldMap);
List importList = ExcelTools.readExcel(in, config);
if (org.springframework.util.CollectionUtils.isEmpty(importList)) {
return failure("导入的数据不能为空!");
}
carAttributeDataSyncImpl.updateCarAttribute(importList);
return succeed();
}
}
导出使用:
package com.dstcar.common.annotation;
import com.dstcar.common.constant.ExportConstant;
import com.dstcar.common.constant.FileTypeConstant;
import java.lang.annotation.*;
/**
* @ClassName: OSSExport
* @Description:
* @Author: liu wei ping
* @Date: 2022/5/28 21:54
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OSSExport {
/** 模块名称 **/
String moduleName() default "";
/** 附件名称 **/
String fileName();
/** 数据请求地址 **/
String dataUrl();
/** 文件类型 **/
String fileType() default FileTypeConstant.EXCEL_2007;
/** 文件类型,默认excel导出 **/
int fileClassification() default ExportConstant.FILE_CLASSIFICATION_0;
/** 分页数量 **/
int pageSize() default 0;
/** 取样字段名称 **/
String field() default "";
/** 是否动态附件名称 **/
boolean isDynamicFileName() default false;
}
/**
* 导出
*
* @param query 查询条件
* @return Results
*/
@OSSExport(moduleName = "新车辆信息",fileName = "新车辆信息",dataUrl = "/operatingNewCar/task/operatingNewCarTaskExport",field = "vinCode")
@Log(businessModel = BusinessModelEnum.VEHICLE_MODEL_EXPORT, businessType = BusinessTypeEnum.EXPORT, remark = "新车辆信息导出")
@PostMapping(value = "/operatingNewCarExport")
public Results operatingNewCarExport(@RequestBody OperatingNewCarViewListQuery query) {
return succeed();
}
/**
* 新车辆导出
*
* @param query 查询条件
* @return Results
*/
@PostMapping(value = "/task/operatingNewCarTaskExport")
public Results operatingNewCarTaskExport(@RequestBody OperatingNewCarViewListQuery query) {
List data = new ArrayList<>();
int totalPages = 0;
try {
query.setSort(false);
List orgs = getCurrentOrgCodes();
if (isNull(orgs)) {
return null;
}else if (isNull(query.getOrgCodes())){
query.setOrgCodes(orgs);
}
// 查询处理
boolean result = getOperatingNewCarQuery(query);
if(result){
return succeed(ExportResult.wrap(data, totalPages, OperatingNewCarExcel.class));
}
PageInfo pageInfo = operatingNewCarService.getOperatingNewCarListPage(query);
if (pageInfo != null){
// 为了获取车辆标签
query.setJobNum(getCurrentUser().getJobNumber());
operatingNewCarTranslateService.convertOperatingCarViewPageList(pageInfo.getList(), query);
}
if (pageInfo != null && !CollectionUtils.isEmpty((pageInfo.getList()))){
totalPages = pageInfo.getPages();
for (OperatingNewCarViewPageListDTO utl : pageInfo.getList()){
OperatingNewCarExcel uti = new OperatingNewCarExcel();
uti.settingNewCarDTO(utl);
data.add(uti);
}
}
} catch (Exception e) {
log.error("新车辆信息导出excel异常 ", e);
}
return succeed(ExportResult.wrap(data, totalPages, OperatingNewCarExcel.class));
}