package com.dstcar.common.utils.excel.common;import org.springframework.util.StringUtils;/*** Description : Excel异常类* <br/>Created By : liu wei ping * <br/>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错误枚举类* <br>Created By : liu wei ping * <br>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 : 错误代码转错误信息* <br/>Created By : liu wei ping  * <br/>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文件类型枚举类* <br/>Created By : liu wei ping * <br/>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辅助通用类* <br/>Created By : liu wei ping * <br/>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导航转索引* <br/>Created By : xiaok0928@hotmail.com * <br/>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索引转导航* <br/>Created By : xiaok0928@hotmail.com * <br/>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用户输入的配置文件转程序可读配置文件* <br/>Created By : liu wei ping  * <br/>Creation Time : 2022年5月10日 下午6:57:18 * * @param userConfig* @param workbook* @return*/public static <T> ExcelReadConfig<T> converConfig(ExcelUserReadConfig<T> userConfig, Workbook workbook) {ExcelReadConfig<T> config = new ExcelReadConfig<T>();//校验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<Integer, String> columnIndex = new HashMap<Integer, String>();for (Map.Entry<String, String> 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* <br/>Created By : liu wei ping * <br/>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写入配置文件的有效性* <br/>Created By : liu wei ping  * <br/>Creation Time : 2022年5月10日 下午7:17:21 * * @param useExcelTemplate* @param excelWriteConfig*/public static <T> void validateWriteConfig(boolean useExcelTemplate, ExcelWriteConfig<T> 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 : 反射赋值属性* <br/>Created By : xiaok0928@hotmail.com * <br/>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 : 基础校验* <br/>Created By : liu wei ping * <br/>Creation Time : 2022年5月10日 下午6:11:20*/
public class Validate {/*** Description : 校验:数据不为空* <br/>Created By : xiaok0928@hotmail.com * <br/>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 : 校验表达式为真* <br/>Created By : xiaok0928@hotmail.com * <br/>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的相关配置* <br/>Created By : liu wei ping * <br/>Creation Time : 2022年5月11日 上午9:29:54*/
public class ExcelReadConfig<T> {//读取的Sheet索引private Integer sheetIndex;//开始行索引private Integer startRowIndex;//结束行索引private Integer endRowIndex;//固定选择读取的行private Integer[] readRowIndexArray;//列索引:Excel列转换后的索引, 属性名private Map<Integer, String> columnIndex;//返回的实体类private Class<T> 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<Integer, String> getColumnIndex() {return this.columnIndex;}public void setColumnIndex(Map<Integer, String> columnIndex) {this.columnIndex = columnIndex;}public Class<T> getTargetClass() {return this.targetClass;}public void setTargetClass(Class<T> 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相关方法* <br/>Created By : liu wei ping * <br/>Creation Time : 2022年5月11日 上午9:32:37*/
public class ExcelReadValue {/*** Description : 读取Excel* <br/>Created By : xiaok0928@hotmail.com * <br/>Creation Time : 2018年5月11日 上午9:34:12 * * @param file* @param readConfig* @return* @throws ExcelException */public static <T> List<T> readExcel(InputStream file, ExcelUserReadConfig<T> readConfig) throws ExcelException {//判断文件是否存在Validate.isTrue(null == file, "未读取到文件!");//获取工作区Workbook workbook = getExcelWorkBook(file);//转换用户输入的ConfigExcelReadConfig<T> excelConfig = ExcelUtil.converConfig(readConfig, workbook);//读取SheetSheet sheet = getExcelSheet(workbook, excelConfig.getSheetIndex().intValue());//返回实体return readExcelValue(sheet, excelConfig);}/*** Description : 获取Excel的工作区* <br/>Created By : liu wei ping * <br/>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* <br/>Created By : liu wei ping * <br/>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的数据* <br/>Created By : liu wei ping * <br/>Creation Time : 2022年5月11日 上午9:37:28 * * @param sheet* @param excelConfig* @return* @throws ExcelException */private static <T> List<T> readExcelValue(Sheet sheet, ExcelReadConfig<T> excelConfig) throws ExcelException {List<T> dataList = new ArrayList<T>();Row row = null;//判断起始行及结束行是否有值if (null != excelConfig.getStartRowIndex() && null != excelConfig.getEndRowIndex()) {// 循环要读取的行for (int i = excelConfig.getStartRowIndex(); i <= excelConfig.getEndRowIndex(); i++) {Map<String, Cell> fieldMapping = new HashMap<String, Cell>();//获取行row = sheet.getRow(i);if (null != row) {//循环每一列for (Map.Entry<Integer, String> 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<String, Cell> fieldMapping = new HashMap<String, Cell>();//获取行row = sheet.getRow(index);if (null != row) {//循环每一列的值for (Map.Entry<Integer, String> 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的值* <br/>Created By : liu wei ping * <br/>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 : 将数据转换为实体对象数据* <br/>Created By : liu wei ping * <br/>Creation Time : 2022年5月11日 上午11:09:54 * * @param targetClazz* @param excelValue* @return* @throws ExcelException*/private static <T> T convertJavaBeanValue(Class<T> targetClazz, Map<String, Cell> excelValue) throws ExcelException {T tClass = null;try {tClass = targetClazz.newInstance();} catch (Exception e) {throw new ExcelException(ExcelExceptionEnum.ER00006, "目标对象反射实例化过程出错!");}//循环映射该实体对象的数据for (Map.Entry<String, Cell> 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 : 判断数据是否有效* 既判断不为空的对象其属性也不包含不为空的数据* <br/>Created By :  liu wei ping * <br/>Creation Time : 2022年5月11日 下午3:23:46 * * @param valueClass* @param excelValue* @return* @throws ExcelException*/private static <T> boolean valueIsEffect(T valueClass, Map<String, Cell> excelValue) throws ExcelException {//获取该数据实体类的类Class<?> clazz = valueClass.getClass();//标识数据是否有效, 有效的依据为该实体中只要存在一个不为空的属性既有效boolean isEffect = false;//循环要判断的属性for (Map.Entry<String, Cell> 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用户输入的相关配置<br/>* 优先级顺序如下:<br/>* SheetIndex > SheetName<br/>* endRowIndex > readRowNumber && readRowIndexArray<br/>* null == endRowIndex -> [readRowNumber > readRowIndexArray]<br/>* null == endRowIndex && null == readRowNumber && null == readRowIndexArray -> [startRowIndex = 0 && endRowIndex = data.lastRow]<br/>* * <br/>Created By : liu wei ping  * <br/>Creation Time : 2022年5月11日 上午9:53:11*/
public class ExcelUserReadConfig<T> {//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<String, String> columnIndex;//选择接收返回数据的实体类private Class<T> 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<String, String> getColumnIndex() {return this.columnIndex;}public void setColumn(Map<String, String> columnIndex) {this.columnIndex = columnIndex;}public Class<T> getTargetClass() {return this.targetClass;}public void setTargetClass(Class<T> 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 写入配置* <br/>Created By : liu wei ping  * <br/>Creation Time : 2022年5月11日 上午11:21:24*/
public class ExcelWriteConfig<T> {//Sheet索引private Integer sheetIndex;//Sheet名称private String sheetName;//开始行private Integer startRow;//头部:转换后的索引, 标题名称private Map<Integer, String> headsMap = new HashMap<Integer, String>();//字段:转换后的索引, 字段名private Map<Integer, String> fieldMap = new HashMap<Integer, String>();//数据private List<T> 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<Integer, String> getHeadsMap() {return this.headsMap;}public Map<Integer, String> getFieldMap() {return this.fieldMap;}public List<T> getDataList() {return this.dataList;}public void setDataList(List<T> dataList) {this.dataList = dataList;}public void setExcelWriteFieldMapping(ExcelWriteFieldMapping excelWriteFieldMapping) {Validate.isTrue(null == excelWriteFieldMapping, "字段映射不可为空!");Map<String, Map<String, ExcelWriteFieldAttribute>> userInputFieldMapping = excelWriteFieldMapping.getFieldMapping();//解析Head及列for (Map.Entry<String, Map<String, ExcelWriteFieldAttribute>> inputMap : userInputFieldMapping.entrySet()) {Map<String, ExcelWriteFieldAttribute> fieldMapping = inputMap.getValue();for (Map.Entry<String, ExcelWriteFieldAttribute> 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的字段及头部* <br/>Created By : liu wei ping * <br/>Creation Time : 2022年5月11日 上午11:49:08*/
public class ExcelWriteFieldMapping {//Map<Excel列导航, Map<字段名称, 标题名称>>private Map<String, Map<String, ExcelWriteFieldAttribute>> fieldMapping = new HashMap<String, Map<String, ExcelWriteFieldAttribute>>();/*** Description : 设置映射字段及Head标题* <br/>Created By : xiaok0928@hotmail.com * <br/>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<String, ExcelWriteFieldAttribute> attrMap = this.fieldMapping.get(columnIndex);if ((null == attrMap) || (attrMap.size() < 1)) {attrMap = new HashMap<String, ExcelWriteFieldAttribute>();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<String, Map<String, ExcelWriteFieldAttribute>> getFieldMapping() {return this.fieldMapping;}/*** Description : Head名称* <br/>Created By : xiaok0928@hotmail.com * <br/>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写入* <br/>Created By : liu wei ping  * <br/>Creation Time : 2022年5月11日 下午1:04:47*/
public class ExcelWriteValue {/*** Description : 创建Excel并写入数据* <br/>Created By : xiaok0928@hotmail.com * <br/>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 <T> void writeExcel(ExcelType excelType, OutputStream outputStream, ExcelWriteConfig<T> 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的SheetwriteExcelSheet(false, workbook, outputStream, excelWriteConfig);}/*** Description : 根据用户提供的模板信息填写Excel数据* <br/>Created By : liu wei ping  * <br/>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 <T> void writeExcel(InputStream excelTemplate, OutputStream outputStream, ExcelWriteConfig<T> 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的SheetwriteExcelSheet(true, workbook, outputStream, excelWriteConfig);}/*** Description : 写入Excel的Sheet* <br/>Created By : xiaok0928@hotmail.com * <br/>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 <T> void writeExcelSheet(boolean useExcelTemplate, Workbook workbook, OutputStream outputStream, ExcelWriteConfig<T> excelWriteConfig) throws ExcelException, IOException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {Sheet sheet = null;//如果使用的是Excel模板的话,则根据Sheet名称获取Sheetif (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 : 写入头部标题* <br/>Created By : liu wei ping * <br/>Creation Time : 2022年5月11日 下午1:13:24 * * @param row* @param headerMapping* @return*/private static Integer writeExcelHead(Row row, Map<Integer, String> headerMapping) {Cell cell = null;//循环头部标题,并写入对应的单元格for (Map.Entry<Integer, String> 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数据写入* <br/>Created By : liu wei ping  * <br/>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 <T> void writeExcelValue(Sheet sheet, Map<Integer, String> fieldMapping, List<T> 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行数据写入* <br/>Created By : liu wei ping  * <br/>Creation Time : 2022年5月11日 下午1:21:32 * * @param row* @param fieldMapping* @param tclass* @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException * @throws ExcelException*/private static <T> void writeExcelRowValue(Row row, Map<Integer, String> fieldMapping, T tclass) throws ExcelException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {Validate.notNull(row, "创建写入行出错!");Class<?> clazz = tclass.getClass();//循环写入每一列的值for (Map.Entry<Integer, String> 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 : 根据数据类型写入单元格数据* <br/>Created By : liu wei ping  * <br/>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读写工具类* <br>Created By : liu wei ping * <br>Creation Time : 2022年5月14日 上午11:35:38*/
public class ExcelTools {/*** Description : Excel读取* <br/>Created By : xiaok0928@hotmail.com * <br/>Creation Time : 2018年5月11日 下午1:35:51 * * @param file* @param readConfig* @return* @throws ExcelException * @throws FileNotFoundException */public static <T> List<T> readExcel(InputStream fileStream, ExcelUserReadConfig<T> readConfig) throws Exception {return ExcelReadValue.readExcel(fileStream, readConfig);}/*** Description : Excel写入* <br/>Created By : xiaok0928@hotmail.com * <br/>Creation Time : 2018年5月11日 下午1:38:25 * * @param excelType* @param filePath* @param fileName* @param excelWriteConfig* @throws Exception */public static <T> boolean writeExcel(ExcelType excelType, OutputStream outputStream, ExcelWriteConfig<T> 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- 版本的excelprivate final static String excel2007U = ".xlsx"; // 2007+ 版本的excel/*** 描述:获取IO流中的数据,组装成List<List<Object>>对象** @param in,fileName* @return* @throws IOException*/public static <T> List<T> getBankListByExcel(InputStream in, String fileName, Class<T> 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<List<Object>>对象** @param in,fileName* @return* @throws IOException*/public static <T> List<T> getBankListByExcel(InputStream in, String fileName, Class<T> 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<Map<String,Object>> list = new ArrayList<>();for (Field field : fields) {ExcelImportFiled excelImportFiled = field.getAnnotation(ExcelImportFiled.class);if(excelImportFiled != null){Map<String,Object> map = new HashMap<>();map.put("index",excelImportFiled.cellIndex());map.put("value",field.getName());list.add(map);}}if(CollectionUtils.isEmpty(list)){throw new RuntimeException("该对象不符合使用条件");}String pros[] = list.stream().sorted(Comparator.comparing(x->Integer.parseInt(x.get("index").toString()))).map(x->x.get("value").toString()).toArray(String[]::new);return getBankListByExcel(work ,clazz, pros,pattern, -1);} finally {work.close();}}/*** 描述:获取IO流中的数据,组装成List<List<Object>>对象** @param work* @param clazz* @param pros* @param pattern* @param sheetNum 传入的是-1 则表明获取excel表中的所有sheet,其他则获取对应的第几个sheet* @param <T>* @return* @throws Exception*/public static <T> List<T> getBankListByExcel(Workbook work, Class<T> clazz, String[] pros, String pattern,int sheetNum) throws Exception {List<T> list = null;// 创建Excel工作薄if (null == work) {throw new Exception("创建Excel工作薄为空!");}// 获取实体类型T entity = clazz.newInstance();Map<String, String> entityType = getEntityType(entity);Sheet sheet = null;Row row = null;Cell cell = null;list = new ArrayList<>();// 遍历Excel中所有的sheetfor (int i = 0; i < work.getNumberOfSheets(); i++) {if (sheetNum != -1 && sheetNum != i) {continue;}sheet = work.getSheetAt(i);if (sheet == null) {continue;}// 遍历当前sheet中的所有行for (int j = sheet.getFirstRowNum(); j <= sheet.getLastRowNum(); j++) {if (j == 0) {++j;}
//                log.info("excel数据-->开始解析第 【 " + j + " 】 行数据,当前第 【 " + (i + 1) + " 】 个sheet");row = sheet.getRow(j);/*if (row == null || row.getFirstCellNum() == j) {continue;}*/if (row == null) {continue;}// 遍历所有的列entity = clazz.newInstance();for (int y = 0; y < pros.length; y++) {cell = row.getCell(y);if (cell != null && !StringUtil.isEmpty(String.valueOf(getCellValue(cell)))) {// "yyyy-MM-dd"
//                        log.info("excel数据-->开始解析第 【 " + j + " 】 行,第 【" + (y + 1) + "列数据,当前第 【 " + (i + 1) + " 】 个sheet,解析数据行值为-->" + getCellValue(cell));Object value = castPropType(getCellValue(cell), entityType.get(pros[y]), pattern);BeanUtils.setProperty(entity, pros[y], value);}}list.add(entity);}}return list;}/*** 描述:根据文件后缀,自适应上传文件的版本** @param inStr,fileName* @return* @throws Exception*/public static Workbook getWorkbook(InputStream inStr, String fileName) throws Exception {Workbook wb = null;String fileType = fileName.substring(fileName.lastIndexOf("."));if (excel2003L.equals(fileType)) {// 2003-wb = new HSSFWorkbook(inStr);} else if (excel2007U.equals(fileType)) {// 2007+wb = new XSSFWorkbook(inStr);} else {throw new Exception("解析的文件格式有误!");}return wb;}public static void closeInputStream( Workbook work,InputStream in) {try {if (work != null) {work.close();}if (in != null) {in.close();}} catch (IOException e) {log.error("关闭导入流异常",e);}}private static Object castPropType(Object object, String type, String pattern) throws ParseException {if (type != null) {switch (type) {case "class java.util.Date":DateFormat format = new SimpleDateFormat(pattern);return format.parse(String.valueOf(object));case "class java.lang.Double"://Double格式化DecimalFormat df2 = new DecimalFormat("0.00");return df2.parse(object.toString());}}return object;}/*** 描述:对表格中数值进行格式化** @param cell* @return*/private static Object getCellValue(Cell cell) {Object value = null;DecimalFormat df = new DecimalFormat("0"); // 格式化number String字符SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 日期格式化DecimalFormat df2 = new DecimalFormat("0.00"); // 格式化数字switch (cell.getCellType()) {case STRING:value = cell.getRichStringCellValue().getString().trim();break;case NUMERIC:if (StringUtils.contains(cell.getCellStyle().getDataFormatString(), "yy")) {value = sdf.format(cell.getDateCellValue());}else if (covertStr(cell)) {cell.setCellType(CellType.STRING);value = cell.getStringCellValue();}else {value = cell.getNumericCellValue();}break;case BOOLEAN:value = cell.getBooleanCellValue();break;case BLANK:value = "";break;default:break;}return value;}private static Boolean covertStr(Cell cell) {Object numericCellValue = cell.getNumericCellValue();if (numericCellValue != null && StringUtil.isNotNullorEmpty(numericCellValue.toString())) {Pattern pattern = Pattern.compile("^[+-]?((\\d+\\.?\\d*)|(\\.\\d+))[Ee][+-]?\\d+$");Matcher match = pattern.matcher(numericCellValue.toString());if (match.matches()) {return true;}}return false;}private static <T> Map<String, String> getEntityType(T t) {Map<String, String> map = new HashMap<>();Field[] declaredFields = t.getClass().getDeclaredFields();Arrays.stream(declaredFields).forEach(e -> {if (e.getType().toString().contains("$")) {try {T entity = (T) e.getType().newInstance();Map<String, String> entityMap = getEntityType(entity);entityMap.forEach((key, value) -> map.put(e.getName() + "." + key, value));} catch (InstantiationException ex) {ex.printStackTrace();} catch (IllegalAccessException ex) {ex.printStackTrace();}} else {map.put(e.getName(), e.getType().toString());}});return map;}
}

导入使用:

  /*** 车辆车架号数据导入,修改最近一次入库时间,拿采购入库时间** @param file 文件* @return Results*/@PostMapping("/importVinCodeData")public Results importVinCodeData(@RequestBody MultipartFile file) throws  Exception {try (InputStream in = file.getInputStream()) {ExcelUserReadConfig<VinCodeDatas> config = new ExcelUserReadConfig<>();config.setSheetIndex(1);config.setStartRowIndex(2);config.setTargetClass(VinCodeDatas.class);Map<String, String> fieldMap = new HashMap<>();// 车架号fieldMap.put("A", "vinCode");config.setColumn(fieldMap);List<VinCodeDatas> 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<ExcelVO> data = new ArrayList<>();int totalPages = 0;try {query.setSort(false);List<String> 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<OperatingNewCarViewPageListDTO> 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));}

Excel导入导出源码分析相关推荐

  1. 若依管理系统源码分析-导出Excel时怎样通过注解中readConverterExp实现格式化导出列的显示格式(0和1格式化为是否)

    场景 在数据库中存储某些个是否的字段时,有时会使用tinint进行存储 这样会在实体类中生成布尔类型的变量 private Boolean sfkt; 有时也会用int进行存储是否 那么在实体类中就可 ...

  2. 【飞秋】ASP.NET 之 常用类、方法的超级总结,并包含动态的EXCEL导入导出功能,奉上类库源码

    最近闲了,花点几天时间将项目中常用的一些类.方法做了一下总结,希望对大家有用. 实用类:UtilityClass 包含如下方法 判断对象是否为空或NULL,如果是空或NULL返回true,否则返回fa ...

  3. 导出目录结构_Selenium Webdriver 3.X源码分析之核心目录结构

    > 这是Selenium3.X源码分析系列第3篇 在看Selenium 3.X核心目录结构前,我们先看一个基础的Selenium使用实例 请注意上述代码中,匡红的导入部分,为什么可以从selen ...

  4. seo必备网站分析工具,关键词百度搜索结果查询导出源码

    seo必备网站分析工具,关键词百度搜索结果查询导出源码 两个简单的版本,关于百度搜索结果的采集抓取,可以获取到竞争对手的网站,加以分析和研究,只需输入关键词和搜索页码,即可完成对于竞争对手的获取和研究 ...

  5. Openssl ECC椭圆曲线算法 - 密钥/签名/验签/加密/解密/SM2密文 - 序列化反序列化导出导入 - C源码

    . . . . 废话不多说,本代码继承自另外一位讲解Openssl ECC椭圆曲线算法大佬的源代码:https://blog.csdn.net/scuyxi/article/details/59182 ...

  6. SpringBoot-web开发(一): 静态资源的导入(源码分析)

    目录 方式一:通过WebJars 1. 什么是webjars? 2. webjars的使用 3. webjars结构 4. 解析源码 5. 测试访问 方式二:放入静态资源目录 1. 源码分析 2. 测 ...

  7. Python3.5源码分析-sys模块及site模块导入

    Python3源码分析 本文环境python3.5.2. 参考书籍<<Python源码剖析>> python官网 Python3的sys模块初始化 根据分析完成builtins ...

  8. Dubbo 源码分析 - 服务导出

    1.服务导出过程 本篇文章,我们来研究一下 Dubbo 导出服务的过程.Dubbo 服务导出过程始于 Spring 容器发布刷新事件,Dubbo 在接收到事件后,会立即执行服务导出逻辑.整个逻辑大致可 ...

  9. java导入工程tomcat_Tomcat源码分析【一】版本选择与工程导入

    项目中有直接使用外置Tomcat的,也有springboot内置Tomcat的,虽然一直在使用,也会简单的配置与调优,但是从来没有系统的分析过Tomcat. 版本选择 因为我使用的Test工程中spr ...

最新文章

  1. linux下查看内存使用情况
  2. 不用写一行代码,这款 高颜值 可视化神器,值得try一try!
  3. 使用Xamarin开发手机聊天程序 -- 基础篇(大量图文讲解 step by step,附源码下载)
  4. python输出文本 去掉引号_Python可以在文本文件中读取时从字符串中删除双引号吗?...
  5. Springmvc架构详解
  6. Virtual Box 与海马玩 安卓模拟器
  7. oracle 树形结构表,树结构表递归查询在ORACLE和MSSQL中的实现方法
  8. CoreData 增删改查
  9. TensorFlow/Python的一个范例代码及阅读说明
  10. js数组去重(for循环去遍历源数组)
  11. sql的casewhen
  12. 网络直播对现代社会的影响
  13. 辞旧迎新又一年(18年年终总结)
  14. 车载etc充值显示服务器连接失败,为什么有的etc会显示余额,有的没有
  15. 怎么把链接生成二维码?怎样制作一个链接二维码?
  16. iPhone手机轻松获取UDID的六种方式
  17. android之银联支付,android端银联支付
  18. 相机系统综述 —— ISP
  19. azure 配置vpn_ASP.NET和Azure中配置中的私有配置数据和连接字符串的最佳做法
  20. 相关-21. 卷积的示意图(普通卷积,多通道卷积等)及Featur Map可视化

热门文章

  1. c语言 学生注册,c语言学生管理系统之用户注册
  2. android:performClick的用法——自定义View增加点击事件更配performClick噢!
  3. 在 JavaScript 中三个点‘...‘的意思
  4. 例题:计算运费。c#语言基础,比较简单。看代码输入格式和方法。同样方法可以做一个 出租车打车的程序...
  5. Java虚拟机 - 双亲委派机制
  6. 沐雪微信|asp.net 微信源码 多用户平台 c#整套源码
  7. 链接器 --- Linker
  8. SWH-1T显微硬度计及图像测量系统
  9. 微信系列研究之-手把手教你脱掉微信的外衣
  10. linux系统日常管理