自定义注解:
package com.resuper.yhexcel.util; import java.lang.annotation.*; @Documented @Inherited @Target({ ElementType.FIELD, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) public @interface ExcelI18N { String i18nkey(); }
配置文件:excel.properties
#row即表头行(起始值/最小值为1); excel.zgnyyh.row=3 excel.zgnyyh.jysj=会计日期 excel.zgnyyh.jffse=支出金额 excel.zgnyyh.dffse=收入金额 excel.zgnyyh.jyhye=账户余额 excel.zgnyyh.fkzh=对方账号 excel.zgnyyh.fkzhm=对方户名 excel.zgnyyh.zysm=交易用途
excel对应的实体:
package com.resuper.yhexcel.excelData; import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.format.DateTimeFormat; import com.resuper.yhexcel.converter.ZggsyhConverter; import com.resuper.yhexcel.converter.ZgnyyhConverter; import com.resuper.yhexcel.util.ExcelI18N; import lombok.Data; import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.math.BigDecimal; import java.util.Date; import java.util.Map; import java.util.PropertyResourceBundle; @Data public class Data { /* // 强制读取第三个 这里不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去匹配 @ExcelProperty(index = 2) private Double doubleData; // 用名字去匹配,这里需要注意,如果名字重复,会导致只有一个字段读取到数据 @ExcelProperty("字符串标题") private String string; @ExcelProperty("日期标题") private Date date; */ /** * 交易时间 */ // @ExcelProperty(value = "交易时间" , converter = ZgnyyhConverter.class) // @DateTimeFormat("yyyyMMdd HH:mm:ss") // private Date jysj; @ExcelI18N(i18nkey = "会计日期") @ExcelProperty(value = "会计日期") private String jysj; /** * 收入支出标志(1 收入,2 支出) */ // private String srzcbz; /** * 金额 */ // @ExcelProperty("支出金额") // private BigDecimal je; @ExcelI18N(i18nkey = "支出金额") @ExcelProperty(value = "支出金额") // @ExcelProperty("借方发生额(支取)") private String jffse; // private BigDecimal jffse; @ExcelI18N(i18nkey = "收入金额") @ExcelProperty(value = "收入金额") // @ExcelProperty("贷方发生额(收入)") private String dffse; // private BigDecimal dffse; /** * 交易后余额 */ @ExcelI18N(i18nkey = "账户余额") @ExcelProperty(value = "账户余额") private String jyhye; // private BigDecimal jyhye; /** * 付款账号 */ @ExcelI18N(i18nkey = "对方账号") @ExcelProperty(value = "对方账号") private String fkzh; /** * 付款账号名 */ @ExcelI18N(i18nkey = "对方户名") @ExcelProperty(value = "对方户名") private String fkzhm; /** * 摘要说明 */ @ExcelI18N(i18nkey = "交易用途") @ExcelProperty(value = "交易用途") private String zysm; /** * 用途=摘要说明 */ // @ExcelProperty(value = "交易用途") // private String yt; public synchronized void changeExcelHead() throws NoSuchFieldException, IllegalAccessException { Field[] fields = ZgnyyhData.class.getDeclaredFields(); for (int j = 0; j < fields.length; j++) { Field field = fields[j]; if (field.isAnnotationPresent(ExcelI18N.class) && field.isAnnotationPresent(ExcelProperty.class)) { //获取NcxysData字段上的ExcelProperty注解实例 ExcelI18N i18n = field.getAnnotation(ExcelI18N.class); ExcelProperty excel = field.getAnnotation(ExcelProperty.class); //获取 ExcelProperty 这个代理实例所持有的 InvocationHandler InvocationHandler i18nH = Proxy.getInvocationHandler(i18n); InvocationHandler excelH = Proxy.getInvocationHandler(excel); // 获取 AnnotationInvocationHandler 的 memberValues 字段 Field i18nF = i18nH.getClass().getDeclaredField("memberValues"); Field excelF = excelH.getClass().getDeclaredField("memberValues"); // 因为这个字段事 private final 修饰,所以要打开权限 i18nF.setAccessible(true); excelF.setAccessible(true); // 获取 memberValues Map i18nValues = (Map) i18nF.get(i18nH); Map excelValues = (Map) excelF.get(excelH); // 修改 value 属性值 Object i18nO = i18nValues.get("i18nkey"); Object excelOS = excelValues.get("value"); if (i18nO != null && excelOS != null) { String HEAD = (String) i18nO;//这里取到的就是@ExcelProperty的value值 PropertyResourceBundle res = (PropertyResourceBundle) PropertyResourceBundle.getBundle("excel"); // properties 文件名 switch (HEAD) { case "会计日期": excelValues.put("value", new String[]{res.getString("excel.zgnyyh.jysj")}); break; case "支出金额": excelValues.put("value", new String[]{res.getString("excel.zgnyyh.jffse")}); break; case "收入金额": excelValues.put("value", new String[]{res.getString("excel.zgnyyh.dffse")}); break; case "账户余额": excelValues.put("value", new String[]{res.getString("excel.zgnyyh.jyhye")}); break; case "对方账号": excelValues.put("value", new String[]{res.getString("excel.zgnyyh.fkzh")}); break; case "对方户名": excelValues.put("value", new String[]{res.getString("excel.zgnyyh.fkzhm")}); break; case "交易用途": excelValues.put("value", new String[]{res.getString("excel.zgnyyh.zysm")}); break; } } } } } }
只需要在EasyExcelFactory.read之前调用changeExcelHead()方法即可从配置文件读取excel表头:
private ResponseEntity readExcelData(MultipartFile file) { try { DataListener2<ZwWyjymx> listener = new DataListener2<ZwWyjymx>(); byte [] byteArr=file.getBytes(); PropertyResourceBundle res = (PropertyResourceBundle)PropertyResourceBundle.getBundle("excel"); Integer row = Integer.valueOf(res.getString("excel.zgnyyh.row")); new Data().changeExcelHead(); InputStream inputStream = new ByteArrayInputStream(byteArr);//MultipartFile转为InputStream // ExcelReader excelReader = EasyExcelFactory.read(inputStream, null, listener).headRowNumber(5).build(); ExcelReader excelReader = EasyExcelFactory.read(inputStream, Data.class, listener).headRowNumber(row).build(); excelReader.readAll(); List<ZwWyjymx> listMap = listener.getDatas();//取excel解析后的数据 excelReader.finish(); return ResponseEntity.ok(new Result(ResponseConstant.SUCCESS_CODE, ResponseConstant.PARSE_SUCCESS_MSG, listMap)); } catch (IOException e) { e.printStackTrace(); return ResponseEntity.ok(new Result(ResponseConstant.ERROR_CODE, ResponseConstant.SERVER_ERROR_MSG, null)); //读取文件出错的处理逻辑 } catch (NoSuchFieldException e) { e.printStackTrace(); return ResponseEntity.ok(new Result(ResponseConstant.ERROR_CODE, "配置表头读取失败", null)); } catch (IllegalAccessException e) { e.printStackTrace(); return ResponseEntity.ok(new Result(ResponseConstant.ERROR_CODE, "配置表头读取失败", null)); } }
注意:上面的配置文件虽然在idea中设置了.properties的文件格式utf-8,但当鼠标点击文件内容后在idea中其格式依然为ISO-8859-1,所以
(PropertyResourceBundle) PropertyResourceBundle.getBundle("excel").getString("excel.zgnyyh.jysj")就能取到配置文件的中文;
但当鼠标点击文件内容后发现格式已经为utf-8了,就要做如下变动
(PropertyResourceBundle) PropertyResourceBundle.getBundle("excel").getString("exce.zggsyh.jysj").getBytes("ISO-8859-1"),"UTF-8")取到的中文才不会乱码。
idea中设置文件编码格式和查看具体文件编码如下:
上面的方式读取的配置文件是在打包是会打在jar包里
*************************************************************************************************************************************************************
下面的方式读取的配置文件只需要(未打包时:放在项目根目录下面;打jar包时:放在jar包同级目录下)
放在jar包同级目录下的配置文件读取方式:
//2022年2月21日
Properties properties = new Properties();
//优先使用外部配置文件 路径为 jar包所在目录System.getProperty("user.dir")即读取到jar包同级目录或者未打包前的项目根目录
String path = System.getProperty("user.dir")+"/"+"excel.properties";
File file = new File(path);
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
properties.load(fis);
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//读取配置文件中具体参数
Integer row = Integer.valueOf(new String(properties.getProperty("excel0506.zggsyh.row").getBytes("ISO-8859-1"),"UTF-8"));