JAVA读取Excel文件
工具类
/** * 同步无模型读取(默认读取sheet0,从第2行开始读) * * @param filePath 文件路径 * @return List<Map < Integer, String>> */ public static List<Map<Integer, String>> syncRead(String filePath) { return EasyExcelFactory.read(filePath).sheet().doReadSync(); } /** * 同步无模型读取(默认表头占一行,从第2行开始读) * * @param filePath 文件路径 * @param sheetNo sheet页号,从0开始 * @return List<Map < Integer, String>> */ public static List<Map<Integer, String>> syncRead(String filePath, Integer sheetNo) { return EasyExcelFactory.read(filePath).sheet(sheetNo).doReadSync(); } /** * 同步无模型读取(指定sheet和表头占的行数) * * @param inputStream 输入流 * @param sheetNo sheet页号,从0开始 * @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0) * @return List<Map < colNum, cellValue>> */ public static List<Map<Integer, String>> syncRead(InputStream inputStream, Integer sheetNo, Integer headRowNum) { return EasyExcelFactory.read(inputStream).sheet(sheetNo).headRowNumber(headRowNum).doReadSync(); } /** * 同步无模型读取(指定sheet和表头占的行数) * * @param file 文件 * @param sheetNo sheet页号,从0开始 * @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0) * @return List<Map < colNum, cellValue>> */ public static List<Map<Integer, String>> syncRead(File file, Integer sheetNo, Integer headRowNum) { return EasyExcelFactory.read(file).sheet(sheetNo).headRowNumber(headRowNum).doReadSync(); } /** * 同步无模型读取(指定sheet和表头占的行数) * * @param filePath 文件路径 * @param sheetNo sheet页号,从0开始 * @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0) * @return List<Map < colNum, cellValue>> */ public static List<Map<Integer, String>> syncRead(String filePath, Integer sheetNo, Integer headRowNum) { return EasyExcelFactory.read(filePath).sheet(sheetNo).headRowNumber(headRowNum).doReadSync(); } /** * 同步按模型读取(默认读取sheet0,从第2行开始读) * * @param filePath 文件路径 * @param clazz 模型的类类型(excel数据会按该类型转换成对象) * @return List<T> */ public static List<T> syncReadModel(String filePath, Class<?> clazz) { return EasyExcelFactory.read(filePath).sheet().head(clazz).doReadSync(); } /** * 同步按模型读取(默认表头占一行,从第2行开始读) * * @param filePath 文件路径 * @param clazz 模型的类类型(excel数据会按该类型转换成对象) * @param sheetNo sheet页号,从0开始 * @return List<T> */ public static List<T> syncReadModel(String filePath, Class<?> clazz, Integer sheetNo) { return EasyExcelFactory.read(filePath).sheet(sheetNo).head(clazz).doReadSync(); } /** * 同步按模型读取(指定sheet和表头占的行数) * * @param inputStream 输入流 * @param clazz 模型的类类型(excel数据会按该类型转换成对象) * @param sheetNo sheet页号,从0开始 * @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0) * @return List<T> */ public static List<T> syncReadModel(InputStream inputStream, Class<?> clazz, Integer sheetNo, Integer headRowNum) { return EasyExcelFactory.read(inputStream).sheet(sheetNo).headRowNumber(headRowNum).head(clazz).doReadSync(); } /** * 同步按模型读取(指定sheet和表头占的行数) * * @param file 文件 * @param clazz 模型的类类型(excel数据会按该类型转换成对象) * @param sheetNo sheet页号,从0开始 * @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0) * @return List<T> */ public static List<T> syncReadModel(File file, Class<?> clazz, Integer sheetNo, Integer headRowNum) { return EasyExcelFactory.read(file).sheet(sheetNo).headRowNumber(headRowNum).head(clazz).doReadSync(); } /** * 同步按模型读取(指定sheet和表头占的行数) * * @param filePath 文件路径 * @param clazz 模型的类类型(excel数据会按该类型转换成对象) * @param sheetNo sheet页号,从0开始 * @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0) * @return List<T> */ public static List<T> syncReadModel(String filePath, Class<?> clazz, Integer sheetNo, Integer headRowNum) { return EasyExcelFactory.read(filePath).sheet(sheetNo).headRowNumber(headRowNum).head(clazz).doReadSync(); } /** * 异步按模型读取(默认表头占一行,从第2行开始读) */ /** * 异步按模型读取 * * @param file 文件 * @param excelListener 监听器,在监听器中可以处理行数据LinkedHashMap,表头数据,异常处理等 * @param clazz 模型的类类型(excel数据会按该类型转换成对象) * @param sheetNo sheet页号,从0开始 * @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0) */ public static void asyncReadModel(File file, AnalysisEventListener<T> excelListener, Class<?> clazz, Integer sheetNo, Integer headRowNum) { EasyExcelFactory.read(file, clazz, excelListener).sheet(sheetNo).headRowNumber(headRowNum).doRead(); } /** * 异步按模型读取 文件路径 */ /** * 异步按模型读取 输入流 * */ /** * 无模板写文件 文件路径 */ /** * 无模板写文件 指定sheet名称 */ /** * 根据excel模板文件写入文件 */ /** * 根据excel模板文件写入文件 * */ /** * 按模板写文件 */ /** * 按模板写文件 * */ /** * 按模板写文件(包含某些字段) */ /** * 按模板写文件(排除某些字段) */ /** * 多个sheet页的数据链式写入 */ /** * 多个sheet页的数据链式写入(失败了会返回一个有部分数据的Excel) */ /** * 同步按模型读,设置监听(指定sheet和表头占的行数) */
监听器
public class ExcelListener<T> extends AnalysisEventListener<T> { // 保存读取的对象 private final List<T> rows = new ArrayList<>(); // 日志输出 private final Logger logger = LoggerFactory.getLogger(getClass()); private String sheetName = ""; // 获取对应类 private Class headClazz; // 此map用来存储错误信息 private final List<String> errorMessage = new ArrayList<>(); public ExcelListener(Class headClazz) { this.headClazz = headClazz; } /** * @param headClazz * @Description 通过class获取类字段信息 */ public Map<Integer, String> getIndexNameMap(Class headClazz) throws NoSuchFieldException { Map<Integer, String> result = new HashMap<>(); Field field; Field[] fields = headClazz.getDeclaredFields(); //获取类中所有的属性 for (int i = 0; i < fields.length; i++) { field = headClazz.getDeclaredField(fields[i].getName()); // logger.info(String.valueOf(field)); field.setAccessible(true); ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);//获取根据注解的方式获取ExcelProperty修饰的字段 if (excelProperty != null) { int index = excelProperty.index(); //索引值 String[] values = excelProperty.value(); //字段值 StringBuilder value = new StringBuilder(); for (String v : values) { value.append(v); } result.put(index, value.toString()); } } return result; } @Override public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) { logger.info("解析到一条头数据:{}", JSON.toJSONString(headMap)); Map<Integer, String> head = new HashMap<>(); try { head = getIndexNameMap(headClazz); //通过class获取到使用@ExcelProperty注解配置的字段 logger.info(String.valueOf(head)); } catch (NoSuchFieldException e) { e.printStackTrace(); } Set<Integer> keySet = head.keySet(); //解析到的excel表头和实体配置的进行比对 for (Integer key : keySet) { if (StringUtils.isEmpty(headMap.get(key))) { errorMessage.add("您上传的文件第" + (key + 1) + "列表头为空,请安照模板检查后重新上传"); } if (!headMap.get(key).equals(head.get(key))) { errorMessage.add("您上传的文件第" + (key + 1) + "列表头与模板表头不一致,请检查后重新上传"); } } } @Override public void invoke(T t, AnalysisContext analysisContext) { rows.add(t); } @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { // 当前sheet的名称 编码获取类似 sheetName = analysisContext.readSheetHolder().getSheetName(); logger.info(sheetName); logger.info("read {} rows", rows.size()); } @Override public void onException(Exception exception, AnalysisContext context) { logger.error("解析失败,但是继续解析下一行:{}", exception.getMessage()); if (exception instanceof ExcelDataConvertException) { ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException) exception; errorMessage.add("第" + excelDataConvertException.getRowIndex() + "行,第" + (excelDataConvertException.getColumnIndex() + 1) + "列数据类型解析异常,数据为:" + excelDataConvertException.getCellData()); logger.error("第{}行,第{}列数据类型解析异常,数据为:{}", excelDataConvertException.getRowIndex(), excelDataConvertException.getColumnIndex() + 1, excelDataConvertException.getCellData()); } } public List<T> getRows() { return rows; } public Class getHeadClazz() { return headClazz; } public List<String> getErrorMessage() { return errorMessage; } public String getSheetName() { return sheetName; } }
具体使用
public void upload(@RequestParam("file") MultipartFile file) throws Exception { File newFile = FileUtil.multipartFileToFile(file); //创建监听器 ExcelListener listener = new ExcelListener(BoxAndUnitDTO.class); //调用EasyExcelUtils EasyExcelUtils.asyncReadModel(newFile, listener, BoxAndUnitDTO.class, 0, 1); //获取解决出的错误信息 List<String> errorMessage = listener.getErrorMessage(); System.out.println("errorMessage = " + errorMessage); //获取监听器读到的数据 List<String> rows = listener.getRows(); for (Object o : rows) { System.out.println(o.toString()); } FileUtil.deleteTempFile(newFile); }

浙公网安备 33010602011771号