java excel 导入demo_Java基于注解和反射导入导出Excel

1. 构建项目

使用Spring Boot快速构建一个Web工程,并导入与操作Excel相关的POI包以及一些常用的工具类包,pom文件中添加如下一些依赖:

org.apache.poi

poi

3.9

org.apache.poi

poi-ooxml

3.9

org.apache.commons

commons-lang3

3.3.2

com.google.collections

google-collections

1.0

2. 自定义Excel注解

使用注解的形式,自定义一些与操作Excel相关的基本信息,如生成Excel模板时,需要有哪些字段名、字段标题、字段之间的排序、字段中内容的位置、对齐方式等信息。然后通过在JavaBean中的需要的字段对应的getter方法上添加这些注解,就可以将其标记为Excel相关的字段。自定义注解内容主要如下(为了节省篇幅,一下代码中的注解已删除,详细代码可以看下载附件)

@Target({ElementType.FIELD,ElementType.TYPE,ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

public @interface ExcelField {

String value() default "";

String title();

int type() default 0;

int align() default 0;

int sort() default 0;

String dictType() default "";

Class> fieldType() default Class.class;

int[] groups() default {};

}

3. 通过反射创建Excel模板

使用反射的方式获取类的信息、类中方法、属性,为了创建一个可供用户填写的Excel模板,我们需要在模板中定义系统需要收集的数据字段,即在JavaBean中,通过注解定义的相关字段。伪代码及关键代码如下:

public ExportExcel(String title, Class> cls, int type, int... groups){

// Get annotation field

Field[] fs = cls.getDeclaredFields();

for (Field f : fs){

//获取字段上加的@Excel注解

ExcelField ef = f.getAnnotation(ExcelField.class);

if (ef != null && (ef.type()==0 || ef.type()==type)){

//根据字段注解中配置的groups进行分组

//....

}else{

//若无group属性,则直接将字段和对应的注解加入到一个全局的注解链表中,用于之后进行统一的排序

annotationList.add(new Object[]{ef, f});

}

}

}

// Get annotation method

Method[] ms = cls.getDeclaredMethods();

for (Method m : ms){

//获取方法上的注解

ExcelField ef = m.getAnnotation(ExcelField.class);

if (ef != null && (ef.type()==0 || ef.type()==type)){

//操作同对字段的操作

}else{

annotationList.add(new Object[]{ef, m});

}

}

}

// 对字段进行排序

Collections.sort(annotationList, new Comparator() {

//排序规则

});

// Initialize

List headerList = Lists.newArrayList();

for (Object[] os : annotationList){

//获取注解title属性值

String t = ((ExcelField)os[0]).title();

//将字段名称保存在一个list中,交给初始化方法使用

headerList.add(t);

}

//初始化操作,创建Excel,设置文件名称,表格标题,表头内容及单元格的格式等信息

initialize(title, headerList);

}

4. 导入Excel文件

导入Excel文件,意味着需要将一个根据我们生成模板填好的Excel文件导入到系统中。在这个过程中,需要使用一个接口去接收文件,并对文件进行解析。在Excel文件中,每一行都对应着我们定义的一个实体对象,所以解析之后,我们得到的是一个存放着多个对象的List。

在解析文件的过程中,首先需要对文件格式校验,保证是一个有效的Excel文件,然后循环读取每一行的数据,并将其赋值给对象。

5. 导出Excel文件

导出Excel的原理同导出模板一样,只是需要将数据填充到Excel文件中。填充数据过程中,还是需要通过@Excel注解将JavaBean中的字段找出,并将值设置到单元格中

6. 测试

1. 定义实体类并为其中字段方法添加@Excel注解

public class User {

private String userName;

private String nickName;

private Integer age;

private Date birth;

@NotNull(message = "User Name 不能为空")

@ExcelField(title="User Name", align=2, sort=1)

public String getUserName() {

return userName;

}

public void setUserName(String userName) {

this.userName = userName;

}

@ExcelField(title="Nick Name", align=2, sort=2)

public String getNickName() {

return nickName;

}

public void setNickName(String nickName) {

this.nickName = nickName;

}

@ExcelField(title="Age", align=2, sort=3)

public Integer getAge() {

return age;

}

public void setAge(Integer age) {

this.age = age;

}

@JsonFormat(pattern = "mm/dd/YYYY")

@NotNull(message="Birth Day不能为空")

@ExcelField(title="Birth Day", align=2, sort=4)

public Date getBirth() {

return birth;

}

public void setBirth(Date birth) {

this.birth = birth;

}

}

2. 定义接口方法

1. 下载输入数据的模板

@RequestMapping("import/template")

public void importFileTemplate(HttpServletResponse response){

try {

//定义文件名称

String fileName = "User_Data_import_template.xlsx";

List list = Lists.newArrayList();

new ExportExcel("User Data", User.class, 1).setDataList(list).write(response, fileName).dispose();

} catch (IOException e) {

e.printStackTrace();

}

}

2. 导入Excel文件到系统

@RequestMapping(value = "import",method = RequestMethod.POST)

public void importFile(MultipartFile multipartFile){

try {

int successNum = 0;

int failureNum = 0;

StringBuilder failureMsg = new StringBuilder();

ImportExcel ei = new ImportExcel(multipartFile, 1, 0);

List list = ei.getDataList(User.class);

for (User user : list){

try{

//to do: 保存/处理数据

//userService.save(user);

logger.info(user.toString());

successNum++;

}catch(ConstraintViolationException ex){

failureNum++;

}catch (Exception ex) {

failureNum++;

}

}

if (failureNum>0){

failureMsg.insert(0, ", Failures: "+failureNum);

}

logger.info("Had Operation "+successNum+" Data;"+" "+"Failure "+failureNum);

} catch (Exception e) {

logger.error("导入失败",e);

}

}

3. 导出Excel文件

@RequestMapping("export")

public void export(HttpServletResponse response){

try {

String fileName = "User Data"+ DateUtils.getDate("yyyyMMddHHmmss")+".xlsx";

List users=new ArrayList<>();

User user1=new User();

user1.setUserName("小明");

user1.setNickName("猪小明");

user1.setAge(20);

user1.setBirth(DateUtils.parseDate("1992-10-10"));

users.add(user1);

User user2=new User();

user2.setUserName("小红");

user2.setNickName("小小红");

user2.setAge(18);

user2.setBirth(DateUtils.parseDate("1998-11-09"));

users.add(user2);

new ExportExcel("Test Over View Define", User.class,2).setDataList(users).write(response, fileName).dispose();

} catch (Exception e) {

}

}

3. 演示

端口号可以自己通过在application.properties文件中,添加server.port=8000进行定义

ba4bc20530d489f0fc4a85ce22236fe2.png

e5edc03feb50250bef98ecdab9970c5c.png

编辑Excel文件,并通过接口测试工具Postman访问接口localhost:8000/user/import:

e7248650006dedf92ca6d5df4dd20695.png

接口测试工具中,上传文件,并访问:

153182bec6a47a237c81a1f70c3a7738.png

8e1eb686da97f084520f2f2dd60a949a.png

上传之后,通过日志输出文件解析的结果:

2017-11-24 19:56:15.186 INFO 37428 --- [nio-8000-exec-5] com.shexd.Controller.UserController : User{userName='小明', nickName='猪小明', age=18, birth=1992-10-09}

2017-11-24 19:56:15.187 INFO 37428 --- [nio-8000-exec-5] com.shexd.Controller.UserController : User{userName='蘑菇头', nickName='小蘑菇', age=21, birth=1996-09-25}

2017-11-24 19:56:15.187 INFO 37428 --- [nio-8000-exec-5] com.shexd.Controller.UserController : Had Operation 2 Data; Failure 0

4140f0eb8fbd197ff6ce5df12122e167.png

7. 项目目录结构

c9ba3e9fe48704444bbb1c7ea2f30855.png

8. 小结

本文简单介绍了利用Java注解和反射对Excel进行操作的基本原理,并实例进行详细说明。

Java基于注解和反射导入导出Excel

注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值