首先可能会有一个Model,与数据库的一张表对应:
package com.bob.config.mvc.model;
import java.io.Serializable;
/**
* Excel映射的Model
*
* @author dell-7359
* @create 2017-10-19 19:46
*/
public class ExcelModel implements Serializable {
private static final long serialVersionUID = -422292418932719315L;
private Integer id;
private String userName;
private String password;
private Integer age;
private String telephone;
private String adress;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public String getAdress() {
return adress;
}
public void setAdress(String adress) {
this.adress = adress;
}
}
但是我们的映射Model可能不是表对应的model,可能是属性字段不足,也不应该在表对应的model上修改东西,所以我们自定义了一个扩展类,继承自ExcelModel,有一些额外的属性:
package com.bob.config.mvc.model;
import java.util.Date;
import com.bob.config.mvc.excelmapping.ExcelColumn;
import com.bob.config.mvc.excelmapping.ExcelColumn.Column;
import com.bob.config.mvc.excelmapping.ExcelMapping;
import com.bob.config.mvc.excelmapping.PropertyInitializer;
/**
* Excel映射的Model扩展类
*
* @author dell-7359
* @create 2017-10-19 19:55
*/
@ExcelMapping(titleRow = 2, dataRow = 3, sheetAt = 0)
public class ExcelModelExtends extends ExcelModel implements PropertyInitializer<ExcelModelExtends> {
private static final long serialVersionUID = 445175433808433505L;
@ExcelColumn(value = Column.G,last = true)
private String description;
private Date parseTime;
@ExcelColumn(value = Column.A,key = true)
public Integer getId() {
return super.getId();
}
@ExcelColumn(value = Column.B)
public String getUserName() {
return super.getUserName();
}
@ExcelColumn(value = Column.C)
public String getPassword() {
return super.getPassword();
}
@ExcelColumn(value = Column.D)
public Integer getAge() {
return super.getAge();
}
@ExcelColumn(value = Column.E)
public String getTelephone() {
return super.getTelephone();
}
@ExcelColumn(value = Column.F)
public String getAdress() {
return super.getAdress();
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getParseTime() {
return parseTime;
}
public void setParseTime(Date parseTime) {
this.parseTime = parseTime;
}
/**初始化Model对象
* @return
*/
@Override
public ExcelModelExtends initProperties() {
ExcelModelExtends modelExtends = new ExcelModelExtends();
modelExtends.setParseTime(new Date());
return modelExtends;
}
}
我们在ExcelModelExtends 类上添加了一个注解ExcelMapping,指明Excel内标题行,数据起始行,以及数据页码。ExcelModelExtends 实现了一个属性初始化接口,每解析一行数据时通过此接口方法得到ExcelModelExtends 实例,同时做一些初始化工作。我们再ExcelModelExtends 重写自ExcelModel的getter方法上添加了ExcelColumn注解,表名这个字段对应Excel第几列,同时是否是数据行与行之间唯一性的标识,可以有多个key字段,当每个key字段均相等时行数据重复,重复校验失败。
假设Excel数据如下:
解析测试代码如下:
package com.bob.test.concrete.excelmapping;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import com.bob.config.mvc.excelmapping.Excel;
import com.bob.config.mvc.excelmapping.ExcelInstance;
import com.bob.config.mvc.excelmapping.ExcelMappingProcessor;
import com.bob.config.mvc.model.ExcelModelExtends;
import org.junit.Test;
/**
* Excel解析工具类测试
*
* @author
* @create 2017-09-26 16:56
*/
public class ExcelMappingTest {
private ExcelMappingProcessor<ExcelModelExtends> processor;
@Test
public void testParsing() throws Exception {
Excel excel = new Excel("C:\\Users\\dell-7359\\Desktop\\Excel原始数据.xlsx");
processor = new ExcelMappingProcessor<ExcelModelExtends>(excel,ExcelModelExtends.class);
boolean success = processor.process();
Collection<ExcelInstance<ExcelModelExtends>> results = processor.getCorrectResult();
System.out.println(results.size());
if(!success){
File errorFile = new File("C:\\Users\\dell-7359\\Desktop\\Excel原始数据_错误回写.xlsx");
excel.write(errorFile);
}
}
}
运行测试用例,数据正常时能得到解析成功的对象集合。
当单元格数据类型与字段类型不匹配时:
运行单元测试,重新打开上传的Excel文件:
解析框架会一次性解析完所有的Excel行,同时将所有的类型不匹配单元格上添加批注,批注上指明错误信息,同时对key=true的字段对应的单元格的标题行(显示第3行,序号为2)上插入批注。
当修改了单元格数据时,不需要删除批注新,可以直接上传,解析框架在解析之间会抹去错误批注,不会影响错误标识的第二次添加。
当两行的数据的key=true字段值均相应相等时:
运行解析测试代码:
默认第一行数据时正确行,key值相等第二行为重复行,在重复行的最后一个单元格之后添加错误信息,标识醒目背景色,修改完错误单元格时删除错误信息列。重新上传。
解析框架还支持对表单校验的结果BindingResul,将其错误新写入对应的单元格中。
正常流程是用户上传了Excel之后,解析,如果有错误信息。将错误信息写入Excel的二进制流中,同时将二进制数据缓存起来,当用户看到解析异常时,下载标识了错误信息的excel,将缓存的二进制信息重新生成一个Excel供用户下载,此Excel中已经包含了相应的错误信息。