0


Java操作Excel - Easy Excel

一、介绍

官网 https://easyexcel.opensource.alibaba.com/

EasyExcel是阿里巴巴开源的,一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。
他能让你在不用考虑性能、内存的等因素的情况下,快速完成Excel的读、写等功能。
其特点是:

  • 快速的读取excel中的数据。
  • 映射excel和实体类,让代码变的更加简洁。
  • 在读写大文件的时候使用磁盘做缓存,更加的节约内存。

二、使用EasyExcel写

2.1 导入依赖

<!-- easyexcel依赖 --><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.1</version></dependency><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.20</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency>

2.2 导出表格极简入门

①声明一个简单的对象

@Getter@Setter@EqualsAndHashCodepublicclassDemoData{@ExcelProperty("字符串标题")//这里默认为value属性赋值,value为导出的表格的表头privateString string;@ExcelProperty("日期标题")privateDate date;@ExcelProperty("数字标题")privateDouble doubleData;@ExcelIgnore//忽略这个字段,生成的表格中就不会有该字段privateString ignore;}

②写一个简单的表格导出案例

publicclassSimpleWriteTest{@TestpublicvoidsimpleWrite(){//1.模拟要写出数据List<DemoData> list =ListUtils.newArrayList();for(int i =0; i <10; i++){DemoData data =newDemoData();
            data.setString("字符串"+ i);
            data.setDate(newDate());
            data.setDoubleData(0.56);
            list.add(data);}//2.设置写出的文件路径String fileName ="demo1.xlsx";//3.利用EasyExcel写出,会自动关流//write方法的参数1:文件路径,参数2:模板对象类型EasyExcel.write(fileName,DemoData.class).sheet("模板")//sheet页名字.doWrite(list);//要写出的数据}}

这样,就会在当前项目目录下生成名为

demo1.xlsx

的表格,内容如下:
在这里插入图片描述

2.3 根据参数导出指定属性

案例1:指定哪些属性不需要导出到表格中,仅导出剩余属性。

publicclassSimpleWriteTest{@TestpublicvoidexcludeWrite(){//1.模拟要写出数据List<DemoData> list =ListUtils.newArrayList();for(int i =0; i <10; i++){DemoData data =newDemoData();
            data.setString("字符串"+ i);
            data.setDate(newDate());
            data.setDoubleData(0.56);
            list.add(data);}//2.设置导出过程中剔除的字段Set<String> excludeColumnFiledNames =newHashSet<String>();
        excludeColumnFiledNames.add("date");//这里剔除date属性//3.设置写出的文件路径String fileName ="demo2.xlsx";//4.写出EasyExcel.write(fileName,DemoData.class).excludeColumnFieldNames(excludeColumnFiledNames)//将要剔除的列设置给EasyExcel.sheet("模板").doWrite(list);}}

结果如下,就没有了日期列。
在这里插入图片描述

案例2:指定仅导出哪些属性,剩余属性不导出。

publicclassSimpleWriteTest{@TestpublicvoidIncludeWrite(){//1.模拟要写出数据List<DemoData> list =ListUtils.newArrayList();for(int i =0; i <10; i++){DemoData data =newDemoData();
            data.setString("字符串"+ i);
            data.setDate(newDate());
            data.setDoubleData(0.56);
            list.add(data);}//2.设置仅导出哪些属性Set<String> includeColumnFiledNames =newHashSet<String>();
        includeColumnFiledNames.add("date");//3.设置写出的文件路径String fileName ="demo3.xlsx";//4.写出EasyExcel.write(fileName,DemoData.class).includeColumnFieldNames(includeColumnFiledNames)//设置给EasyExcel.sheet("模板").doWrite(list);//这里导出的表格中就只有:时间字段。}}

2.4 指定写入的列

使用

@ExcelProperty

注解的

index

属性指定要导入列的下标。

@Getter@Setter@EqualsAndHashCodepublicclassIndexData{@ExcelProperty(value ="字符串标题", index =0)privateString string;@ExcelProperty(value ="日期标题", index =1)privateDate date;//这里设置3 会导致第三列空的@ExcelProperty(value ="数字标题", index =3)privateDouble doubleData;}
publicclassWriteTest{@TestpublicvoidwriteDemo(){//1.模拟要写出数据List<IndexData> list =ListUtils.newArrayList();for(int i =0; i <10; i++){IndexData data =newIndexData();
            data.setString("字符串"+ i);
            data.setDate(newDate());
            data.setDoubleData(0.56);
            list.add(data);}//2.设置写出的文件路径String fileName ="demo4.xlsx";//3.写出EasyExcel.write(fileName,IndexData.class).sheet("模板").doWrite(list);}}

能看到第三列是空的:
在这里插入图片描述

2.5 复杂头写入

在导出表格的时候,会因为业务需求,导出复杂的表头,咱们可以使用

@ExcelProperty

注解的

value

属性来实现这个需求。

例如我们要导出一个如图的表格:
在这里插入图片描述
仅需通过

value

属性设置即可:

@Getter@Setter@EqualsAndHashCodepublicclassComplexHeadData{@ExcelProperty(value={"主标题","副标题1","字符串标题"})privateString string;@ExcelProperty(value={"主标题","副标题1","日期标题"})privateDate date;@ExcelProperty(value={"主标题","副标题2","数字标题"})privateDouble doubleData;}

导出的代码:

publicclassWriteTest{@TestpublicvoidcomplexHeadWrite(){List<ComplexHeadData> list =ListUtils.newArrayList();for(int i =0; i <10; i++){ComplexHeadData data =newComplexHeadData();
            data.setString("字符串"+ i);
            data.setDate(newDate());
            data.setDoubleData(0.56);
            list.add(data);}//2.设置写出的文件路径String fileName ="demo5.xlsx";//3.导出EasyExcel.write(fileName,ComplexHeadData.class).sheet("模板").doWrite(list);}}

2.6 写出到多个sheet

2.6.1 多个sheet中写入相同类型对象

publicclassWriteTest{@TestpublicvoidrepeatedWrite(){//1.模拟要写出数据List<DemoData> list =ListUtils.newArrayList();for(int i =0; i <10; i++){DemoData data =newDemoData();
            data.setString("字符串"+ i);
            data.setDate(newDate());
            data.setDoubleData(0.56);
            list.add(data);}String fileName ="demo6.xlsx";//2.创建 ExcelWriter对象,并指定文件名和对象类型try(ExcelWriter excelWriter =EasyExcel.write(fileName,DemoData.class).build()){// 这里模拟5次for(int i =0; i <5; i++){// 每次都要创建writeSheet,这里注意必须指定sheetNo(sheet页编号),而且sheetName(sheet也名字)必须不一样WriteSheet writeSheet =EasyExcel.writerSheet(i,"模板"+ i).build();// 将数据写入到sheet页中,最终,会生成5个sheet页
                excelWriter.write(list, writeSheet);}}}}

效果见下图:
在这里插入图片描述

2.6.2 多个sheet中写入不同类型对象

publicclassWriteTest{@TestpublicvoidrepeatedWrite1(){//1.模拟要写出数据List<DemoData> list =ListUtils.newArrayList();for(int i =0; i <10; i++){DemoData data =newDemoData();
            data.setString("字符串"+ i);
            data.setDate(newDate());
            data.setDoubleData(0.56);
            list.add(data);}String fileName ="demo7.xlsx";//2.创建ExcelWriter对象,仅需指定文件名,因为写入的数据是不固定的,所以不能写死try(ExcelWriter excelWriter =EasyExcel.write(fileName).build()){// 模拟5次for(int i =0; i <5; i++){// 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样。// 注意:head方法中的DemoData.class 可以每次都变,我这里为了方便 所以用的同一个class,实际上可以一直变WriteSheet writeSheet =EasyExcel.writerSheet(i,"模板"+ i).head(DemoData.class).build();// 写出数据
                excelWriter.write(list, writeSheet);}}}}

2.7 日期、数字或者自定义格式转换

在写出数据时,如果需要对数据进行格式设置,可以为对象进行如下设置:

@Getter@Setter@EqualsAndHashCodepublicclassConverterData{/**
     * 我想所有的 字符串起前面加上"自定义:"三个字
     */@ExcelProperty(value ="字符串标题", converter =CustomStringStringConverter.class)privateString string;/**
     * 我想写到excel 用年月日的格式
     */@DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")@ExcelProperty("日期标题")privateDate date;/**
     * 我想写到excel 用百分比表示
     */@NumberFormat("#.##%")@ExcelProperty(value ="数字标题")privateDouble doubleData;}

自定义格式:

publicclassCustomStringStringConverterimplementsConverter<String>{@OverridepublicClass<?>supportJavaTypeKey(){returnString.class;}@OverridepublicCellDataTypeEnumsupportExcelTypeKey(){returnCellDataTypeEnum.STRING;}/**
     * 这里读的时候会调用,先不管
     */@OverridepublicStringconvertToJavaData(ReadConverterContext<?> context){return"自定义:"+ context.getReadCellData().getStringValue();}/**
     * 这里是写的时候会调用
     * 会在原有内容之前拼接上:"自定义:"
     */@OverridepublicWriteCellData<?>convertToExcelData(WriteConverterContext<String> context){returnnewWriteCellData<>("自定义:"+context.getValue());}}

写出的代码:

publicclassSimpleWriteTest{@TestpublicvoidconverterWrite(){//1.模拟要写出数据List<ConverterData> list =ListUtils.newArrayList();for(int i =0; i <10; i++){ConverterData data =newConverterData();
            data.setString("字符串"+ i);
            data.setDate(newDate());
            data.setDoubleData(0.56);
            list.add(data);}String fileName ="demo8.xlsx";//3.写出EasyExcel.write(fileName,ConverterData.class).sheet("模板").doWrite(list);}}

效果如下:
在这里插入图片描述

2.8 设置列宽,行高

使用注解在对象的属性上进行设置即可

@Getter@Setter@EqualsAndHashCode@ContentRowHeight(20)//内容高度为:20@HeadRowHeight(40)//表头高度为:40@ColumnWidth(25)//列宽为:25publicclassWidthAndHeightData{@ExcelProperty("字符串标题")privateString string;@ExcelProperty("日期标题")privateDate date;//单独设置宽度为50@ColumnWidth(50)@ExcelProperty("数字标题")privateDouble doubleData;}

导出代码为:

publicclassWriteTest{@TestpublicvoidwidthAndHeightWrite(){//1.模拟要写出数据List<WidthAndHeightData> list =ListUtils.newArrayList();for(int i =0; i <10; i++){WidthAndHeightData data =newWidthAndHeightData();
            data.setString("字符串"+ i);
            data.setDate(newDate());
            data.setDoubleData(0.56);
            list.add(data);}String fileName ="demo9.xlsx";//3.写出EasyExcel.write(fileName,WidthAndHeightData.class).sheet("模板").doWrite(list);}}

2.9 合并单元格

使用注解来设置合并规则:

@Getter@Setter@EqualsAndHashCode// 将第6-7行的2-3列合并成一个单元格// @OnceAbsoluteMerge(firstRowIndex = 5, lastRowIndex = 6, firstColumnIndex = 1, lastColumnIndex = 2)publicclassDemoMergeData{// 这一列 每隔2行 合并单元格@ContentLoopMerge(eachRow =2)@ExcelProperty("字符串标题")privateString string;@ExcelProperty("日期标题")privateDate date;@ExcelProperty("数字标题")privateDouble doubleData;}

写出:

publicclassSimpleWriteTest{@TestpublicvoidmergeWrite(){//1.模拟要写出数据List<DemoMergeData> list =ListUtils.newArrayList();for(int i =0; i <10; i++){DemoMergeData data =newDemoMergeData();
            data.setString("字符串"+ i);
            data.setDate(newDate());
            data.setDoubleData(0.56);
            list.add(data);}String fileName ="demo10.xlsx";//2.写出EasyExcel.write(fileName,DemoMergeData.class).sheet("模板").doWrite(list);}}

效果如下
在这里插入图片描述

2.10 在web项目中实现excel的导出

2.10.1 客户端页面

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title></head><body><ahref="/download">导出excel</a></body></html>

2.10.2 服务端代码

@ControllerpublicclassDownloadController{@GetMapping("/download")publicvoiddownload(HttpServletResponse response)throwsIOException{//1.模拟数据List<DemoData> list =ListUtils.newArrayList();for(int i =0; i <10; i++){DemoData data =newDemoData();
            data.setString("字符串"+ i);
            data.setDate(newDate());
            data.setDoubleData(0.56);
            list.add(data);}//2.执行导出//设置响应类型
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");//设置编码
        response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止文件名中文乱码,当然和easyexcel没有关系String fileName =URLEncoder.encode("测试","UTF-8").replaceAll("\\+","%20");//设置文件名
        response.setHeader("Content-disposition","attachment;filename*=utf-8''"+ fileName +".xlsx");//导出EasyExcel.write(response.getOutputStream(),DemoData.class).sheet("模板").doWrite(list);}}

三、使用EasyExcel读

easyexcel读取表格内容是基于监听器方式实现的,我们需要实现它提供的

ReadListener

接口,进而实现读取的功能。

3.1 极简入门

假如有表格

demo.xlsx

的内容如下:
在这里插入图片描述
① 首先我们需要准备一个对象与之对应:

@Getter@Setter@EqualsAndHashCodepublicclassDemoData{@ExcelProperty("字符串标题")privateString string;@ExcelProperty("日期标题")privateDate date;@ExcelProperty("数字标题")privateDouble doubleData;}

② 准备监听器

publicclassDemoDataListenerimplementsReadListener<DemoData>{/**
     * 每存储100条,可以存储一次数据库,然后清理list ,方便内存回收
     */privatestaticfinalint BATCH_COUNT =100;/**
     * 用于缓存的数据的集合
     */privateList<DemoData> cachedDataList =ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);/* 在实际开发中我们可以使用有参构造,将自己的 dao 或者 service传进来,进而实现数据入库
    private DemoDAO demoDAO;
    public DemoDataListener(DemoDAO demoDAO) {
        this.demoDAO = demoDAO;
    }
     *//**
     * 这个每一条数据解析都会来调用
     */@Overridepublicvoidinvoke(DemoData data,AnalysisContext context){System.out.println("每次读到内容是:"+data);
        cachedDataList.add(data);// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOMif(cachedDataList.size()>= BATCH_COUNT){//1.存储数据库//demoDAO.saveBatch(cachedDataList);//2.存储完成清理 list
            cachedDataList =ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);}}/**
     * 所有数据解析完成了 都会来调用
     */@OverridepublicvoiddoAfterAllAnalysed(AnalysisContext context){System.out.println("所有数据解析完成!");}}

③ 读取表格内容

publicclassReadTest{@TestpublicvoidsimpleRead(){String fileName ="demo.xlsx";// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭EasyExcel.read(fileName,DemoData.class,newDemoDataListener()).sheet().doRead();}}

3.2 在web中的读

@PostMapping("/upload")@ResponseBodypublicStringupload(MultipartFile file)throwsIOException{//read方法参数说明://参数1:文件输入流//参数2:与表格数据对应的对象类型//参数3:监听器EasyExcel.read(file.getInputStream(),UploadData.class,newUploadDataListener(uploadDAO)).sheet().doRead();return"success";}
标签: java junit spring

本文转载自: https://blog.csdn.net/weixin_45691611/article/details/127123322
版权归原作者 码赛客1024 所有, 如有侵权,请联系我们删除。

“Java操作Excel - Easy Excel”的评论:

还没有评论