EasyExcel的使用:入门到模板填充

EasyExcel

EasyExcel依赖

<!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.0.5</version>
</dependency>

EasyExcel相关网站

EasyExcel简单读取Excel文件

前期准备

  • 准备Excel文件

在这里插入图片描述

  • 准备Excel文件对应的实体类:Student
    package com.study.easyexcel.entity;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    import java.util.Date;
    
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Student {
      
      /**
       * id
       */
      private String id;
      
      /**
       * 学生姓名
       */
      private String name;
      
      /**
       * 学生出生日期
       */
      private Date birthday;
      
      /**
       * 学生性别
       */
      private String gender;
      
    }
    
    

编写代码-简单读取一个Excel中的Sheet的数据

  • 注意:在没有任何配置的情况下,Excel中的数据列顺序要与实体类的属性顺序保持一致

BasicRead-主代码

package com.study.easyexcel.basic;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.builder.ExcelReaderBuilder;
import com.alibaba.excel.read.builder.ExcelReaderSheetBuilder;
import com.study.easyexcel.basic.listener.StudentListener;
import com.study.easyexcel.entity.Student;

import java.io.InputStream;


public class BasicRead {
  
  public static void main(String[] args) {
    //获取到要读取的Excel文件的输入流
    InputStream excelFileIs = BasicRead.class.getResourceAsStream("/excel/学员信息表.xlsx");
    
    //获取一个工作簿对象
    /*
     * @param inputStream:表示要读取的 Excel 文件的输入流。可以从文件、网络、数据库等地方获取。
     * @param head:表示要读取的 Excel 文件中的表头信息所对应的数据模型类型。可以是 Java 类型、Map 类型或 List 类型。
     * @param readListener:表示读取 Excel 文件时的数据监听器(ReadListener)实例,用于在读取过程中接收读取到的数据,并在读取过程中执行相应的操作。
     */
    ExcelReaderBuilder readWorkerBook = EasyExcel.read(excelFileIs, Student.class, new StudentListener());
    //获取一个工作簿对象
    ExcelReaderSheetBuilder sheet = readWorkerBook.sheet();
    //读取工作表中的内容
    sheet.doRead();
  }
  
}


StudentListener-继承了AnalysisEventListener的读监听类

package com.study.easyexcel.basic.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.read.metadata.holder.ReadRowHolder;
import com.study.easyexcel.entity.Student;


public class StudentListener extends AnalysisEventListener<Student> {
  
  /**
   * 在读取到 Excel 文件中的一行数据时会被调用
   *
   * @param data    读取到的一行数据,可以是 Java 对象、Map、List 等类型的数据
   * @param context 参数表示当前读取的上下文信息,包括当前 Sheet 页的信息、当前行号、表头行号等。
   */
  @Override
  public void invoke(Student data, AnalysisContext context) {
    //获取上下文信息
    ReadRowHolder readRowHolder = context.readRowHolder();
    Integer rowIndex = readRowHolder.getRowIndex();
    System.out.println("读取到了第 " + rowIndex + " 行数据 --> " + data);
    
  }
  
  /**
   * 在读取 Excel 文件完成后会被调用
   *
   * @param context 表示当前读取的上下文信息,包括当前 Sheet 页的信息、总行数等。
   */
  @Override
  public void doAfterAllAnalysed(AnalysisContext context) {
    System.out.println("读取完毕!");
  }
  
}

读取效果

在这里插入图片描述

EasyExcel简单写入Excel文件-默认样式

编写代码:BasicWrite

package com.study.easyexcel.basic;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.study.easyexcel.entity.Student;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;


public class BasicWrite {
  
  public static void main(String[] args) {
    //设置输出的Excel文件的存储路径
    String savePath = "F:\\JavaCodeStandalone\\easy-excel-study\\eaey-excel-basic\\src\\main\\resources\\excel\\学员信息表-Write.xlsx";
    //构建一个写的工作簿对象
    //如果写入的文件不存在,则会自动创建
    ExcelWriterBuilder write = EasyExcel.write(savePath, Student.class);
    //工作表对象
    ExcelWriterSheetBuilder sheet = write.sheet();
    //向工作表写入数据
    sheet.doWrite(getStudentList());
  }
  
  /**
   * 随机获取10个Student数据
   */
  private static List<Student> getStudentList() {
    List<Student> list = new ArrayList<>();
    for (int i = 1; i <= 10; i++) {
      list.add(new Student(
          String.valueOf((int) (Math.random() * 1000_0000) + 1000_0000),
          "张" + i,
          new Date((long) (System.currentTimeMillis() + Math.random() * 10_0000)),
          Math.random() < 0.5 ? "男" : "女"
      ));
    }
    return list;
  }
  
}

查看生成的Excel数据

  • 可以发现,默认情况下,使用的列名是属性名,且列宽也不适应数据

EasyExcel简单写入Excel文件-自定义样式(列名、行宽)

  • 在写入Excel文件时,可以使用EasyExcel提供的注解对列名、列顺序、行高、列宽等进行设置
  • 写入Excel的代码还是编写代码:BasicWrite类中的数据,只需要调整实体类的注解即可

修改实体类Student,添加相应的注解

package com.study.easyexcel.entity;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;


@Data
@AllArgsConstructor
@NoArgsConstructor

public class Student {
  
  /**
   * id
   */
  @ExcelProperty(value = "学生Id", index = 0)//设置列名和列顺序
  @ColumnWidth(value = 10)//设置列宽
  private String id;
  
  /**
   * 学生姓名
   */
  @ExcelProperty(value = "学生姓名", index = 1)
  @ColumnWidth(value = 15)
  private String name;
  
  /**
   * 学生出生日期
   */
  @ExcelProperty(value = "学生出生日期", index = 2)
  @ColumnWidth(value = 25)
  private Date birthday;
  
  /**
   * 学生性别
   */
  @ExcelProperty(value = "学生性别", index = 3)
  @ColumnWidth(value = 15)
  private String gender;
  
}

查看写出的Excel文件样式

在这里插入图片描述


EasyExcel+SpringMVC简单的上传下载Excel文件

  • 准备一个普通的Webapp项目,然后进行配置:web.xml配置文件
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
    
        <!-- Spring相关配置 -->
        <!-- 指定Spring配置文件名称位置 -->
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring.xml</param-value>
        </context-param>
    
        <!-- ServletContext创建监听器,会触发创建Spring容器 -->
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
    
        <servlet>
            <servlet-name>dispatcherServlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:spring-mvc.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <!-- 拦截除了JSP以外的所有请求,需要在MVC配置文件中放行静态资源 -->
        <servlet-mapping>
            <servlet-name>dispatcherServlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    
        <!-- 配置全局过滤器,设置编码为UTF-8,解决POST请求乱码问题 -->
        <filter>
            <filter-name>encodingFilter</filter-name>
            <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
            <init-param>
                <param-name>encoding</param-name>
                <param-value>UTF-8</param-value>
            </init-param>
            <init-param>
                <param-name>forceEncoding</param-name>
                <param-value>true</param-value>
            </init-param>
        </filter>
        <filter-mapping>
            <filter-name>encodingFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
    </web-app>
    
    
  • resources目录配置文件:spring.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.2.xsd">
    
        <!-- 组件扫描-->
        <context:component-scan base-package="com.study.easyexcel">
            <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>
    
    </beans>
    
    
  • resources目录配置文件:spring-mvc.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.2.xsd
           http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
        <!-- 组件扫描-->
        <context:component-scan base-package="com.study.easyexcel.controller"/>
    
        <!-- MVC文件上传多部件解析器 -->
        <bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
              id="multipartResolver"/>
    
        <mvc:annotation-driven>
            <mvc:message-converters>
                <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                    <constructor-arg value="UTF-8"/>
                </bean>
            </mvc:message-converters>
        </mvc:annotation-driven>
    
    </beans>
    
    
    
  • controller层代码:StudentController
    package com.study.easyexcel.controller;
    
    import com.alibaba.excel.EasyExcel;
    import com.study.easyexcel.entity.Student;
    import com.study.easyexcel.listener.WebStudentListener;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.multipart.MultipartFile;
    
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.net.URLEncoder;
    import java.nio.charset.StandardCharsets;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    
    @RestController
    @RequestMapping("/student")
    public class StudentController {
      
      @Autowired
      WebStudentListener webStudentListener;
      
      /**
       * 上传Excel
       */
      @RequestMapping("/upload")
      public String uploadExcel(MultipartFile uploadExcel) {
        
        try {
          EasyExcel
              .read(uploadExcel.getInputStream(), Student.class, webStudentListener)
              .sheet()
              .doRead();
          return "上传成功";
        } catch (IOException e) {
          e.printStackTrace();
          return "上传失败";
        }
      }
      
      /**
       * 下载Excel
       */
      @RequestMapping("/download")
      public void downloadExcel(HttpServletResponse response) throws IOException {
        
        //设置响应类型
        response.setContentType("application/vnd.ms-excel");
        //设置响应编码
        response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
        //将文件名进行URL编码
        String fileName = URLEncoder.encode("学员数据", "UTF-8");
        //设置如何显示响应内容:inline->直接浏览、attachment->附件下载
        response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + fileName + ".xlsx");
        
        //获取响应给客户端的输出流
        ServletOutputStream outputStream = response.getOutputStream();
        EasyExcel
            .write(outputStream, Student.class)
            .sheet()
            .doWrite(getStudentList());
      }
      
      /**
       * 随机获取10个Student数据
       */
      private static List<Student> getStudentList() {
        List<Student> list = new ArrayList<>();
        for (int i = 1; i <= 10; i++) {
          list.add(new Student(
              String.valueOf((int) (Math.random() * 1000_0000) + 1000_0000),
              "张" + i,
              new Date((long) (System.currentTimeMillis() + Math.random() * 10_0000)),
              Math.random() < 0.5 ? "男" : "女",
              Math.random() * 1_0000,
              "信息工程学院"
          ));
        }
        return list;
      }
      
    }
    
    
  • 编写Excel读取所需的Linstener:com.study.easyexcel.listener.WebStudentListener
    package com.study.easyexcel.listener;
    
    import com.alibaba.excel.context.AnalysisContext;
    import com.alibaba.excel.event.AnalysisEventListener;
    import com.study.easyexcel.entity.Student;
    import com.study.easyexcel.service.IStudentService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Component;
    
    import java.util.ArrayList;
    import java.util.List;
    
    
    @Component
    @Scope("prototype")//Listener不要配置成单例模式
    public class WebStudentListener extends AnalysisEventListener<Student> {
      
      @Autowired
      private IStudentService studentService;
      
      private List<Student> list = new ArrayList<>();
      
      @Override
      public void invoke(Student data, AnalysisContext context) {
        list.add(data);
        //每5条消息处理一次
        if(list.size() % 5==0){
          studentService.save(list);
          list.clear();
        }
      }
      
      @Override
      public void doAfterAllAnalysed(AnalysisContext context) {
      
      }
      
    }
    
    
  • 编写service接口:com.study.easyexcel.service.IStudentService
    package com.study.easyexcel.service;
    
    import com.study.easyexcel.entity.Student;
    
    import java.util.List;
    
    
    public interface IStudentService {
      
      void save(List<Student> students);
      
    }
    
    
  • 编写service接口实现类:com.study.easyexcel.service.impl.StudentImpl
    package com.study.easyexcel.service.impl;
    
    import com.study.easyexcel.entity.Student;
    import com.study.easyexcel.service.IStudentService;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    
    
    @Service
    public class StudentImpl implements IStudentService {
      
      @Override
      public void save(List<Student> students) {
        System.out.println("接收到上传解析出来的Excel数据:");
        students.forEach(System.out::println);
      }
      
    }
    
    
  • 上传接口:http://localhost:8080/student/upload
  • 下载接口:http://localhost:8080/student/upload

EasyExcel模板填充-概述

模板填充的语法-单条数据填充

  • 在需要填充的位置使用{属性名}的方式进行占位
    在这里插入图片描述

  • 如果本身内容就有{}需要对其使用\进行转义,例如:\{name\}

  • 单行填充可以使用实体类或者Map作为填充数据源,那么实体类的属性或者Map的Key名要与Excel模板文件中的占位名称保持一致

  • 如果在一个单元格内需要填充两个数据,那么可以直接写两个占位的,可以是同名的,如果同名,则会重复填充(可以多行,但是只会重复相同的填充数据)
    在这里插入图片描述

  • 如果希望在填充后的Excel文件中,让\{name\}显示为{name},那么与之一起的必须有一个能被正常填充的占位符
    在这里插入图片描述
    在这里插入图片描述

  • 使用{属性名}方式占位时,如果强行传入多条数据,那么最后将不会进行任何数据填充

模板填充的语法-多条数据填充

  • 占位符语法:{.属性名}
  • 多条数据填充只是在属性名前面家里一个.,此时就可以传入一个集合类型的数据,那么最终填充出来的数据就会是整个集合中的数据

EasyExcel模板填充-最简单的单组数据填充-使用实体类填充

  • 准备一个要填充的模板,该模板的样式会在填充后仍然保留

    在这里插入图片描述

用于填充的实体类-StudentByFill

package com.study.easyexcel.entity;

import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.format.NumberFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.math.RoundingMode;
import java.util.Date;


@Data
@AllArgsConstructor
@NoArgsConstructor
@ExcelIgnoreUnannotated
public class StudentByFill {
  
  /**
   * 学生Id
   */
  @ExcelProperty(value = "学生Id")
  private String id;
  
  /**
   * 学生姓名
   */
  @ExcelProperty(value = "学生姓名")
  private String name;
  
  /**
   * 学生出生日期
   */
  @DateTimeFormat(value = "yyyy-MM-dd")
  @ExcelProperty(value = "学生出生日期")
  private Date birthday;
  
  /**
   * 学生性别
   */
  @ExcelProperty(value = "学生性别")
  private String gender;
  
  /**
   * 学费
   */
  @ExcelProperty(value = "学费")
  @NumberFormat(value = "#.00", roundingMode = RoundingMode.HALF_UP)
  private Double tuition;
  
  /**
   * 学生院系
   */
  @ExcelProperty(value = "学生院系")
  private String department;
  
}

编写填充代码-OneLineFill

package com.study.easyexcel.fill.oneline;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.study.easyexcel.entity.StudentByFill;

import java.util.Date;


public class OneLineFill {
  
  public static void main(String[] args) {
    //要填充的Excel模板的路径
    String templatePath = "F:\\JavaCodeStandalone\\easy-excel-study\\eaey-excel-basic\\src\\main\\resources\\excel_template\\简单的单行填充.xlsx";
    
    //获取工作簿对象(整个Excel文件)
    ExcelWriterBuilder workBook = EasyExcel
        .write("F:\\JavaCodeStandalone\\easy-excel-study\\eaey-excel-basic\\src\\main\\resources\\excel\\简单的单行填充-Write.xlsx", StudentByFill.class)
        //与模板进行关联
        .withTemplate(templatePath);
    
    //获取Sheet对象
    ExcelWriterSheetBuilder sheet = workBook.sheet();
    
    //创建需要被填充的数据
    StudentByFill fillData = new StudentByFill("20222410666", "张三", new Date(978567730000L), "男", 21035.00, "信息工程学院");
    
    //执行数据填充
    sheet.doFill(fillData);//do开头的方法会自在操作结束后,自动关闭流
  }
  
}

填充效果

在这里插入图片描述

EasyExcel模板填充-最简单的单组数据填充-使用Map填充

  • 填充模板和属性仍然使用EasyExcel模板填充-最简单的单组数据填充-使用实体类填充中的
  • 这里只将填充方式从实体类填充变为Map填充

编写填充代码-OneLineFillByMap

package com.study.easyexcel.fill.oneline;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.study.easyexcel.entity.StudentByFill;

import java.util.HashMap;
import java.util.Map;


public class OneLineFillByMap {
  
  public static void main(String[] args) {
    //要填充的Excel模板的路径
    String templatePath = "F:\\JavaCodeStandalone\\easy-excel-study\\eaey-excel-basic\\src\\main\\resources\\excel_template\\简单的单行填充.xlsx";
    
    //获取工作簿对象(整个Excel文件)
    ExcelWriterBuilder workBook = EasyExcel
        .write("F:\\JavaCodeStandalone\\easy-excel-study\\eaey-excel-basic\\src\\main\\resources\\excel\\简单的单行填充-Write.xlsx", StudentByFill.class)
        //与模板进行关联
        .withTemplate(templatePath);
    
    //获取Sheet对象
    ExcelWriterSheetBuilder sheet = workBook.sheet();
    
    //创建需要被填充的数据
    Map<String, String> fillData = new HashMap<>();
    fillData.put("id", "20222410666");
    fillData.put("name", "张三");
    //这里要注意,由于日期直接使用了字符串填充,需要注意日期对象转成日期之后的格式
    //fillData.put("birthday",new Date(978567730000L).toString());//Thu Jan 04 08:22:10 CST 2001
    fillData.put("birthday", "2001-01-01 11:22:33");//Thu Jan 04 08:22:10 CST 2001
    fillData.put("gender", "男");
    fillData.put("tuition", "21035.00");
    fillData.put("department", "信息工程学院");
    
    //执行数据填充
    sheet.doFill(fillData);
  }
  
}

填充效果

在这里插入图片描述


EasyExcel模板填充-垂直列表填充-使用List<T>填充

  • 准备一个要填充的模板,该模板的样式会在填充后仍然保留

在这里插入图片描述

  • 用于填充的实体类-StudentByFill同上

编写填充代码-MultilineFileByList

package com.study.easyexcel.fill.multiline;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.study.easyexcel.entity.StudentByFill;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class MultilineFileByList {
  
  public static void main(String[] args) {
    //要填充的Excel模板的路径
    String templatePath = "F:\\JavaCodeStandalone\\easy-excel-study\\eaey-excel-basic\\src\\main\\resources\\excel_template\\多行数据填充模板.xlsx";
    //填充后文件的保存路径
    String savePath = "F:\\JavaCodeStandalone\\easy-excel-study\\eaey-excel-basic\\src\\main\\resources\\excel\\多行数据填充-Write.xlsx";
    //根据模板获取工作簿
    ExcelWriterBuilder workBook = EasyExcel.write(savePath, StudentByFill.class).withTemplate(templatePath);
    //获取工作表
    ExcelWriterSheetBuilder sheet = workBook.sheet();
    //获取要填充的数据源
    List<StudentByFill> fillDataList = getFillDataList();
    //填充模板
    sheet.doFill(fillDataList);
  }
  
  /**
   * 生成要用于填充的数据
   */
  public static List<StudentByFill> getFillDataList() {
    List<StudentByFill> list = new ArrayList<>();
    
    for (int i = 1; i <= 10; i++) {
      list.add(new StudentByFill(String.valueOf((int) (Math.random() * 1000_0000) + 1000_0000), "张" + i, new Date(), Math.random() < 0.5 ? "男" : "女", Math.random() * 1_0000, "信息工程学院"));
    }
    return list;
  }
  
}

填充效果

在这里插入图片描述

EasyExcel模板填充-水平列表填充

  • 准备一个要填充的模板,该模板的样式会在填充后仍然保留

在这里插入图片描述

  • 用于填充的实体类-StudentByFill同上

编写填充代码-HorizontalFill

package com.study.easyexcel.fill.multiline;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.enums.WriteDirectionEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.study.easyexcel.entity.StudentByFill;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;


public class HorizontalFill {
  
  public static void main(String[] args) {
    //要填充的Excel模板的路径
    String templatePath = "F:\\JavaCodeStandalone\\easy-excel-study\\eaey-excel-basic\\src\\main\\resources\\excel_template\\水平列表填充模板.xlsx";
    //填充后文件的保存路径
    String savePath = "F:\\JavaCodeStandalone\\easy-excel-study\\eaey-excel-basic\\src\\main\\resources\\excel\\水平列表填充-Write.xlsx";
    //根据模板获取工作簿对象
    ExcelWriter workBook = EasyExcel
        .write(savePath, StudentByFill.class)
        .withTemplate(templatePath)
        .build();
    //获取工作表对象
    WriteSheet sheet = EasyExcel.writerSheet().build();
    
    //构建一个 FillConfig 对象,设置填充方向
    FillConfig build = FillConfig.builder()
        //设置填充方向为水平
        .direction(WriteDirectionEnum.HORIZONTAL)
        .build();
    
    //填充数据
    workBook.fill(getFillDataList(), build, sheet);
    //调用do开头的方法时,内部会自动关闭流,当调用fill()方法时,需要自己手动关闭流
    workBook.finish();
  }
  
  /**
   * 生成要用于填充的数据
   */
  public static List<StudentByFill> getFillDataList() {
    List<StudentByFill> list = new ArrayList<>();
    
    for (int i = 1; i <= 10; i++) {
      list.add(new StudentByFill(String.valueOf((int) (Math.random() * 1000_0000) + 1000_0000), "张" + i, new Date(), Math.random() < 0.5 ? "男" : "女", Math.random() * 1_0000, "信息工程学院"));
    }
    return list;
  }
  
}

填充效果

在这里插入图片描述
在这里插入图片描述


EasyExcel模板填充-复杂数据填充

  • 填充列表时,会有多组数据填充和单组数据填充的混合使用。这种情况下就必须手动调用fill()方法进行填充
  • 如果多组数据在单组数据之前填充,那么需要用FillConfig设置多组数据填充时要从新行开始,这样就不会覆盖住底部的汇总数据

Excel模板

在这里插入图片描述

代码需要的实体类-Bill

package com.study.easyexcel.entity;

import lombok.AllArgsConstructor;
import lombok.Data;

import java.util.Date;


@Data
@AllArgsConstructor
public class Bill {
  
  /**
   * 日期
   */
  private Date date;
  
  /**
   * 收支类型
   */
  private String type;
  
  /**
   * 类别
   */
  private String category;
  
  /**
   * 金额
   */
  private Double amount;
  
  /**
   * 备注
   */
  private String note;
  
}

编写填充代码-AccountingFill

package com.study.easyexcel.fill.complex;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.study.easyexcel.entity.Bill;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class AccountingFill {
  
  public static void main(String[] args) throws ParseException {
    //要填充的Excel模板的路径
    String templatePath = "F:\\JavaCodeStandalone\\easy-excel-study\\eaey-excel-basic\\src\\main\\resources\\excel_template\\组合数据填充模板.xlsx";
    //填充后文件的保存路径
    String savePath = "F:\\JavaCodeStandalone\\easy-excel-study\\eaey-excel-basic\\src\\main\\resources\\excel\\组合数据填充-Write.xlsx";
    
    //工作簿对象
    ExcelWriter workBook = EasyExcel.write(savePath, Bill.class)
        .withTemplate(templatePath)
        .build();
    
    //工作表对象
    WriteSheet sheet = EasyExcel.writerSheet().build();
    
    //配置多组数据填充完后,需要换行,防止覆盖模板中的单组数据模板
    FillConfig fillConfig = FillConfig.builder().forceNewRow(true).build();
    
    //获取要填充的数据
    List<Bill> bills = getBills();
    
    //先填充出来多组数据(账单详情数据)
    workBook.fill(bills, fillConfig, sheet);
    
    //填充单组数据(汇总数据)
    long totalCount = bills.size();//账单条数
    double totalAmount = bills.stream().mapToDouble(Bill::getAmount).sum();//账单总金额
    
    HashMap<String, String> summaryMap = new HashMap<>();
    summaryMap.put("totalCount", String.valueOf(totalCount));
    summaryMap.put("totalAmount", String.valueOf(totalAmount));
    //手动单独填充单组数据
    workBook.fill(summaryMap, sheet);
    
    //关闭流
    workBook.finish();
  }
  
  /**
   * 生成账单数据
   */
  private static List<Bill> getBills() throws ParseException {
    List<Bill> list = new ArrayList<>();
    
    String datas = "2022-10-11\t支出\t购物\t18.36\t这里是备注内容\n" +
        "2022-10-11\t支出\t餐饮\t6\t这里是备注内容\n" +
        "2022-10-11\t支出\t学习\t1\t这里是备注内容\n" +
        "2022-10-11\t支出\t餐饮\t9\t这里是备注内容\n" +
        "2022-10-11\t支出\t学习\t1.5\t这里是备注内容\n" +
        "2022-10-10\t支出\t洗澡\t0.6\t这里是备注内容\n" +
        "2022-10-10\t支出\t餐饮\t6\t这里是备注内容\n" +
        "2022-10-10\t支出\t网络支出\t1\t这里是备注内容\n" +
        "2022-10-10\t支出\t餐饮\t9\t这里是备注内容";
    
    //分解出每一条数据
    for (String bill : datas.split("\n")) {
      String[] bills = bill.split("\t");
      Bill bill1 = new Bill(new SimpleDateFormat("yyyy-MM-dd").parse(bills[0]),
                  bills[1],
                  bills[2],
                  Double.parseDouble(bills[3]),
                  bills[4]);
      list.add(bill1);
    }
    return list;
  }
  
}

填充效果

在这里插入图片描述

  • 7
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
EasyExcel中,使用ExcelWriter基于Excel模板填充时,可以使用注解`@ExcelProperty`来指定数据在Excel模板中的位置,并使用`@ContentRowHeight`、`@HeadRowHeight`、`@HeadStyle`、`@ContentStyle`等注解来设置单元格的样式和格式。 而对于合并单元格,可以使用`@ContentLoopMerge`注解来实现。具体步骤如下: 1.在Excel模板中设置需要合并的单元格。例如,我们需要将第2列的数据按照第1列的值进行合并,则可以在第1列的单元格中设置`@ContentLoopMerge(name = "name")`注解来指定需要合并的单元格。如下所示: ``` | 姓名 | 年龄 | 性别 | |------|------|------| | A | 20 | 男 | | A | 25 | 女 | | B | 30 | 男 | | B | 35 | 女 | ``` 2.在实体类中使用`@ExcelProperty`注解来指定数据在Excel模板中的位置。同时,使用`@ContentLoopMerge(name = "name")`注解来指定需要合并的单元格。如下所示: ```java public class User { @ExcelProperty(value = "姓名", index = 0) @ContentLoopMerge(name = "name") private String name; @ExcelProperty(value = "年龄", index = 1) private Integer age; @ExcelProperty(value = "性别", index = 2) private String gender; // getter和setter方法省略 } ``` 3.在代码中使用`ExcelWriter`对象来填充数据,使用`FillConfig`对象来设置`@ContentLoopMerge`注解的参数。如下所示: ```java // 加载Excel模板 InputStream templateInputStream = new FileInputStream("template.xlsx"); Template template = TemplateUtil.loadTemplate(templateInputStream); // 创建ExcelWriter对象 ExcelWriter writer = EasyExcel.write(outputStream).withTemplate(template).build(); // 设置FillConfig对象 FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build(); // 填充数据 List<User> userList = getUserList(); writer.fill(userList, fillConfig, new Sheet(0)); // 关闭ExcelWriter对象 writer.finish(); ``` 在上面的示例中,我们首先加载Excel模板,然后创建`ExcelWriter`对象,设置`FillConfig`对象并填充数据。其中,`forceNewRow`参数表示是否强制创建新的行,`Sheet`对象表示填充数据的Sheet页。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值