相关推荐recommended
【业务功能篇55】Springboot+easyPOI 导入导出
作者:mmseoamin日期:2024-01-21

Apache POI是Apache软件基金会的开源项目,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。

Apache POI 代码实现复杂,学习成本较高。

Easypoi 功能如同名字easy,主打的功能就是容易,让一个没见接触过poi的人员 就可以方便的写出Excel导出,Excel模板导出,Excel导入,Word模板导出,通过简单的注解和模板 语言(熟悉的表达式语法),完成以前复杂的写法

EasyPOI官网:EasyPoi教程_V1.0

环境搭建

1)搭建springboot项目

2)导入依赖

        
        
            cn.afterturn
            easypoi-spring-boot-starter
            4.2.0
        

 EasyPOI相关注解

easypoi 起因就是Excel的导入导出,最初的模板是实体和Excel的对应,model--row,filed--col 这样利用注解我们可以和容易做到excel到导入导出 经过一段时间发展,现在注解有5个类分别是

  • @Excel 作用到filed上面,是对Excel一列的一个描述
  • @ExcelCollection 表示一个集合,主要针对一对多的导出,比如一个老师对应多个科目,科目就可以用集合表示
  • @ExcelEntity 表示一个继续深入导出的实体,但他没有太多的实际意义,只是告诉系统这个对象里面同样有导出的字段
  • @ExcelIgnore 和名字一样表示这个字段被忽略跳过这个导导出
  • @ExcelTarget 这个是作用于最外层的对象,描述这个对象的id,以便支持一个对象可以针对不同导出做出不同处理

    @ExcelTarget

    1.说明

    - 用在实体类上标识是一个可以通过EasyPOI导入导出的实体类

    - 相关属性:

    value:  [String][定义id唯一标识,不能重复]    `常用`

    height: [Double][定义单元格高度]

    fontSize:[short ][定义单元格字体大小]

    2.使用

    @ExcelTarget("users")
    public class User implements Serializable {
     //..... 省略属性 相关GET,SET方法
    }

     

    @Excel

    # 1.说明

    - 用在filed(属性)上面,是对Excel一列的一个描述

    - 常用属性: 

    name :  [String][生成Excel表格中列名]

    needMerge: [boolean][是否需要纵向合并单元格(用于含有list中,单个的单元格,合并list创建的多个row)]

    orderNum :       [String][指定生成Excel中列的顺序,按照数字自然顺序排序]

    savePath :       [String][指定导入Excel中图片的保存路径]

    type :       [String][导出类型 1 是文本 2 是图片,3 是函数,10 是数字 默认是文本]

    width    : [Double][指定导出Excel时列的宽度]

    isImportField:   [boolean][是否是导入字段,如果没有说明是错误的Excel]

    exportFormat:    [String][导出Excel的时间格式]

    importFormat:    [String][导入Excel的时间格式]

    format :       [String][相当于同时设置了exportFormat和importFormat]

    imageType:   [int   ][导出类型 1 从file读取 2 是从数据库中读取 默认是文件 同样导入也是一样的]

    suffix :       [String][文字后缀,如% 90 变成90%]

    2.使用

    public class User implements Serializable {
        @Excel(name="编号",orderNum="1",replace = {"xxx_1","nnn_2"})
        private String id;
        
        @Excel(name="姓名",orderNum="2")
        private String name;
        @Excel(name="年龄",orderNum="4",suffix = " $")
        private Integer age;
        @Excel(name="生日",orderNum = "3",width = 20.0,exportFormat = "yyyy年MM月dd日")
        private Date bir;
      //...省略GET、SET方法
    }

     

    @ExcelEntity

    1.说明

    - 标记是不是导出excel 标记为实体类,一遍是一个内部属性类,标记是否继续穿透

    - 常用属性:

    name: [String][定义唯一标识]

    2.使用

    @ExcelTarget("users")
    public class User implements Serializable {
    //... 省略GET SET和其他属性
        @ExcelEntity(name="身份信息")
        private Card card;
    }
    @ExcelTarget("card")
    public class Card  implements Serializable {
        @Excel(name="身份证号",orderNum = "6")
        private String id;
        @Excel(name="家庭住址",orderNum = "7")
        private String address;
    }

    @ExcelCollection

    1.说明

    - 一对多的集合注解,用以标记集合是否被数据以及集合的整体排序

    - 常用属性:

    name: [String][定义集合列名]

    orderNum:[int][用来指定导出excel集合内列的顺序]

    type:     [Class\][用来指定导出是创建对象类型] 

     2.使用

    @ExcelTarget("users")
    public class User implements Serializable {    
      //....省略GET SET其他属性
    @ExcelCollection(name="订单",orderNum = "5")
        private List orders;
    }
    @ExcelTarget("orders")
    public class Order implements Serializable {
    //....省略GET SET方法
        @Excel(name = "订单编号")
        private String id;
        @Excel(name = "订单名称")
        private String name;
    }

    @ExcelIgnore 

    .说明

    • 用在属性上,导出Excel时忽略这个属性

       

      导出Excel

      导出基本数据 

      注意:导出Excel的对象必须实现对象序列化接口

      1)定义对象

      @Data
      @ExcelTarget("users")
      public class User implements Serializable {
          @ExcelIgnore
          @Excel(name="编号",orderNum="1")
          private String id;
          @Excel(name="姓名",orderNum="2")
          private String name;
          @Excel(name="年龄",orderNum="3",suffix = " &")
          private Integer age;
          @Excel(name="生日",orderNum="4",width = 35.0,format = "yyyy-MM-dd HH:mm:ss")
          private Date birthday;
          @Excel(name ="状态" ,orderNum="5",replace = {"激活_1","未激活_0"})
          private String status;
      }
      

       

      2)定义测试数据

          public List getUsers(){
              List users = new ArrayList<>();
              for (int i = 0; i < 10; i++) {
                  User user = new User();
                  user.setId(String.valueOf(i));
                  user.setName("向阳");
                  user.setAge(16+i);
                  user.setBirthday(new Date());
                  user.setStatus(String.valueOf(i%2));
                  users.add(user);
              }
              return users;
          }

      3)导出Excel

          @Test
          public void testExport() throws Exception {
              //1.配置对象 2.导出类型 3.导出数据集合
              Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("用户列表", "测试"), User.class, getUsers());
              FileOutputStream outputStream = new FileOutputStream("C:\Users\86187\Desktop\user.xls");
              workbook.write(outputStream);
              outputStream.close();
              workbook.close();
          }

      4)查看Excel

      【业务功能篇55】Springboot+easyPOI 导入导出,第1张

       

      导出List集合

      1)说明

      - 往往有时候导出的对象中含有数组或者集合,需要导出这样的数据可以直接使用@Excel进行导出

       2)使用
      @Data
      @ExcelTarget("users")
      public class User implements Serializable {
          @Excel(name = "爱好",width=20.0,orderNum = "6")
          private List hobby;
      }

      【业务功能篇55】Springboot+easyPOI 导入导出,第2张

      3) 改换格式

      //    @Excel(name = "爱好",width=20.0,orderNum = "6")
          @ExcelIgnore
          private List hobby;
          @Excel(name = "爱好",width=20.0,orderNum = "6")
          private String hobbystr;
          //自定义格式
          public String getHobbystr() {
              StringBuilder sb = new StringBuilder();
              this.hobby.forEach(s -> sb.append(s).append("、") );
              return sb.toString();
          }

       【业务功能篇55】Springboot+easyPOI 导入导出,第3张

      导出对象中含有的对象

      • - 导出对象中含有对象的Excel
        @Data
        @ExcelTarget("users")
        public class User implements Serializable {
            //定义对象
            @ExcelEntity(name="card")
            private Card card;
        }
        @ExcelTarget("card")
        public class Card  implements Serializable {
            @Excel(name="身份证号",orderNum = "6")
            private String id;
            @Excel(name="家庭住址",orderNum = "7")
            private String address;
        }
        •  为导出对象赋值
          public List getUsers(){
              List users = new ArrayList<>();
              for (int i = 0; i < 10; i++) {
                  User user = new User();
                  user.setId(String.valueOf(i));
                  user.setName("向阳");
                  user.setAge(16+i);
                  user.setBirthday(new Date());
                  user.setStatus(String.valueOf(i%2));
                  user.setHobby(Arrays.asList("抽烟","喝酒","烫头"));
                  user.setCard(new Card("11000103422323212342","北京市朝阳区"));
                  users.add(user);
              }
              return users;
          }

           

          • 导出Excel
            //1.配置对象 2.导出类型 3.导出数据集合
            Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("用户列表", "测试"), User.class, getUsers());
            FileOutputStream outputStream = new FileOutputStream("C:\Users\86187\Desktop\user.xls");
            workbook.write(outputStream);
            outputStream.close();
            workbook.close();

             【业务功能篇55】Springboot+easyPOI 导入导出,第4张

             

             

            导出图片

            1. - 往往随着业务不断变化,可能需要在导出excel时将图片信息也一并导出,如商品图标,用户头像信息等数据,这个时候easypoi该如何处理呢?
            @ExcelTarget("users")
            public class User implements Serializable {
                
                @Excel(name = "头像信息",type = 2,orderNum = "0",width = 12,height = 12)
                private String photo;//定义头像 直接写指定图片路径
            }

            准备图片放入指定路径中,并在测试数据中进行赋值 

            public List getUsers(){
                List users = new ArrayList<>();
                for (int i = 0; i < 10; i++) {
                    User user = new User();
                    user.setId(String.valueOf(i));
                    user.setName("向阳");
                    user.setAge(16+i);
                    user.setBirthday(new Date());
                    user.setStatus(String.valueOf(i%2));
                    user.setHobby(Arrays.asList("抽烟","喝酒","烫头"));
                    user.setCard(new Card("11000103422323212342","北京市朝阳区"));
                    user.setPhoto("C:\Users\86187\Desktop\桌面.png");
                    users.add(user);
                }
                return users;
            }

             

             导出Excel查看结果【业务功能篇55】Springboot+easyPOI 导入导出,第5张

             

            导入Excel 

            导入基本数据

            1) 准备导入的目标Excel

            2) 定义导出数据基本对象

            @Data
            @ExcelTarget("emps")
            public class Emp  implements Serializable {
                @Excel(name="编号")
                private String id;
                @Excel(name="姓名")
                private  String  name;
                @Excel(name="年龄")
                private Integer age;
                @Excel(name="生日",format = "yyyy-MM-dd HH:mm:ss")
                private Date bir;
                @Excel(name="状态",replace = {"激活_1","未激活_0"})
                private String status;
                @Excel(name="头像",type = 2,savePath = "I:\resources\static")
                private String photo;
            }

            3) 导入excel中数据 

                 @Test
                public void testImportExcel()throws Exception{
                    ImportParams params = new ImportParams();
                    params.setTitleRows(1); //标题列占几行
                    params.setHeadRows(1); //列名占几行
                    params.setNeedSave(true);
                    params.setSaveUrl("I:\\msb_hejiayun\\easypoi_boot\\src\\main\\resources\\static");
              
                    List list = ExcelImportUtil.importExcel(new FileInputStream("C:\\Users\\86187\\Desktop\\emp.xls"), Emp.class, params);
                    list.forEach(System.out::println);
                }

            多Sheet页导入导出 

            - 读取指定的sheet

            比如要读取上传得第二个sheet 那么需要把startSheetIndex = 1 就可以了

            - 读取几个sheet 

            比如读取前2个sheet,那么 sheetNum=2 就可以了

            - 读取第二个到第五个sheet

            设置 startSheetIndex = 1 然后sheetNum = 4

            - 读取全部的sheet

            sheetNum  设置大点就可以了

            - 判断一个Excel是不是合法的Excel 

            importFields 设置下值,就是表示表头必须至少包含的字段,如果缺一个就是不合法的excel,不导入

             

             

            准备表格,创建对应实体

            【业务功能篇55】Springboot+easyPOI 导入导出,第6张

            @Data
            @ExcelTarget("loginUser")
            public class LoginUser implements Serializable {
                @Excel(name = "用户ID",orderNum = "1")
                private String id;
                @Excel(name = "昵称",orderNum = "2")
                private String nickname;
                @Excel(name = "密码",orderNum = "3")
                private String password;
                @Excel(name="注册时间",orderNum="4",format = "yyyy-MM-dd HH:mm:ss")
                private Date createTime;
                @Excel(name ="状态" ,orderNum="5",replace = {"VIP_1","普通用户_0"})
                private String status;
            }

             

            @Data
            @ExcelTarget("loginUrl")
            public class LoginUrl implements Serializable {
                @Excel(name = "用户ID",orderNum = "1")
                private String userId;
                @Excel(name = "请求类型",orderNum = "2")
                private String type;
                @Excel(name = "访问地址",orderNum = "3")
                private String url;
            }

              

            多sheet导入方法

                /**
                 * 功能描述:根据接收的Excel文件来导入多个sheet,根据索引可返回一个集合
                 * @param filePath   导入文件路径
                 * @param sheetIndex  导入sheet索引
                 * @param titleRows  表标题的行数
                 * @param headerRows 表头行数
                 * @param pojoClass  Excel实体类
                 * @return
                 */
                public static  List importMultiSheet(String filePath,int sheetIndex,Integer titleRows, Integer headerRows, Class pojoClass) {
                    // 根据file得到Workbook,主要是要根据这个对象获取,传过来的excel有几个sheet页
                    ImportParams params = new ImportParams();
                    // 第几个sheet页
                    params.setStartSheetIndex(sheetIndex);
                    params.setTitleRows(titleRows);
                    params.setHeadRows(headerRows);
                    
                    //是否保存本次上传的excel
                    params.setNeedSave(false);
                    //表示表头必须包含的字段,不包含 就报错.
                    params.setImportFields(new String[]{"用户ID"});
                    List list = null;
                    try {
                        list = ExcelImportUtil.importExcel(new FileInputStream(filePath), pojoClass, params);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return list;
                }
                //测试多sheet导入
                @Test
                public void testImportMultiSheet() throws Exception {
                    String excelPath = "C:\\Users\\86187\\Desktop\\login.xls";
                    List loginUserList = this.importMultiSheet(excelPath, 0, 1, 1, LoginUser.class);
                    loginUserList.forEach(System.out::println);
                    List loginUrlList = this.importMultiSheet(excelPath, 1, 1, 1, LoginUrl.class);
                    loginUrlList.forEach(System.out::println);
                }

             

            多sheet导出方法

               public void exportMultiSheet(Object... objects) throws Exception {
                    //创建参数对象,用于设定Excel的sheet页内容等信息
                    ExportParams loginUserExportParams = new ExportParams();
                    //设置sheet的名称
                    loginUserExportParams.setSheetName("登录用户");
                    loginUserExportParams.setTitle("登录用户列表");
                    //使用map创建sheet1
                    HashMap sheet1Map = new HashMap<>();
                    //设置title
                    sheet1Map.put("title",loginUserExportParams);
                    //设置导出的实体类型
                    sheet1Map.put("entity",LoginUser.class);
                    //sheet中要填充的数据
                    sheet1Map.put("data",objects[0]);
                    ///==================================
                    //创建参数对象,用于设定Excel的sheet页内容等信息
                    ExportParams loginUrlExportParams = new ExportParams();
                    //设置sheet的名称
                    loginUrlExportParams.setSheetName("URL路径");
                    loginUrlExportParams.setTitle("URL路径");
                    //使用map创建sheet2
                    HashMap sheet2Map = new HashMap<>();
                    //设置title
                    sheet2Map.put("title",loginUrlExportParams);
                    //设置导出的实体类型
                    sheet2Map.put("entity",LoginUrl.class);
                    //sheet中要填充的数据
                    sheet2Map.put("data",objects[1]);
                    //将sheet1和sheet2 进行包装
                    List> sheetList = new ArrayList<>();
                    sheetList.add(sheet1Map);
                    sheetList.add(sheet2Map);
                    //执行方法
                    Workbook workbook = ExcelExportUtil.exportExcel(sheetList, ExcelType.HSSF);
                    FileOutputStream outputStream =
                            new FileOutputStream("C:\\Users\\86187\\Desktop\\exportLogin.xls");
                    workbook.write(outputStream);
                    outputStream.close();
                    workbook.close();
                }

             

                //测试多sheet导出
                @Test
                public void testExportMultiSheet() throws Exception {
                    List sheet1 = new ArrayList<>();
                    sheet1.add(new LoginUser("1001", "向阳", "123456", new Date(), "0"));
                    sheet1.add(new LoginUser("1002", "文渊", "123456", new Date(), "1"));
                    sheet1.add(new LoginUser("1003", "小李", "123456", new Date(), "0"));
                    List sheet2 = new ArrayList<>();
                    sheet2.add(new LoginUrl("1001", "get", "http://127.0.0.1:8080"));
                    sheet2.add(new LoginUrl("1001", "post", "http://127.0.0.1:8080/logingout"));
                    exportMultiSheet(sheet1,sheet2);
                }

            集成web实现导入导出

            前端代码

            
            
            
                
                导入excel的主页面
                
            
            
                
                    
                        

            选择Excel文件导入到数据中

            显示导入数据列表

            ID编号 订单编号 课程名称 课程简介 课程价格

            导出excel

             

            Controller层 

            @Controller
            @RequestMapping("/course")
            public class CourseController {
                @Autowired
                private CourseService courseService;
                @RequestMapping("/findAll")
                public String findAll(Model model){
                    List courses = courseService.findAll();
                    System.out.println(courses);
                    model.addAttribute("courses",courses);
                    return "index";
                }
                //导入Excel
                @RequestMapping("/importExcel")
                public String importExcel(MultipartFile excelFile) throws Exception {
                    ImportParams params = new ImportParams();
                    params.setTitleRows(1); //设置1级标题行为一行
                    params.setHeadRows(1); //设置header标题行为一行
                    List courseList = ExcelImportUtil.importExcel(excelFile.getInputStream(), Course.class, params);
                    courseService.save(courseList);
                    return "redirect:/course/findAll";
                }
                //导出Excel
                @RequestMapping("/exportExcel")
                public void exportExcel(HttpServletResponse response)throws Exception{
                    //查询数据库的所有数据
                    List courseList = courseService.findAll();
                    //生成Excel
                    Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("课程信息列表", "课程信息"),
                            Course.class, courseList);
                    response.setHeader("content-disposition","attachment;fileName="+ URLEncoder.encode("课程信息列表.xls","UTF-8"));
                    ServletOutputStream outputStream = response.getOutputStream();
                    workbook.write(outputStream);
                    outputStream.close();
                    workbook.close();
                }
            }

            Service层

            public interface CourseService  {
                //查询所有
                List findAll();
                //插入记录
                void save(List courses);
            }
            @Service
            public class CourseServiceImpl implements CourseService {
                @Autowired
                private CourseDao courseDao;
                @Override
                public List findAll() {
                    return courseDao.findAll();
                }
                @Override
                public void save(List courses) {
                    courses.forEach(course -> {
                        course.setCid(null); //自动生成ID 不使用Excel中的编号
                        courseDao.save(course);
                    });
                }
            }

            dao层

            @Mapper
            public interface CourseDao {
                //查询所有
                List findAll();
                //插入记录
                void save(Course course);
            }

            XML 

            
            
                
                
                
                
                    INSERT INTO course VALUES (#{cid},#{orderno},#{cname},#{brief},#{price})