EasyExcel全面教程快速上手

左手的ㄟ右手 2023-06-13 11:29 41阅读 0赞

EasyExcel教程

本文使用的技术是Alibaba集团开源的EasyExcel技术,该技术是针对Apache POI技术的封装和优化,主要解决了POI技术的耗内存问题,并且提供了较好的API使用。不需要大量的代码就可以实现excel的操作功能。

更多学习资料,可以关注下方微信公众号,回复关键字:Java高级资料 。 即可免费获取完整的Java高级开发工程师视频课程。
在这里插入图片描述

文章目录

  • EasyExcel教程
    • 一、简介
    • 二、传统解析的弊端
    • 三、快速感受
    • 四、详解读取Excel
      • 简单读取
      • 指定列的下标或名称
      • 读取多个sheet
      • 自定义格式转换
      • 多行头
      • 读取表头数据
      • 异常处理
      • web读取
    • 五、详解写入Excel
      • 简单写入
      • 导出指定的列
      • 指定写入的列
      • 复杂头写入
      • 自定义格式转换
      • 图片导出
      • 列宽、行高
      • 合并单元格
      • 动态表头
      • web数据写出
    • 六、详解填充样板写入
      • 简单的填充
      • 复杂的填充
    • 七、API
      • 详细参数介绍
        • 关于常见类解析
          • 注解
          • 参数
            • 通用参数
            • ReadWorkbook(理解成excel对象)参数
            • ReadSheet(就是excel的一个Sheet)参数
          • 注解
          • 参数
            • 通用参数
            • WriteWorkbook(理解成excel对象)参数
            • WriteSheet(就是excel的一个Sheet)参数
            • WriteTable(就把excel的一个Sheet,一块区域看一个table)参数
          • 更多学习资料,可以关注下方微信公众号,回复关键字:Java高级资料 。 即可免费获取完整的Java高级开发工程师视频课程。

一、简介

EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。

二、传统解析的弊端

Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。easyexcel重写了poi对07版Excel的解析,能够原本一个3M的excel用POI sax依然需要100M左右内存降低到几M,并且再大的excel不会出现内存溢出,03版依赖POI的sax模式。在上层做了模型转换的封装,让使用者更加简单方便。

三、快速感受

excel内容




































字符串标题 日期标题 数值标题
字符串10 2019/1/1 10
字符串20 2019/2/1 21
字符串30 2019/3/1 32
字符串40 2019/4/1 43
字符串50 2019/5/1 54

读Excel

  1. /** 简单的读取excel文件 */
  2. @Test
  3. public void read() {
  4. String fileName = "demo.xlsx";
  5. // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
  6. // 参数一:读取的excel文件路径
  7. // 参数二:读取sheet的一行,将参数封装在DemoData实体类中
  8. // 参数三:读取每一行的时候会执行DemoDataListener监听器
  9. EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();
  10. }

写Excel

  1. /** 简单的写入数据到excel */
  2. @Test
  3. public void simpleWrite() {
  4. String fileName = "demo.xlsx";
  5. // 这里 需要指定写用哪个class去读,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  6. // 如果这里想使用03 则 传入excelType参数即可
  7. // 参数一:写入excel文件路径
  8. // 参数二:写入的数据类型是DemoData
  9. // data()方法是写入的数据,结果是List<DemoData>集合
  10. EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
  11. }

Web上传与下载

  1. /** excel文件的下载 */
  2. @GetMapping("download")
  3. public void download(HttpServletResponse response) throws IOException {
  4. response.setContentType("application/vnd.ms-excel");
  5. response.setCharacterEncoding("utf-8");
  6. response.setHeader("Content-disposition", "attachment;filename=demo.xlsx");
  7. EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data());
  8. }
  9. /** excel文件的上传 */
  10. @PostMapping("upload")
  11. @ResponseBody
  12. public String upload(MultipartFile file) throws IOException {
  13. EasyExcel.read(file.getInputStream(), DemoData.class, new DemoDataListener()).sheet().doRead();
  14. return "success";
  15. }

四、详解读取Excel

简单读取

对象

  1. // 如果没有特殊说明,下面的案例将默认使用这个实体类
  2. public class DemoData {
  3. private String string;
  4. private Date date;
  5. private Double doubleData;
  6. // getting setting
  7. }

监听器

  1. // 如果没有特殊说明,下面的案例将默认使用这个监听器
  2. public class DemoDataListener extends AnalysisEventListener<DemoData> {
  3. List<DemoData> list = new ArrayList<DemoData>();
  4. /** * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来 */
  5. public DemoDataListener() { }
  6. /** * 这个每一条数据解析都会来调用 * * @param data * @param context */
  7. @Override
  8. public void invoke(DemoData data, AnalysisContext context) {
  9. System.out.println("解析到一条数据:{}", JSON.toJSONString(data));
  10. list.add(data);
  11. }
  12. /** * 所有数据解析完成了 都会来调用 * * @param context */
  13. @Override
  14. public void doAfterAllAnalysed(AnalysisContext context) {
  15. System.out.println(JSON.toJSONString(list));
  16. }
  17. }

代码

  1. @Test
  2. public void simpleRead() {
  3. // 写法1:
  4. String fileName = "demo.xlsx";
  5. // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
  6. EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();
  7. // 写法2:
  8. fileName = "demo.xlsx";
  9. ExcelReader excelReader = EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).build();
  10. ReadSheet readSheet = EasyExcel.readSheet(0).build();
  11. excelReader.read(readSheet);
  12. // 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的
  13. excelReader.finish();
  14. }

指定列的下标或名称

对象

  1. public class DemoData {
  2. /** * 强制读取第三个 这里不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去匹配 */
  3. @ExcelProperty(index = 2)
  4. private Double doubleData;
  5. /** * 用名字去匹配,这里需要注意,如果名字重复,会导致只有一个字段读取到数据 */
  6. @ExcelProperty("字符串标题")
  7. private String string;
  8. @ExcelProperty("日期标题")
  9. private Date date;
  10. }

代码

  1. @Test
  2. public void indexOrNameRead() {
  3. String fileName = "demo.xlsx";
  4. // 这里默认读取第一个sheet
  5. EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();
  6. }

读取多个sheet

代码

  1. @Test
  2. public void repeatedRead() {
  3. String fileName = "demo.xlsx";
  4. // 读取全部sheet
  5. // 这里需要注意 DemoDataListener的doAfterAllAnalysed 会在每个sheet读取完毕后调用一次。然后所有sheet都会往同一个DemoDataListener里面写
  6. EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).doReadAll();
  7. // 读取部分sheet
  8. fileName = "demo.xlsx";
  9. ExcelReader excelReader = EasyExcel.read(fileName).build();
  10. // 这里为了简单 所以注册了 同样的head 和Listener 自己使用功能必须不同的Listener
  11. // readSheet参数设置读取sheet的序号
  12. ReadSheet readSheet1 =
  13. EasyExcel.readSheet(0).head(DemoData.class).registerReadListener(new DemoDataListener()).build();
  14. ReadSheet readSheet2 =
  15. EasyExcel.readSheet(1).head(DemoData.class).registerReadListener(new DemoDataListener()).build();
  16. // 这里注意 一定要把sheet1 sheet2 一起传进去,不然有个问题就是03版的excel 会读取多次,浪费性能
  17. excelReader.read(readSheet1, readSheet2);
  18. // 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的
  19. excelReader.finish();
  20. }

自定义格式转换

对象

  1. @Data
  2. public class ConverterData {
  3. /** * converter属性定义自己的字符串转换器 */
  4. @ExcelProperty(converter = CustomStringConverter.class)
  5. private String string;
  6. /** * 这里用string 去接日期才能格式化 */
  7. @DateTimeFormat("yyyy年MM月dd日 HH时mm分ss秒")
  8. private String date;
  9. /** * 我想接收百分比的数字 */
  10. @NumberFormat("#.##%")
  11. private String doubleData;
  12. }

自定义转换器

  1. public class CustomStringStringConverter implements Converter<String> {
  2. @Override
  3. public Class supportJavaTypeKey() {
  4. return String.class;
  5. }
  6. @Override
  7. public CellDataTypeEnum supportExcelTypeKey() {
  8. return CellDataTypeEnum.STRING;
  9. }
  10. /** * 这里读的时候会调用 * * @param cellData * NotNull * @param contentProperty * Nullable * @param globalConfiguration * NotNull * @return */
  11. @Override
  12. public String convertToJavaData(CellData cellData, ExcelContentProperty contentProperty,
  13. GlobalConfiguration globalConfiguration) {
  14. return "自定义:" + cellData.getStringValue();
  15. }
  16. /** * 这里是写的时候会调用 不用管 * * @param value * NotNull * @param contentProperty * Nullable * @param globalConfiguration * NotNull * @return */
  17. @Override
  18. public CellData convertToExcelData(String value, ExcelContentProperty contentProperty,
  19. GlobalConfiguration globalConfiguration) {
  20. return new CellData(value);
  21. }
  22. }

代码

  1. @Test
  2. public void converterRead() {
  3. String fileName = "demo.xlsx";
  4. // 这里 需要指定读用哪个class去读,然后读取第一个sheet
  5. EasyExcel.read(fileName, ConverterData.class, new ConverterDataListener())
  6. // 这里注意 我们也可以registerConverter来指定自定义转换器, 但是这个转换变成全局了, 所有java为string,excel为string的都会用这个转换器。
  7. // 如果就想单个字段使用请使用@ExcelProperty 指定converter
  8. // .registerConverter(new CustomStringStringConverter())
  9. // 读取sheet
  10. .sheet().doRead();
  11. }

多行头

代码

  1. @Test
  2. public void complexHeaderRead() {
  3. String fileName = "demo.xlsx";
  4. // 这里 需要指定读用哪个class去读,然后读取第一个sheet
  5. EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet()
  6. // 这里可以设置1,因为头就是一行。如果多行头,可以设置其他值。不传入默认1行
  7. .headRowNumber(1).doRead();
  8. }

读取表头数据

监听器

  1. /** * 这里会一行行的返回头 * 监听器只需要重写这个方法就可以读取到头信息 * @param headMap * @param context */
  2. @Override
  3. public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
  4. LOGGER.info("解析到一条头数据:{}", JSON.toJSONString(headMap));
  5. }

代码

  1. @Test
  2. public void headerRead() {
  3. String fileName = "demo.xlsx";
  4. // 这里 需要指定读用哪个class去读,然后读取第一个sheet
  5. EasyExcel.read(fileName, DemoData.class, new ReadDataListener()).sheet().doRead();
  6. }

异常处理

监听器

  1. /** * 监听器实现这个方法就可以在读取数据的时候获取到异常信息 */
  2. @Override
  3. public void onException(Exception exception, AnalysisContext context) {
  4. LOGGER.error("解析失败,但是继续解析下一行:{}", exception.getMessage());
  5. // 如果是某一个单元格的转换异常 能获取到具体行号
  6. // 如果要获取头的信息 配合invokeHeadMap使用
  7. if (exception instanceof ExcelDataConvertException) {
  8. ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception;
  9. LOGGER.error("第{}行,第{}列解析异常", excelDataConvertException.getRowIndex(),
  10. excelDataConvertException.getColumnIndex());
  11. }
  12. }

web读取

代码

  1. @PostMapping("upload")
  2. @ResponseBody
  3. public String upload(MultipartFile file) throws IOException {
  4. EasyExcel.read(file.getInputStream(), UploadData.class, new UploadDataListener(uploadDAO)).sheet().doRead();
  5. return "SUCCESS";
  6. }

五、详解写入Excel

数据写入公用方法

  1. private List<DemoData> data() {
  2. List<DemoData> list = new ArrayList<DemoData>();
  3. for (int i = 0; i < 10; i++) {
  4. DemoData data = new DemoData();
  5. data.setString("字符串" + i);
  6. data.setDate(new Date());
  7. data.setDoubleData(0.56);
  8. list.add(data);
  9. }
  10. return list;
  11. }

简单写入

对象

  1. public class DemoData {
  2. @ExcelProperty("字符串标题")
  3. private String string;
  4. @ExcelProperty("日期标题")
  5. private Date date;
  6. @ExcelProperty("数字标题")
  7. private Double doubleData;
  8. // getting setting
  9. }

代码

  1. @Test
  2. public void simpleWrite() {
  3. // 写法1
  4. String System.currentTimeMillis() + ".xlsx";
  5. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  6. // 如果这里想使用03 则 传入excelType参数即可
  7. EasyExcel.write(fileName, DemoData.class).sheet("写入方法一").doWrite(data());
  8. // 写法2,方法二需要手动关闭流
  9. fileName = System.currentTimeMillis() + ".xlsx";
  10. // 这里 需要指定写用哪个class去写
  11. ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build();
  12. WriteSheet writeSheet = EasyExcel.writerSheet("写入方法二").build();
  13. excelWriter.write(data(), writeSheet);
  14. /// 千万别忘记finish 会帮忙关闭流
  15. excelWriter.finish();
  16. }

导出指定的列

代码

  1. @Test
  2. public void excludeOrIncludeWrite() {
  3. String fileName = "excludeOrIncludeWrite" + System.currentTimeMillis() + ".xlsx";
  4. // 忽略 date 不导出
  5. Set<String> excludeColumnFiledNames = new HashSet<String>();
  6. excludeColumnFiledNames.add("date");
  7. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  8. EasyExcel.write(fileName, DemoData.class).excludeColumnFiledNames(excludeColumnFiledNames).sheet("忽略date")
  9. .doWrite(data());
  10. fileName = "excludeOrIncludeWrite" + System.currentTimeMillis() + ".xlsx";
  11. // 根据用户传入字段 假设我们只要导出 date
  12. Set<String> includeColumnFiledNames = new HashSet<String>();
  13. includeColumnFiledNames.add("date");
  14. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  15. EasyExcel.write(fileName, DemoData.class).includeColumnFiledNames(includeColumnFiledNames).sheet("导出date")
  16. .doWrite(data());
  17. }

指定写入的列

对象

  1. public class IndexData {
  2. /** * 导出的excel第二列和第四列将空置 */
  3. @ExcelProperty(value = "字符串标题", index = 0)
  4. private String string;
  5. @ExcelProperty(value = "日期标题", index = 2)
  6. private Date date;
  7. @ExcelProperty(value = "数字标题", index = 4)
  8. private Double doubleData;
  9. }

代码

  1. @Test
  2. public void indexWrite() {
  3. String fileName = "indexWrite" + System.currentTimeMillis() + ".xlsx";
  4. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  5. EasyExcel.write(fileName, IndexData.class).sheet("模板").doWrite(data());
  6. }

复杂头写入

对象

  1. public class ComplexHeadData {
  2. /** * 主标题 将整合为一个单元格效果如下: * ————————————————————————— * | 主标题 | * ————————————————————————— * |字符串标题|日期标题|数字标题| * ————————————————————————— */
  3. @ExcelProperty({ "主标题", "字符串标题"})
  4. private String string;
  5. @ExcelProperty({ "主标题", "日期标题"})
  6. private Date date;
  7. @ExcelProperty({ "主标题", "数字标题"})
  8. private Double doubleData;
  9. }

代码

  1. @Test
  2. public void complexHeadWrite() {
  3. String fileName = "complexHeadWrite" + System.currentTimeMillis() + ".xlsx";
  4. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  5. EasyExcel.write(fileName, ComplexHeadData.class).sheet("模板").doWrite(data());
  6. }

自定义格式转换

  1. public class ConverterData {
  2. /** * 自定义的转换 */
  3. @ExcelProperty(value = "字符串标题", converter = CustomStringConverter.class)
  4. private String string;
  5. /** * 我想写到excel 用年月日的格式 */
  6. @DateTimeFormat("yyyy年MM月dd日 HH时mm分ss秒")
  7. @ExcelProperty("日期标题")
  8. private Date date;
  9. /** * 我想写到excel 用百分比表示 */
  10. @NumberFormat("#.##%")
  11. @ExcelProperty(value = "数字标题")
  12. private Double doubleData;
  13. // getting setting
  14. }

代码

  1. @Test
  2. public void converterWrite() {
  3. String "converterWrite" + System.currentTimeMillis() + ".xlsx";
  4. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  5. EasyExcel.write(fileName, ConverterData.class).sheet("模板").doWrite(data());
  6. }

图片导出

对象

  1. @Data
  2. @ContentRowHeight(200)
  3. @ColumnWidth(200 / 8)
  4. public class ImageData {
  5. // 图片导出方式有5种
  6. private File file;
  7. private InputStream inputStream;
  8. /** * 如果string类型 必须指定转换器,string默认转换成string,该转换器是官方支持的 */
  9. @ExcelProperty(converter = StringImageConverter.class)
  10. private String string;
  11. private byte[] byteArray;
  12. /** * 根据url导出 版本2.1.1才支持该种模式 */
  13. private URL url;
  14. }

代码

  1. @Test
  2. public void imageWrite() throws Exception {
  3. String fileName = "imageWrite" + System.currentTimeMillis() + ".xlsx";
  4. // 如果使用流 记得关闭
  5. InputStream inputStream = null;
  6. try {
  7. List<ImageData> list = new ArrayList<ImageData>();
  8. ImageData imageData = new ImageData();
  9. list.add(imageData);
  10. String imagePath = "converter" + File.separator + "img.jpg";
  11. // 放入五种类型的图片 根据实际使用只要选一种即可
  12. imageData.setByteArray(FileUtils.readFileToByteArray(new File(imagePath)));
  13. imageData.setFile(new File(imagePath));
  14. imageData.setString(imagePath);
  15. inputStream = FileUtils.openInputStream(new File(imagePath));
  16. imageData.setInputStream(inputStream);
  17. imageData.setUrl(new URL(
  18. "https://raw.githubusercontent.com/alibaba/easyexcel/master/src/test/resources/converter/img.jpg"));
  19. EasyExcel.write(fileName, ImageData.class).sheet().doWrite(list);
  20. } finally {
  21. if (inputStream != null) {
  22. inputStream.close();
  23. }
  24. }
  25. }

列宽、行高

对象

  1. @Data
  2. @ContentRowHeight(10)
  3. @HeadRowHeight(20)
  4. @ColumnWidth(25)
  5. public class WidthAndHeightData {
  6. @ExcelProperty("字符串标题")
  7. private String string;
  8. @ExcelProperty("日期标题")
  9. private Date date;
  10. /** * 宽度为50,覆盖上面的宽度25 */
  11. @ColumnWidth(50)
  12. @ExcelProperty("数字标题")
  13. private Double doubleData;
  14. }

代码

  1. @Test
  2. public void widthAndHeightWrite() {
  3. String fileName = "widthAndHeightWrite" + System.currentTimeMillis() + ".xlsx";
  4. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  5. EasyExcel.write(fileName, WidthAndHeightData.class).sheet("模板").doWrite(data());
  6. }

合并单元格

代码

  1. @Test
  2. public void mergeWrite() {
  3. String fileName = "mergeWrite" + System.currentTimeMillis() + ".xlsx";
  4. // 每隔2行会合并 把eachColumn 设置成 3 也就是我们数据的长度,所以就第一列会合并。当然其他合并策略也可以自己写
  5. LoopMergeStrategy loopMergeStrategy = new LoopMergeStrategy(2, 0);
  6. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
  7. EasyExcel.write(fileName, DemoData.class).registerWriteHandler(loopMergeStrategy).sheet("合并单元格")
  8. .doWrite(data());
  9. }

动态表头

代码

  1. @Test
  2. public void dynamicHeadWrite() {
  3. String fileName = "dynamicHeadWrite" + System.currentTimeMillis() + ".xlsx";
  4. EasyExcel.write(fileName)
  5. // 这里放入动态头
  6. .head(head()).sheet("模板")
  7. // 当然这里数据也可以用 List<List<String>> 去传入
  8. .doWrite(data());
  9. }
  10. // 动态表头的数据格式List<List<String>>
  11. private List<List<String>> head() {
  12. List<List<String>> list = new ArrayList<List<String>>();
  13. List<String> head0 = new ArrayList<String>();
  14. head0.add("字符串" + System.currentTimeMillis());
  15. List<String> head1 = new ArrayList<String>();
  16. head1.add("数字" + System.currentTimeMillis());
  17. List<String> head2 = new ArrayList<String>();
  18. head2.add("日期" + System.currentTimeMillis());
  19. list.add(head0);
  20. list.add(head1);
  21. list.add(head2);
  22. return list;
  23. }

web数据写出

代码

  1. @GetMapping("download")
  2. public void download(HttpServletResponse response) throws IOException {
  3. response.setContentType("application/vnd.ms-excel");
  4. response.setCharacterEncoding("utf-8");
  5. // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
  6. String fileName = URLEncoder.encode("数据写出", "UTF-8");
  7. response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
  8. EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data());
  9. }

六、详解填充样板写入

这里的案例填充都是模板向下,如果需要横向填充只需要模板设置好就可以。

简单的填充

Excel模板





















A B C
姓名 数字 复杂
{name} {number} {name}今年{number}岁

Excel最终效果





















A B C
姓名 数字 复杂
知春秋 25 知春秋今年25岁

对象

  1. public class FillData {
  2. private String name;
  3. private double number;
  4. // getting setting
  5. }

代码

  1. @Test
  2. public void simpleFill() {
  3. // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
  4. String templateFileName = "simple.xlsx";
  5. // 方案1 根据对象填充
  6. String fileName = System.currentTimeMillis() + ".xlsx";
  7. // 这里 会填充到第一个sheet, 然后文件流会自动关闭
  8. FillData fillData = new FillData();
  9. fillData.setName("知春秋");
  10. fillData.setNumber(25);
  11. EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(fillData);
  12. // 方案2 根据Map填充
  13. fileName = System.currentTimeMillis() + ".xlsx";
  14. // 这里 会填充到第一个sheet, 然后文件流会自动关闭
  15. Map<String, Object> map = new HashMap<String, Object>();
  16. map.put("name", "知春秋");
  17. map.put("number", 25);
  18. EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(map);
  19. }

复杂的填充

使用List集合的方法批量写入数据,点表示该参数是集合

Excel模板





















A B C
姓名 数字 复杂
{.name} {.number} {.name}今年{.number}岁

Excel最终效果














































A B C
姓名 数字 复杂
知春秋 25 知春秋今年25岁
知春秋 25 知春秋今年25岁
知春秋 25 知春秋今年25岁
知春秋 25 知春秋今年25岁
知春秋 25 知春秋今年25岁
知春秋 25 知春秋今年25岁

代码

  1. @Test
  2. public void complexFill() {
  3. // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
  4. // {} 代表普通变量 {.} 代表是list的变量
  5. String templateFileName = "complex.xlsx";
  6. String fileName = System.currentTimeMillis() + ".xlsx";
  7. ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build();
  8. WriteSheet writeSheet = EasyExcel.writerSheet().build();
  9. // 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行,然后下面的数据往后移动。默认 是false,会直接使用下一行,如果没有则创建。
  10. // forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了,所以慎用
  11. // 简单的说 如果你的模板有list,且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
  12. // 如果数据量大 list不是最后一行 参照下一个
  13. FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
  14. excelWriter.fill(data(), fillConfig, writeSheet);
  15. excelWriter.fill(data(), fillConfig, writeSheet);
  16. // 其他参数可以使用Map封装
  17. Map<String, Object> map = new HashMap<String, Object>();
  18. excelWriter.fill(map, writeSheet);
  19. excelWriter.finish();
  20. }

七、API

详细参数介绍

关于常见类解析

Ø EasyExcel 入口类,用于构建开始各种操作

Ø ExcelReaderBuilder ExcelWriterBuilder 构建出一个 ReadWorkbook WriteWorkbook,可以理解成一个excel对象,一个excel只要构建一个

Ø ExcelReaderSheetBuilder ExcelWriterSheetBuilder 构建出一个 ReadSheet WriteSheet对象,可以理解成excel里面的一页,每一页都要构建一个

Ø ReadListener 在每一行读取完毕后都会调用ReadListener来处理数据

Ø WriteHandler 在每一个操作包括创建单元格、创建表格等都会调用WriteHandler来处理数据

Ø 所有配置都是继承的,Workbook的配置会被Sheet继承,所以在用EasyExcel设置参数的时候,在EasyExcel…sheet()方法之前作用域是整个sheet,之后针对单个sheet

注解

Ø ExcelProperty 指定当前字段对应excel中的那一列。可以根据名字或者Index去匹配。当然也可以不写,默认第一个字段就是index=0,以此类推。千万注意,要么全部不写,要么全部用index,要么全部用名字去匹配。千万别三个混着用,除非你非常了解源代码中三个混着用怎么去排序的。

Ø ExcelIgnore 默认所有字段都会和excel去匹配,加了这个注解会忽略该字段

Ø DateTimeFormat 日期转换,用String去接收excel日期格式的数据会调用这个注解。里面的value参照java.text.SimpleDateFormat

Ø NumberFormat 数字转换,用String去接收excel数字格式的数据会调用这个注解。里面的value参照java.text.DecimalFormat

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

参数
通用参数

Ø ReadWorkbook,ReadSheet 都会有的参数,如果为空,默认使用上级。

Ø converter 转换器,默认加载了很多转换器。也可以自定义。

Ø readListener 监听器,在读取数据的过程中会不断的调用监听器。

Ø headRowNumber 需要读的表格有几行头数据。默认有一行头,也就是认为第二行开始起为数据。

Ø head 与clazz二选一。读取文件头对应的列表,会根据列表匹配数据,建议使用class。

Ø clazz 与head二选一。读取文件的头对应的class,也可以使用注解。如果两个都不指定,则会读取全部数据。

Ø autoTrim 字符串、表头等数据自动trim

Ø password 读的时候是否需要使用密码

ReadWorkbook(理解成excel对象)参数

Ø excelType 当前excel的类型 默认会自动判断

Ø inputStream 与file二选一。读取文件的流,如果接收到的是流就只用,不用流建议使用file参数。因为使用了inputStream easyexcel会帮忙创建临时文件,最终还是file

Ø file 与inputStream二选一。读取文件的文件。

Ø autoCloseStream 自动关闭流。

Ø readCache 默认小于5M用 内存,超过5M会使用 EhCache,这里不建议使用这个参数。

ReadSheet(就是excel的一个Sheet)参数

Ø sheetNo 需要读取Sheet的编码,建议使用这个来指定读取哪个Sheet

Ø sheetName 根据名字去匹配Sheet,excel 2003不支持根据名字去匹配

注解

Ø ExcelProperty index 指定写到第几列,默认根据成员变量排序。value指定写入的名称,默认成员变量的名字,多个value可以参照快速开始中的复杂头

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

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

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

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

参数
通用参数

Ø WriteWorkbook,WriteSheet ,WriteTable都会有的参数,如果为空,默认使用上级。

Ø converter 转换器,默认加载了很多转换器。也可以自定义。

Ø writeHandler 写的处理器。可以实现WorkbookWriteHandler,SheetWriteHandler,RowWriteHandler,CellWriteHandler,在写入excel的不同阶段会调用

Ø relativeHeadRowIndex 距离多少行后开始。也就是开头空几行

Ø needHead 是否导出头

Ø head 与clazz二选一。写入文件的头列表,建议使用class。

Ø clazz 与head二选一。写入文件的头对应的class,也可以使用注解。

Ø autoTrim 字符串、表头等数据自动trim

WriteWorkbook(理解成excel对象)参数

Ø excelType 当前excel的类型 默认xlsx

Ø outputStream 与file二选一。写入文件的流

Ø file 与outputStream二选一。写入的文件

Ø templateInputStream 模板的文件流

Ø templateFile 模板文件

Ø autoCloseStream 自动关闭流。

Ø password 写的时候是否需要使用密码

Ø useDefaultStyle 写的时候是否是使用默认头

WriteSheet(就是excel的一个Sheet)参数

Ø sheetNo 需要写入的编码。默认0

Ø sheetName 需要些的Sheet名称,默认同sheetNo

WriteTable(就把excel的一个Sheet,一块区域看一个table)参数

Ø tableNo 需要写入的编码。默认0

更多学习资料,可以关注下方微信公众号,回复关键字:Java高级资料 。 即可免费获取完整的Java高级开发工程师视频课程。

在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,41人围观)

还没有评论,来说两句吧...

相关阅读