在项目开发中,开发人员在编写代码过程中或多或少都要涉及到直接将固定格式的数据文件内容导入到系统中,例如将一个存放员工信息的Excel文件导入到系统中。以员工信息导入为例,大部分程序员的做法步骤如下:
- 在员工管理页面提供导入功能,让用户可以上传员工Excel文件;
- 服务器端采用POI或其它工具读取Excel工作表中每行数据;
- 创建一个User对象,读取每行单元格内容,验证单元格数据是否合法,如果合法调用User对象对应setter方法进行赋值;
- 保存User对象,继续处理下一行数据。
一般项目都会涉及到至少一个以上的导入,每个导入功能都要重复上述步骤,特别是在对第三步中读取转换时,涉及的代码会更多、更为复杂。为了减少开发人员重复编写数据导入代码的负担,增强导入代码可读性,作者结合本人经验开发了一套excel-data-transformer工具用于简化在步骤2、3中的代码编写复杂度。
excel-data-transformer是什么?
- 遵循Apache 2.0协议;
- 非常方便的将Excel、CSV及其它文件中的数据直接转换为指定对象;
- 直接在转换类的setter上增加验证注解,无需对字符、数字等硬编码验证;
- 采用流式方式处理,支持对大文件的解析、转换;
- 扩展方便,可以轻松的增加自定义的文件解析类;
excel-data-transformer如何简化代码?
- 实现了对Excel和CSV格式文件的解析,无需编写文件读取代码;
- 采用注解方式实现对解析数据的合法性认证,自动将文件表头列名映射到类下;
excel-data-transformer如何使用?
- 在转换类的setter方法上增加@ExcelColumn(指定对应转换文件的列名)、@NumberDesc(数字转换、验证)、@StringDesc(字符串转换、验证)、@DateDesc(日期转换、验证)、@CustomDesc(自定义验证器)等注解;其中@ExcelColumn是必须要增加的;
public class User {
private String name;
private int age;
private Date birthday;
private String email;
public String getName() {
return name;
}
@ExcelColumn(name = "姓名", required = true, trim = true)
@CustomDesc(handler = "nameHandler")
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
@ExcelColumn(name = "年龄", trim = true)
@NumberDesc(min = "0", max = "100")
public void setAge(int age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
@ExcelColumn(name = "出生日期", trim = true)
@DateDesc(pattern = "yyyy年MM月dd日")
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getEmail() {
return email;
}
@ExcelColumn(name = "Email", trim = true)
@StringDesc(pattern = StringRegex.EMAIL)
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + ", birthday=" + birthday + ", email=" + email + "]";
}
}
- 如果有自定义转换类,需要将自定义转换类放到Map中,且key对应的值和@CustomDesc注解中的handler一致。如果没有可忽略此步。
/**
* 员工姓名自定义转换器
*
* @author wangguobin
*
*/
public class NameHandler extends CustomTypeHandler<String> {
public NameHandler() {
}
public NameHandler(Method method) {
super(method);
}
@Override
protected String transform(Object value) {
return "Ext" + value;
}
}
- 对数据进行转换。
public class DataTransformerTest {
@Test
public void transform() {
try (InputStream in = new FileInputStream(new File("/home/wangguobin/test/用户.xlsx"))) {
// Excel数据转换
TableFileReader excelReader = new POIXLSXExcelReader(in);
transform(excelReader);
System.out.println("----------------------------");
// CSV数据转换
TableFileReader csvReader = new CSVFileReader("/home/wangguobin/test/用户.csv");
transform(csvReader);
} catch (Exception e) {
e.printStackTrace();
}
}
private void transform(TableFileReader excelReader)
throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException,
NotFoundColumnException, IllegalParameterNumException, NotSupportTypeException, TransformerException {
Map<String, CustomTypeHandler<?>> mapTypeHandler = new HashMap<String, CustomTypeHandler<?>>();
// 将自定义转换器放到map中,key值必须和@CustomDesc(handler = "nameHandler")中的handler值一致
mapTypeHandler.put("nameHandler", new NameHandler());
// 逐行读取文件数据,并将数据转换为指定的类
DataTransformer.transform(excelReader, User.class, new TransformHandler<User>() {
@Override
public void success(User rst) {
// 处理转换成功的后续处理代码...
}
/**
* @param pos 行号
* @param rowData 错误行原始数据
* @param errorMsg 错误消息
*/
@Override
public void error(int pos, Object[] rowData, String errorMsg) {
// 转换失败的后续代码...
}
}, mapTypeHandler);
}
}
通过上述简单操作即可快速、方便的将文件数据转换为对象,excel-data-transformer下载地址:
https://github.com/binxigogo/excel-data-transformer
欢迎大家下载并提出指导意见。