easyexcel读写excel

一、easyexcel是什么?

       EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单,节省内存著称.(在poi的基础上进行了封装,优化了poi学习成本高,内存消耗大的问题)

二、easyexcel怎么用?

2.1 读取操作

  • 看下最简单的读取
/**
*业务场景 我们在开发当中很容易会遇到一种场景就是读写excel
*下面就是最简单的一维excel
 */
//excel数据格式
姓名 出生日期 性别
xx  xx      xx

// 导入坐标
<!-- EasyExcel -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>2.1.6</version>
</dependency>
<!-- lombok 简化开发 -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.10</version>
</dependency>

//创建实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
    private String name;
    private String gender;
    private Date birthday;
    private String id;
}

//书写监听器,处理产生的数据
public class StudentReadListener extends AnalysisEventListener<Student> {
    // 每读一样,会调用该invoke方法一次
    @Override
    public void invoke(Student data, AnalysisContext context) {
        System.out.println("data = " + data);
    }

    // 全部读完之后,会调用该方法
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // TODO......
    }
}

public class Test {
    public static void main(String[] args) throws FileNotFoundException {
        // 读取文件,读取完之后会自动关闭
        /*
        	pathName  		文件路径;
        	head			每行数据对应的实体;Student.class
        	readListener	读监听器,每读一样就会调用一次该监听器的invoke方法
        	sheet方法参数: 工作表的顺序号(从0开始)或者工作表的名字,不传默认为0
        */
        // 封装工作簿对象
        //观察其 构造方法发现可以传流的
        ExcelReaderBuilder read = EasyExcel.read("C:\\Users\\86183\\Desktop\\info.xlsx", Student.class, new StudentReadListener());
        ExcelReaderSheetBuilder sheet = read.sheet();
        sheet.doRead();

    }
}

2.2 写操作

  • @ContentRowHeight() 标注在类上或属性上,指定内容行高

  • @HeadRowHeight() 标注在类上或属性上,指定列头行高

  • @ColumnWidth() 标注在类上或属性上,指定列宽

  • ExcelIgnore` 默认所有字段都会写入excel,这个注解会忽略这个字段

  • DateTimeFormat 日期转换,将Date写到excel会调用这个注解。里面的value参照java.text.SimpleDateFormat

  • NumberFormat 数字转换,用Number写excel会调用这个注解。里面的value参照java.text.DecimalFormat

  • ExcelIgnoreUnannotated 默认不加 ExcelProperty 的注解的都会参与读写,加了不会参与

简单的写操作
package com.itheima.domain;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ColumnWidth(20)
public class Student {


    //@ExcelProperty(value = "编号",index = 3)
    @ExcelIgnore
    private String id;

    @ExcelProperty(value = "学生姓名", index = 0)
    //@ColumnWidth(30)
    private String name;

    @ExcelProperty(value = "学生性别", index = 2)
    private String gender;

    @ExcelProperty(value = "学生出生日期", index = 1)
    //@ColumnWidth(20)
    private Date birthday;
}

     /*     参数说明
            String pathName 写入文件的路径
            Class head      写入文件的对象类型
            默认写入到07的xlsx中,如果想要写入xls,可以指定类型(待验证)
         */
    public static void main(String[] args) {
        ExcelWriterBuilder write = EasyExcel.write("C:\\Users\\86183\\Desktop\\info-2.xlsx", Student.class);

        List<Student> data = getData();
        write.sheet().doWrite(data);
    }

    private static List<Student> getData() {
        ArrayList<Student> students = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Student data = new Student();
            data.setName("lujun" + i);
            data.setBirthday(new Date());
            data.setGender("男");
            students.add(data);
        }
        return students;
    }

2.3 excel的流操作(上传下载)

2.3.1上传解析

  1. 编写实体类(略过)
  2. 编写监听器
@Component
@Scope("prototype")	// 作者要求每次读取都要使用新的Listener
public class StudentReadListener extends AnalysisEventListener<Student> {

    @Autowired
    private StudentService studentService;

	//达到一定的数量就调用数据库的保存方法
    private final int BATCH_SAVE_NUM = 5;
    ArrayList<Student> students = new ArrayList<>();


    private int count = 0;

    // 每读一样=行,会调用该invoke方法一次
    @Override
    public void invoke(Student data, AnalysisContext context) {
        students.add(data);
        if (++count % BATCH_SAVE_NUM == 0) {
            studentService.save(students);
            students.clear();
        }
    }

    // 全部读完之后,会调用该方法
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // TODO......
    }
}
  1. 业务方法和接口(略过)
  2. controller
@Controller
public class ExcelController {
    @PostMapping("upload")
    @ResponseBody
    public String upload(MultipartFile file) throws IOException {
        ExcelReaderBuilder workBook = EasyExcel.read(file.getInputStream(), Student.class, studentReadListener);
        workBook.sheet().doRead();
        return "xx";
    }

2.3.2 文件下载

1.实体类略过
2.controller

public class WebUploadAndDownload {

    @GetMapping("download")
    public void download(HttpServletResponse response) throws IOException {
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        // 防止中文乱码 
        String fileName = URLEncoder.encode("test", "UTF-8");
        response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + fileName + ".xlsx");
        ExcelWriterBuilder workBook = EasyExcel.write(response.getOutputStream(), Student.class);

        ExcelWriterSheetBuilder sheet = workBook.sheet("模板");
        sheet.doWrite(getData);
    }
}

2.4 模板的填充

​ Excel表格中用{} 来表示包裹要填充的变量,如果单元格文本中本来就有{}左右大括号,需要在括号前面使用斜杠转义\{\}

​ 代码中被填充数据的实体对象的成员变量名或被填充map集合的key需要和Excel中被{}包裹的变量名称一致。

@Data
public class FillData {

    private String name;
    private int age;
}

// 两种填充方式一种实体类一种map
public static void main(String[] args) {
    // 加载模板
    InputStream templateFile = FillData.class.getClassLoader().getResourceAsStream(
            "fill_data_template1" +
            ".xlsx");

    // 写入文件
    String targetFileName = "填充数据.xlsx";

    // 准备对象数据填充
    FillData fillData = new FillData();
    fillData.setName("demon");
    fillData.setAge(10);


    // 生成工作簿对象
    ExcelWriterBuilder workBookWriter = EasyExcel.write(targetFileName).withTemplate(templateFile);

    // 获取工作表并填充
    //workBookWriter.sheet().doFill(fillData);

    // 使用Map数据填充
    HashMap<String, String> mapFillData = new HashMap<>();
    mapFillData.put("name", "mapdemon");
    mapFillData.put("age", "11");

    // 获取第一个工作表填充并自动关闭流
    workBookWriter.sheet().doFill(mapFillData);
}
  • 多行填充(修改模板其他的不变)
    在这里插入图片描述

  • 组合填充
    在这里插入图片描述
    即有多组数据填充,又有单一数据填充,为了避免两者数据出现冲突覆盖的情况,在多组填充时需要通过FillConfig对象设置换行。

public static void main(String[] args) {

    InputStream templateFile = FillData.class.getClassLoader().getResourceAsStream(
            "fill_data_template3.xlsx");

    // 目标文件
    String targetFileName = "组合数据填充.xlsx";

    List<FillData> fillDatas = initData();


    ExcelWriter excelWriter = EasyExcel.write(targetFileName).withTemplate(templateFile).build();

    WriteSheet writeSheet = EasyExcel.writerSheet().build();

    // 组合填充时,因为多组填充的数据量不确定,需要在多组填充完之后另起一行
    FillConfig fillConfig = FillConfig.builder().forceNewRow(true).build();

    // 填充并换行
    excelWriter.fill(fillDatas, fillConfig, writeSheet);

    HashMap<String, String> otherData = new HashMap<>();
    otherData.put("date", "2021-03-14");
    otherData.put("total", "130");
    excelWriter.fill(otherData, writeSheet);

    // 关闭
    excelWriter.finish();
}
  • 水平填充
    在这里插入图片描述
public static void main(String[] args) {
    InputStream templateFile = FillData.class.getClassLoader().getResourceAsStream(
            "fill_data_template4.xlsx");

    // 写入文件
    String targetFileName = "easyExcelDemo\\水平数据填充.xlsx";

    List<FillData> fillDatas = initData();

    // 生成工作簿对象
    ExcelWriter excelWriter = EasyExcel.write(targetFileName).withTemplate(templateFile).build();

    // 生成工作表对象
    WriteSheet writeSheet = EasyExcel.writerSheet().build();


    // 组合填充时,因为多组填充的数据量不确定,需要在多组填充完之后另起一行
    FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build();

    // 填充
    excelWriter.fill(fillDatas, fillConfig, writeSheet);

    HashMap<String, String> otherData = new HashMap<>();
    otherData.put("date", "2021-05-14");
    otherData.put("total", "120");
    excelWriter.fill(otherData, writeSheet);

    // 关闭
    excelWriter.finish();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值