123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390 |
- package pub.vie.excel.read;
- import org.apache.commons.collections4.CollectionUtils;
- import org.apache.poi.ss.usermodel.*;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import pub.vie.excel.common.annotation.ExcelEntity;
- import pub.vie.excel.common.annotation.ExcelField;
- import pub.vie.excel.common.utils.CommonUtils;
- import java.io.BufferedInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.UnsupportedEncodingException;
- import java.lang.reflect.Field;
- import java.net.URL;
- import java.net.URLDecoder;
- import java.nio.charset.StandardCharsets;
- import java.text.SimpleDateFormat;
- import java.util.*;
- import static pub.vie.excel.common.utils.CommonUtils.arrayEmpty;
- import static pub.vie.excel.common.utils.CommonUtils.isBlank;
- /**
- * @Descrption :
- * @Author: zoujie
- * @Date: 2020-4-13
- */
- public class ExcelReader<T> {
- private static Logger log = LoggerFactory.getLogger(ExcelReader.class);
- private static final String DEFAULT_DATE_FORMATE = "yyyy-MM-dd";
- public static InputStream getStreamOnClassPath(String virtualPath) {
- return ExcelReader.class.getClassLoader().getResourceAsStream(virtualPath);
- }
- public static String getRealPathOnClassPath(String virtualPath) {
- URL resource = getClassLoader().getResource(virtualPath);
- if (resource == null) {
- return null;
- }
- String realPath;
- try {
- realPath = URLDecoder.decode(resource.getPath(), StandardCharsets.UTF_8.toString());
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- return null;
- }
- return realPath;
- }
- public List<T> read(InputStream inputStream, Class<T> dataClass) {
- return read(inputStream, 0, 0, -1, dataClass);
- }
- public List<T> read(InputStream inputStream,int skip, Class<T> dataClass) {
- return read(inputStream, 0, skip, -1, dataClass);
- }
- public List<T> read(InputStream inputStream, int sheetAt, int skip, int limitRow, Class<T> dataClass) {
- return baseRead(dataClass,inputStream,sheetAt,skip,limitRow,false);
- }
- public List<T> read(Class<T> dataClass) {
- ExcelReadProperties excelReadProperties = excelReadProperties(dataClass);
- if (excelReadProperties == null) {
- throw new IllegalArgumentException(dataClass.getName() + "不含有ExcelEntity注解信息,无法解析excel");
- }
- String classPathSource = excelReadProperties.classPathSource;
- if (isBlank(classPathSource)) {
- throw new IllegalArgumentException(dataClass.getName() + "该方法ExcelEntity注解配置的classPathSource不能为空");
- }
- int sheetAt = excelReadProperties.sheetAt;
- int skip = excelReadProperties.skip;
- int limitRow = excelReadProperties.limitRow;
- InputStream inputStream = getStreamOnClassPath(classPathSource);
- return baseRead(dataClass, inputStream, sheetAt, skip, limitRow,true);
- }
- public List<T> read(Class<T> dataClass, InputStream inputStream) {
- ExcelReadProperties excelReadProperties = excelReadProperties(dataClass);
- if (excelReadProperties == null) {
- throw new IllegalArgumentException(dataClass.getName() + "不含有ExcelEntity注解信息,无法解析excel");
- }
- int sheetAt = excelReadProperties.sheetAt;
- int skip = excelReadProperties.skip;
- int limitRow = excelReadProperties.limitRow;
- return baseRead(dataClass, inputStream, sheetAt, skip, limitRow,true);
- }
- private List<T> baseRead(Class<T> dataClass, InputStream inputStream, int sheetAt, int skip, int limitRow, boolean useAnnotation) {
- Workbook workbook = null;
- List<T> resList = null;
- if (inputStream == null) {
- log.error("excel inputStream 为 null");
- return null;
- }
- BufferedInputStream bufferedInputStream = convertInputStream(inputStream);
- try {
- workbook = WorkbookFactory.create(bufferedInputStream);
- Sheet sheet = workbook.getSheetAt(sheetAt);
- if (sheet == null) {
- log.info("获取工作簿sheetAt[{}]为空");
- return null;
- }
- int lastRowNum = sheet.getLastRowNum();
- if (skip > lastRowNum) {
- log.warn("sheet 总条数[{}] 跳过[{}]条不合法直接返回", lastRowNum, skip);
- return null;
- }
- resList = new ArrayList<>();
- if (skip < 0) {
- skip = 0;
- }
- //最大条数
- int end;
- if (limitRow <= 0 || skip + limitRow > lastRowNum) {
- end = lastRowNum;
- } else {
- end = skip + limitRow - 1;
- }
- for (int i = skip; i <= end; i++) {
- Row row = sheet.getRow(i);
- if (row == null) {
- break;
- }
- if (useAnnotation) {
- resList.add(handleRow(dataClass, row));
- } else {
- resList.add(handleRow(row, dataClass));
- }
- }
- log.info("总条数[{}] 成功处理了{}条excel数据,跳过了{}条excel数据", end, resList.size(), skip);
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- CommonUtils.close(workbook, bufferedInputStream);
- }
- return resList;
- }
- private static ClassLoader getClassLoader() {
- return ExcelReader.class.getClassLoader();
- }
- private T handleRow(Row row, Class<T> resDataClass) {
- T resData;
- try {
- resData = resDataClass.newInstance();
- } catch (InstantiationException | IllegalAccessException e) {
- e.printStackTrace();
- return null;
- }
- short lastCellNum = row.getLastCellNum();
- if (lastCellNum < 0) {
- throw new IllegalArgumentException("数据列小于1");
- }
- Field[] declaredFields = resDataClass.getDeclaredFields();
- if (arrayEmpty(declaredFields)) {
- throw new IllegalArgumentException(resDataClass.getName() + "未定义任何属性匹配excel文件");
- }
- int limit = declaredFields.length > lastCellNum ? lastCellNum : declaredFields.length;
- List<Cell> cellList = getCellList(row, limit);
- handleRow(Arrays.asList(declaredFields), cellList, resData, limit);
- return resData;
- }
- private void handleRow(List<Field> fieldList, List<Cell> cellList, Object object, int limit) {
- if (CollectionUtils.isEmpty(cellList) || CollectionUtils.isEmpty(fieldList)) {
- return;
- }
- if (limit > cellList.size() || limit > fieldList.size()) {
- throw new IndexOutOfBoundsException("cellList.size = " + cellList.size() + "fieldList.size=" + fieldList.size() + "max index=" + limit);
- }
- for (int i = 0; i < limit; i++) {
- Field field = fieldList.get(i);
- Cell cell = cellList.get(i);
- try {
- convertAndSet(field, object, cell);
- } catch (IllegalAccessException e) {
- log.error(e.getLocalizedMessage(), e);
- }
- }
- log.debug("解析到内容并封装为对象:[{}]", object);
- }
- private T handleRow(Class<T> dataClass, Row row) {
- Field[] declaredFields = dataClass.getDeclaredFields();
- Map<Integer, Field> colIndexFieldMap = selectFieldsToMap(declaredFields);
- if (colIndexFieldMap == null) {
- return null;
- }
- T dataObject;
- try {
- dataObject = dataClass.newInstance();
- } catch (InstantiationException | IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- short lastCellNum = row.getLastCellNum();
- for (Map.Entry entry : colIndexFieldMap.entrySet()) {
- Integer key = (Integer) entry.getKey();
- Field value = (Field) entry.getValue();
- if (key < lastCellNum) {
- try {
- convertAndSet(value, dataObject, row.getCell(key));
- } catch (IllegalAccessException e) {
- log.error(e.getLocalizedMessage(), e);
- }
- }
- }
- return dataObject;
- }
- private BufferedInputStream convertInputStream(InputStream inputStream) {
- if (!(inputStream instanceof BufferedInputStream)) {
- return new BufferedInputStream(inputStream);
- } else {
- return (BufferedInputStream) inputStream;
- }
- }
- private List<Cell> getCellList(Row row, int limit) {
- List<Cell> cellList = new ArrayList<>();
- for (int j = 0; j < limit; j++) {
- cellList.add(row.getCell(j));
- }
- return cellList;
- }
- private void convertAndSet(Field field, Object object, Cell cell) throws IllegalAccessException {
- CellType cellType = cell.getCellType();
- field.setAccessible(true);
- Class<?> type = field.getType();
- switch (cellType) {
- case _NONE:
- log.debug("row[{}] cell[{}] 单元格内容未知类型", cell.getRowIndex(), cell.getColumnIndex());
- break;
- case NUMERIC:
- Double numericCellValue = cell.getNumericCellValue();
- if (Double.TYPE.equals(type) || Double.class.equals(type)) {
- field.set(object, numericCellValue);
- } else if (Date.class.equals(type)) {
- field.set(object, new Date(numericCellValue.longValue()));
- }else if(String.class.equals(type)){
- field.set(object, String.valueOf(numericCellValue));
- }else if(Integer.TYPE.equals(type) || Integer.class.equals(type)){
- field.set(object, numericCellValue.intValue());
- }else if(Long.TYPE.equals(type) || Long.class.equals(type)){
- field.set(object, numericCellValue.longValue());
- }
- log.debug("row[{}] cell[{}] 单元格内容[{}]为数字", cell.getRowIndex(), cell.getColumnIndex(), cell.getNumericCellValue());
- break;
- case STRING:
- String stringCellValue = cell.getStringCellValue();
- if (String.class.equals(type)) {
- field.set(object, stringCellValue);
- } else if (Date.class.equals(type)) {
- SimpleDateFormat dateFormat = getDateFormat(field);
- try {
- Date parse = dateFormat.parse(stringCellValue);
- field.set(object, parse);
- } catch (Exception e) {
- log.error("row[{}] col[{}] 内容为非日期类字符串,不能按照日期格式转换为Date类型或ExcelField注解配置的时间格式有误,detail message:\n{}", cell.getRowIndex(), cell.getColumnIndex(), e.getLocalizedMessage());
- }
- } else if (Boolean.TYPE.equals(type) || Boolean.class.equals(type)) {
- try {
- boolean booleanCellValue = Boolean.valueOf(stringCellValue);
- field.set(object, booleanCellValue);
- } catch (Exception e) {
- log.error("row[{}] col[{}] 内容为非boolean类型字符串,不能转换为boolean类型,detail message:\n{}", cell.getRowIndex(), cell.getColumnIndex(), e.getLocalizedMessage());
- }
- }
- log.debug("row[{}] cell[{}] 单元格内容[{}]为字符串", cell.getRowIndex(), cell.getColumnIndex(), stringCellValue);
- break;
- case FORMULA:
- if (String.class.equals(type)) {
- String formulaCellValue = cell.getCellFormula();
- field.set(object, formulaCellValue);
- }
- log.debug("row[{}] cell[{}] 单元格内容[{}]为公式字符串", cell.getRowIndex(), cell.getColumnIndex(), cell.getCellFormula());
- break;
- case BLANK:
- log.debug("row[{}] cell[{}] 单元格内容为空", cell.getRowIndex(), cell.getColumnIndex());
- break;
- case BOOLEAN:
- if (Boolean.TYPE.equals(type) || Boolean.class.equals(type)) {
- boolean booleanCellValue = cell.getBooleanCellValue();
- field.set(object, booleanCellValue);
- }
- log.debug("row[{}] cell[{}] 单元格内容[{}]为boolean", cell.getRowIndex(), cell.getColumnIndex(), cell.getBooleanCellValue());
- break;
- case ERROR:
- log.debug("row[{}] cell[{}] 单元格内容错误", cell.getRowIndex(), cell.getColumnIndex());
- break;
- default:
- break;
- }
- }
- private SimpleDateFormat getDateFormat(Field field) {
- ExcelField[] annotationsByType = field.getAnnotationsByType(ExcelField.class);
- SimpleDateFormat format;
- if (arrayEmpty(annotationsByType)) {
- format = new SimpleDateFormat(DEFAULT_DATE_FORMATE);
- } else {
- format = new SimpleDateFormat(annotationsByType[0].dataFormat());
- }
- return format;
- }
- private ExcelReadProperties excelReadProperties(Class<T> tClass) {
- ExcelEntity[] annotationsByType = tClass.getAnnotationsByType(ExcelEntity.class);
- if (arrayEmpty(annotationsByType)) {
- return null;
- }
- ExcelEntity excelEntity = annotationsByType[0];
- ExcelReadProperties properties = new ExcelReadProperties();
- properties.classPathSource = excelEntity.classPathSource();
- properties.limitRow = excelEntity.limitRow();
- properties.sheetAt = excelEntity.sheetAt();
- properties.skip = excelEntity.skip();
- return properties;
- }
- private Map<Integer, Field> selectFieldsToMap(Field[] fields) {
- if (CommonUtils.arrayEmpty(fields)) {
- return null;
- }
- Map<Integer, Field> selectMap = new HashMap<>();
- for (Field field : fields) {
- ExcelField[] annotationsByType = field.getAnnotationsByType(ExcelField.class);
- if (CommonUtils.arrayEmpty(annotationsByType)) {
- continue;
- }
- int i = annotationsByType[0].colIndex();
- if (i >= 0) {
- selectMap.put(annotationsByType[0].colIndex(), field);
- }
- }
- return selectMap;
- }
- private class ExcelReadProperties {
- public String classPathSource;
- public int sheetAt;
- public int skip;
- public int limitRow;
- }
- }
|