在Java项目中经常会用到Excel相关的功能(导入导出),而实现方式也只有Apache的POI(繁琐且慢),最近发现了阿里开源的EasyExcel,主打简单省内存
依赖
1 2 3 4 5 6 <dependency > <groupId > com.alibaba</groupId > <artifactId > easyexcel</artifactId > <version > 2.2.3</version > </dependency >
准备
本篇将利用一个用户对象演示导入导出
准备实体类
1 2 3 4 5 6 7 8 9 10 11 12 @Data @AllArgsConstructor @NoArgsConstructor public class User implements Serializable { private static final long serialVersionUID = 7108437244995175240L ; @ExcelProperty("ID") private Long id; @ExcelProperty("姓名") private String name; @ExcelProperty("邮箱") private String email; }
写(导出)
模拟数据
1 2 3 4 5 6 7 public List<User> getData () { List<User> list = new ArrayList<>(); for (int i = 1 ; i < 21 ; i++) { list.add(new User((long )i,"王" +i,i+"@gmail.com" )); } return list; }
简单写
无特殊需求,将对象中字段全部导出
注意:无论字段是否有@ExcelProperty
注解,都会导出,默认标题为字段名;
如果需要忽略字段可以使用@ExcelIgnore
注解忽略
1 2 3 public void simpleWrite (String fileName) { EasyExcel.write(fileName, User.class).sheet("用户导出数据" ).doWrite(this .getData()); }
忽略某些字段
1 2 3 4 5 6 7 8 public void excludeWrite (String fileName,String... excludeNames) { Set<String> excludeColumnFiledNames = new HashSet<String>(Arrays.asList(excludeNames)); EasyExcel .write(fileName, User.class) .excludeColumnFiledNames(excludeColumnFiledNames) .sheet("用户导出数据-忽略" +String.join("," ,excludeColumnFiledNames)+"字段" ) .doWrite(this .getData()); }
仅导出某些字段
1 2 3 4 5 6 7 8 public void includeWrite (String fileName,String... includeNames) { Set<String> includeColumnFiledNames = new HashSet<String>(Arrays.asList(includeNames)); EasyExcel .write(fileName, User.class) .includeColumnFiledNames(includeColumnFiledNames) .sheet("用户导出数据-仅导出" +String.join("," ,includeColumnFiledNames)+"字段" ) .doWrite(this .getData()); }
格式转换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Data public class ConverterData { /** * 我想所有的 字符串起前面加上"自定义:"三个字 */ @ExcelProperty(value = "字符串标题", converter = CustomStringStringConverter.class) private String string; /** * 我想写到excel 用年月日的格式 */ @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒") @ExcelProperty("日期标题") private Date date; /** * 我想写到excel 用百分比表示 */ @NumberFormat("#.##%") @ExcelProperty(value = "数字标题") private Double doubleData; }
添加图片(不推荐使用,太慢)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Data @ContentRowHeight(100) @ColumnWidth(100 / 8) public class ImageData { private File file; private InputStream inputStream; @ExcelProperty(converter = StringImageConverter.class) private String string; private byte [] byteArray; private URL url; }
读(导入)
这里的读取使用了监听器,读取不返回数据,读取后的业务操作要放到监听器里
定义监听器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 public class UserImportListener extends AnalysisEventListener <User > { private List<User> importData = new ArrayList<>(); @Override public void invoke (User user, AnalysisContext context) { System.out.println("读取到数据" +user); importData.add(user); } @Override public void doAfterAllAnalysed (AnalysisContext context) { System.out.println("本次一共导入了" +importData.size()+"条数据" ); } }
填充
准备模板
解释
{.name} 表示循环获取对象的name字段,或者map中key为name的value
{name} 只获取一次
代码
1 2 3 4 5 public void simpleFill (String templateFileName,String fileName) { EasyExcel.write(fileName).withTemplate(templateFileName) .sheet() .doFill(new Write().getData()); }
填充后效果
附录