###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.2-1

图2.3.2-2

###2.3.3 图片的导出

在日常运作中不可避免的会遇到图片的导入导出,这里提供了两种类型的图片导出方式

@Excel(name = "公司LOGO", type = 2 ,width = 40 , height = 20,imageType = 1)
    private String companyLogo;
  1. 表示type =2 该字段类型为图片,imageType=1 (默认可以不填),表示从file读取,字段类型是个字符串类型
    可以用相对路径也可以用绝对路径,绝对路径优先依次获取
    @Excel(name = "公司LOGO", type = 2 ,width = 40 , height = 20,imageType = 1)
     private byte[] companyLogo;
    2.表示type =2 该字段类型为图片,imageType=2 ,表示从数据库或者已经读取完毕,字段类型是个字节数组
    直接使用
    同时,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.3 -1

###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都在这后面
作者:悟耘信息  创建时间:2020-04-08 15:59
 更新时间:2022-09-04 22:15