###2.3.1 对象定义
注解介绍了这么多,大家基本上也了解我们的注解是如何定义Excel的了吧,下面我们来跟着路飞实战吧
这天老师吧路飞叫到了办公室,让给给老师实现一个报表的需求,就是从教育平台把某个班级的人员导出来
需求是,导出我们班的所有学生的姓名,性别,出生日期,进校日期
正巧路飞刚看到Easypo,就打算用Easypoi来实现,实现方法如下:
首先定义一个我们导出的对象,为了节省篇幅,统一忽略getter,setter
public class StudentEntity implements java.io.Serializable {
/**
* id
*/
private String id;
/**
* 学生姓名
*/
@Excel(name = "学生姓名", height = 20, width = 30, isImportField = "true_st")
private String name;
/**
* 学生性别
*/
@Excel(name = "学生性别", replace = { "男_1", "女_2" }, suffix = "生", isImportField = "true_st")
private int sex;
@Excel(name = "出生日期", databaseFormat = "yyyyMMddHHmmss", format = "yyyy-MM-dd", isImportField = "true_st", width = 20)
private Date birthday;
@Excel(name = "进校日期", databaseFormat = "yyyyMMddHHmmss", format = "yyyy-MM-dd")
private Date registrationDate;
}
这里设置我们的4列分别是学生姓名,学生性别,出生日期,进校日期
其中学生姓名定义了我们的列的行高,学生性别因为我们基本上都是存在数据库都是数字所以我们转换下,两个日期我们都是进行了格式化输出了,这样我们就完成了业务对我们Excel的样式需求,后面只有把这个学生列表输出就可以了
生成Excel代码如下
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("计算机一班学生","学生"),
StudentEntity .class, list);
这样我们就得到的一个java中的Excel,然后把这个输出就得到我们的Excel了https://static.oschina.net/uploads/space/2017/0622/212811_uh7e_1157922.png
###2.3.2 集合定义
路飞很快的完成了老师的任务,花了也就是喝杯茶的时间,就交差了,但过了一会就又被老师叫去了,让他给出一个某个班级选择选择某些课的学生以及对应的老师
路飞又很快的想到了Easypoi,其中有一对多的导出,这不正是一对多的体现吗,然后他继续定义实体:
一个课程对应一个老师
一个课程对应N个学生
课程的实体
@ExcelTarget("courseEntity")
public class CourseEntity implements java.io.Serializable {
/** 主键 */
private String id;
/** 课程名称 */
@Excel(name = "课程名称", orderNum = "1", width = 25)
private String name;
/** 老师主键 */
@ExcelEntity(id = "absent")
private TeacherEntity mathTeacher;
@ExcelCollection(name = "学生", orderNum = "4")
private List<StudentEntity> students;
}
教师的实体
@ExcelTarget("teacherEntity")
public class TeacherEntity implements java.io.Serializable {
private String id;
/** name */
@Excel(name = "主讲老师_major,代课老师_absent", orderNum = "1", isImportField = "true_major,true_absent")
private String name;
这里在课程这个实体里面就完成了一堆多的导出,达到了我们基础需求,同时使用了orderNum对我们的列进行了排序,满足老师的需求,导出代码如下
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("2412312", "测试", "测试"),
CourseEntity.class, list);
这样我们就完成了老师的需求,效果如图2.3.2-1
但是课程名和代课老师没有合并,不太美观
路飞又果断给课程名称和代课老师加了needMerge = true的属性,就可以完成单元格的合并
/** 课程名称 */
@Excel(name = "课程名称", orderNum = "1", width = 25,needMerge = true)
private String name;
//--------------------------------
/** name */
@Excel(name = "主讲老师_major,代课老师_absent", orderNum = "1",needMerge = true, isImportField = "true_major,true_absent")
效果如图2.3.2-2
到这里,路飞就完美的完成了老师的任务,快乐的去交差了
###2.3.3 图片的导出
在日常运作中不可避免的会遇到图片的导入导出,这里提供了两种类型的图片导出方式
@Excel(name = "公司LOGO", type = 2 ,width = 40 , height = 20,imageType = 1)
private String companyLogo;
- 表示type =2 该字段类型为图片,imageType=1 (默认可以不填),表示从file读取,字段类型是个字符串类型
可以用相对路径也可以用绝对路径,绝对路径优先依次获取
2.表示type =2 该字段类型为图片,imageType=2 ,表示从数据库或者已经读取完毕,字段类型是个字节数组@Excel(name = "公司LOGO", type = 2 ,width = 40 , height = 20,imageType = 1) private byte[] companyLogo;
直接使用
同时,image 类型的cell最好设置好宽和高,会百分百缩放到cell那么大,不是原尺寸,这里注意下
效果如下
List<CompanyHasImgModel> list;
@Before
public void initData() {
list = new ArrayList<CompanyHasImgModel>();
list.add(new CompanyHasImgModel("百度", "imgs/company/baidu.png", "北京市海淀区西北旺东路10号院百度科技园1号楼"));
list.add(new CompanyHasImgModel("阿里巴巴", "imgs/company/ali.png", "北京市海淀区西北旺东路10号院百度科技园1号楼"));
list.add(new CompanyHasImgModel("Lemur", "imgs/company/lemur.png", "亚马逊热带雨林"));
list.add(new CompanyHasImgModel("一众", "imgs/company/one.png", "山东济宁俺家"));
}
@Test
public void exportCompanyImg() throws Exception {
File savefile = new File("D:/excel/");
if (!savefile.exists()) {
savefile.mkdirs();
}
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), CompanyHasImgModel.class, list);
FileOutputStream fos = new FileOutputStream("D:/excel/ExcelExportHasImgTest.exportCompanyImg.xls");
workbook.write(fos);
fos.close();
}
运行效果
###2.3.4 Excel导入介绍
有导出就有导入,基于注解的导入导出,配置配置上是一样的,只是方式反过来而已,比如类型的替换 导出的时候是1替换成男,2替换成女,导入的时候则反过来,男变成1 ,女变成2,时间也是类似
导出的时候date被格式化成 2017-8-25 ,导入的时候2017-8-25被格式成date类型
下面说下导入的基本代码,注解啥的都是上面讲过了,这里就不累赘了
@Test
public void test2() {
ImportParams params = new ImportParams();
params.setTitleRows(1);
params.setHeadRows(1);
long start = new Date().getTime();
List<MsgClient> list = ExcelImportUtil.importExcel(
new File(PoiPublicUtil.getWebRootPath("import/ExcelExportMsgClient.xlsx")),
MsgClient.class, params);
System.out.println(new Date().getTime() - start);
System.out.println(list.size());
System.out.println(ReflectionToStringBuilder.toString(list.get(0)));
}
基本是写法也很简单,ImportParams 参数介绍下
属性 | 类型 | 默认值 | 功能 |
---|---|---|---|
titleRows | int | 0 | 表格标题行数,默认0 |
headRows | int | 1 | 表头行数,默认1 |
startRows | int | 0 | 字段真正值和列标题之间的距离 默认0 |
keyIndex | int | 0 | 主键设置,如何这个cell没有值,就跳过 或者认为这个是list的下面的值,这一列必须有值,不然认为这列为无效数据 |
startSheetIndex | int | 0 | 开始读取的sheet位置,默认为0 |
sheetNum | int | 1 | 上传表格需要读取的sheet 数量,默认为1 |
needSave | boolean | false | 是否需要保存上传的Excel |
needVerfiy | boolean | false | 是否需要校验上传的Excel |
saveUrl | String | “upload/excelUpload” | 保存上传的Excel目录,默认是 如 TestEntity这个类保存路径就是upload/excelUpload/Test/yyyyMMddHHmss_ 保存名称上传时间_五位随机数 |
verifyHanlder | IExcelVerifyHandler | null | 校验处理接口,自定义校验 |
lastOfInvalidRow | int | 0 | 最后的无效行数,不读的行数 |
readRows | int | 0 | 手动控制读取的行数 |
importFields | String[] | null | 导入时校验数据模板,是不是正确的Excel |
keyMark | String | “:” | Key-Value 读取标记,以这个为Key,后面一个Cell 为Value,多个改为ArrayList |
readSingleCell | boolean | false | 按照Key-Value 规则读取全局扫描Excel,但是跳过List读取范围提升性能,仅仅支持titleRows + headRows + startRows 以及 lastOfInvalidRow |
dataHanlder | IExcelDataHandler | null | 数据处理接口,以此为主,replace,format都在这后面 |
更新时间:2022-09-04 22:15