EasyExcel使用与详细说明,EasyExcel工具类(三)

简介: EasyExcel使用与详细说明,EasyExcel工具类

5.常用API及注解

5.1 常用类

  • EasyExcel:入口类,用于构建开始各种操作;
  • ExcelReaderBuilder:构建出一个ReadWorkbook对象,即一个工作簿对象,对应的是一个Excel文件;
  • ExcelWriterBuilder:构建出一个WriteWorkbook对象,即一个工作簿对象,对应的是一个Excel文件;
  • ExcelReaderSheetBuilder:构建出一个ReadSheet对象,即一个工作表的对象,对应的Excel中的每个sheet,一个工作簿可以有多个工作表;
  • ExcelWriterSheetBuilder:构建出一WriteSheet对象,即一个工作表的对象,对应的Excel中的每个sheet,一个工作簿可以有多个工作表;
  • ReadListener:在每一行读取完毕后都会调用ReadListener来处理数据,我们可以把调用service的代码可以写在其invoke方法内部;
  • WriteHandler:在每一个操作包括创建单元格、创建表格等都会调用WriteHandler来处理数据,对使用者透明不可见;

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

5.2 读取时的注解

🍀 @ExcelProperty

使用位置:标准作用在成员变量上,吧实体类中属性和excel表中列关联起来。

可选属性:

属性名 含义 说明
index 对应Excel表中的列数 默认-1,建议指定时从0开始
value 对应Excel表中的列头
converter 成员变量转换器 自定义转换器需要实Converter接口

使用效果:index属性可以指定当前字段对应excel中的哪一列,可以根据列名value去匹配,也可以不写。

如果不使用@ExcelProperty注解,成员变量从上到下的顺序,对应表格中从左到右的顺序;

**使用建议:**要么全部不写,要么全部用index,要么全部用名字去匹配,尽量不要三个混着用。

🍀 @ExcelIgnore

标注在成员变量上,默认所有字段都会和excel去匹配,加了这个注解会忽略该字段

🍀 @DateTimeFormat

标注在成员变量上,日期转换,代码中用String类型的成员变量去接收excel中日期格式的数据会调用这个注解。里面的value参照java.text.SimpleDateFormat

/**
     * 学生出生日期
     */
    @ExcelProperty("出生日期")
    @ColumnWidth(20)
    @DateTimeFormat("yyyy-MM-dd")
    private Date birthday;

🍀 @NumberFormat

标注在成员变量上,数字转换,代码中用String类型的成员变量去接收excel数字格式的数据会调用这个注解。里面的value参照java.text.DecimalFormat

🍀 @ExcelIgnoreUnannotated

标注在类上。

不标注该注解时,默认类中所有成员变量都会参与读写,无论是否在成员变量上加了@ExcelProperty 的注解。

标注该注解后,类中的成员变量如果没有标注 @ExcelProperty 注解将不会参与读写。

5.3 读取时通用参数

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

  • converter 转换器,默认加载了很多转换器。也可以自定义。
  • readListener 监听器,在读取数据的过程中会不断的调用监听器。
  • headRowNumber 指定需要读表格的 列头行数。默认有一行头,也就是认为第二行开始起为数据。
  • headclazz 二选一。读取文件头对应的列表,会根据列表匹配数据。建议使用class,就是文件中每一行数据对应的代码中的实体类型。
  • clazzhead 二选一。读取文件的头对应的class,也可以使用注解。如果两个都不指定,则会读取全部数据。
  • autoTrim 字符串、表头等数据自动trim
  • password 读的时候是否需要使用密码

5.4 ReadWorkbook(工作簿对象)参数

  • excelType 当前excel的类型,读取时会自动判断,无需设置。
  • inputStreamfile二选一。建议使用file。
  • fileinputStream二选一。读取文件的文件。
  • autoCloseStream 自动关闭流。
  • readCache 默认小于5M用 内存,超过5M会使用 EhCache,不建议使用这个参数。
  • useDefaultListener@since 2.1.4 默认会加入ModelBuildEventListener 来帮忙转换成传入class的对象,设置成false后将不会协助转换对象,自定义的监听器会接收到Map<Integer,CellData>对象,如果还想继续接听到class对象,请调用readListener方法,加入自定义的beforeListenerModelBuildEventListener、 自定义的afterListener即可。

5.5 ReadSheet(工作表对象)参数

  • sheetNo 需要读取Sheet的编号,建议使用这个来指定读取哪个Sheet
  • sheetName 根据名字去匹配Sheet,excel 2003不支持根据名字去匹配

5.6 写入时的注解

5.6.1 @ExcelProperty

使用位置:标准作用在成员变量上

可选属性:

属性名 含义 说明
index 对应Excel表中的列数 默认-1,指定时建议从0开始
value 对应Excel表中的列头
converter 成员变量转换器 自定义转换器需要实Converter接口

使用效果

  • index 指定写到第几列,如果不指定则根据成员变量位置排序;
  • value指定写入的列头,如果不指定则使用成员变量的名字作为列头;
    如果要设置复杂的头,可以为value指定多个值。
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
 * 学生实体类
 * lombok:通过一个插件 + 一个依赖 ,就可以在编译的时候自动帮助生成实体类常用方法
 * 注解 @ContentRowHeight():内容的行高
 * 注解 @HeadRowHeight:表头的行高
 *
 * @author 狐狸半面添
 * @create 2023-02-26 14:56
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
    /**
     * 学生姓名
     */
    @ExcelProperty(value = {"学员信息表", "学生姓名"})
    @ColumnWidth(20)
    private String name;
    /**
     * 学生出生日期
     */
    @ExcelProperty(value = {"学员信息表", "出生日期"})
    @ColumnWidth(20)
    @DateTimeFormat("yyyy-MM-dd")
    private Date birthday;
    /**
     * index 从0开始
     * 学生性别
     */
    @ExcelProperty(value = {"学员信息表", "学员性别"})
    @ColumnWidth(20)
    private String gender;
    /**
     * id
     */
    @ExcelIgnore
    private String id;
}

5.6.2 其他注解

基本和读取时一致

  • @ContentRowHeight():标注在类上或属性上,指定内容行高
  • @HeadRowHeight():标注在类上或属性上,指定列头行高
  • @ColumnWidth():标注在类上或属性上,指定列宽
  • @ExcelIgnore:默认所有字段都会写入excel,这个注解会忽略这个字段
  • DateTimeFormat:日期转换,将Date写到excel会调用这个注解。里面的value参照java.text.SimpleDateFormat
  • NumberFormat:数字转换,用Number写excel会调用这个注解。里面的value参照java.text.DecimalFormat
  • ExcelIgnoreUnannotated:默认不加 ExcelProperty 的注解的都会参与读写,加了不会参与

5.7 写入时通用参数

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

  • converter 转换器,默认加载了很多转换器。也可以自定义。
  • writeHandler 写的处理器。可以实现WorkbookWriteHandler,SheetWriteHandler,RowWriteHandler,CellWriteHandler,在写入excel的不同阶段会调用,对使用者透明不可见。
  • relativeHeadRowIndex 距离多少行后开始。也就是开头空几行
  • needHead 是否导出头
  • headclazz二选一。写入文件的头列表,建议使用class。
  • clazzhead二选一。写入文件的头对应的class,也可以使用注解。
  • autoTrim 字符串、表头等数据自动trim

5.8 WriteWorkbook(工作簿对象)参数

  • excelType 当前excel的类型,默认为xlsx
  • outputStreamfile二选一。写入文件的流
  • fileoutputStream二选一。写入的文件
  • templateInputStream 模板的文件流
  • templateFile 模板文件
  • autoCloseStream 自动关闭流。
  • password 写的时候是否需要使用密码
  • useDefaultStyle 写的时候是否是使用默认头

5.9 WriteSheet(工作表对象)参数

  • sheetNo 需要写入的编号。默认0
  • sheetName 需要些的Sheet名称,默认同sheetNo

6.easyexcel工具类

6.1 excel通用读取监听类

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
/**
 * excel通用读取监听类
 *
 * @author 狐狸半面添
 * @create 2023-02-26 15:10
 */
@Slf4j
@Getter
@NoArgsConstructor
public class ExcelListener<T> extends AnalysisEventListener<T> {
    /**
     * 自定义用于暂时存储data 可以通过实例获取该值
     */
    private final List<T> dataList = new ArrayList<>();
    /**
     * 每解析一行都会回调invoke()方法
     *
     * @param data 每一行的数据
     */
    @Override
    public void invoke(T data, AnalysisContext context) {
        dataList.add(data);
        log.info("读取的一条信息:{}", data);
    }
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        log.info("{}条数据,解析完成", dataList.size());
    }
}

6.2 工具类

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.fox.easyexcel.listener.ExcelListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;
import java.util.Set;
/**
 * @author 狐狸半面添
 * @create 2023-02-26 21:50
 */
public class EasyExcelUtils {
    private static final Log log = LogFactory.getLog(EasyExcelUtils.class);
    /**
     * 单sheet版本Excel读取
     * 从Excel中读取文件,读取的文件是一个DTO类
     *
     * @param inputStream 文件流
     * @param clazz       行数据类型
     */
    public static <T> List<T> readExcelOneSheet(InputStream inputStream, final Class<?> clazz) {
        // 1.创建监听类
        ExcelListener<T> listener = new ExcelListener<>();
        // 2.构建工作簿对象的输入流
        ExcelReader excelReader = EasyExcel.read(inputStream, clazz, listener).build();
        // 3.构建工作表对象的输入流,默认是第一张工作表
        ReadSheet readSheet = EasyExcel.readSheet(0).build();
        // 4.读取信息,每读取一行都会调用监听类的 invoke 方法
        excelReader.read(readSheet);
        // 5.关闭流,如果不关闭,读的时候会创建临时文件,到时磁盘会崩的
        excelReader.finish();
        return listener.getDataList();
    }
    /**
     * 多sheet版本Excel读取
     *
     * @param <T>      行数据的类型
     * @param filePath 文件路径
     * @param clazz    行数据的类型
     * @return 所有信息
     */
    public static <T> List<T> readExcelAllSheet(String filePath, final Class<?> clazz) {
        ExcelListener<T> listener = new ExcelListener<>();
        // 读取全部sheet
        // 这里需要注意 ExcelListener的doAfterAllAnalysed 会在每个sheet读取完毕后调用一次。然后所有sheet都会往同一个DemoDataListener里面写
        EasyExcel.read(filePath, clazz, listener).doReadAll();
        return listener.getDataList();
    }
    /**
     * 网页上的下载导出,只有一个工作表
     *
     * @param fileName  文件名
     * @param clazz     类的字节码文件,行数据的类型
     * @param dataList  导出的数据
     * @param sheetName 工作表名
     * @param response  响应体
     * @throws IOException 异常对象
     */
    public static void writeWeb(String fileName, final Class<?> clazz, List<?> dataList, String sheetName, HttpServletResponse response) throws IOException {
        // 1.指定响应体内容类型
        response.setContentType("application/vnd.ms-excel");
        // 2.指定编码方式
        response.setCharacterEncoding("utf-8");
        // 3.URLEncoder.encode可以防止中文乱码:import java.net.URLEncoder
        fileName = URLEncoder.encode(fileName, "UTF-8");
        // 4.指定响应标头
        response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + fileName + ".xlsx");
        // 5.获取工作簿对象的输出流
        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();
        // 6.设置工作表的名称
        if (!StringUtils.hasText(sheetName)) {
            sheetName = "sheet1";
        }
        // 7.指定写用哪个class去写
        WriteSheet writeSheet = EasyExcel.writerSheet(0, sheetName).head(clazz).build();
        // 8.将 dataList 中的数据逐行写入工作表中
        excelWriter.write(dataList, writeSheet);
        // 9.finish关闭流
        excelWriter.finish();
        // 10.关闭流
        response.getOutputStream().close();
    }
    public static <T> void writeExcelList(HttpServletResponse response, List<List<T>> data, String fileName, Class<?> clazz, String sheetName) throws Exception {
        OutputStream out = getOutputStream(fileName, response);
        ExcelWriterBuilder excelWriterBuilder = EasyExcel.write(out, clazz).excelType(ExcelTypeEnum.XLSX).registerWriteHandler(getDefaultHorizontalCellStyleStrategy());
        ExcelWriter excelWriter = excelWriterBuilder.build();
        ExcelWriterSheetBuilder excelWriterSheetBuilder;
        WriteSheet writeSheet;
        for (int i = 1; i <= data.size(); i++) {
            excelWriterSheetBuilder = new ExcelWriterSheetBuilder(excelWriter);
            excelWriterSheetBuilder.sheetNo(i);
            excelWriterSheetBuilder.sheetName(sheetName + i);
            writeSheet = excelWriterSheetBuilder.build();
            excelWriter.write(data.get(i - 1), writeSheet);
        }
        excelWriter.finish();
        out.close();
    }
    private static OutputStream getOutputStream(String fileName, HttpServletResponse response) throws Exception {
        fileName = URLEncoder.encode(fileName, "UTF-8");
        //  response.setContentType("application/vnd.ms-excel"); // .xls
        // .xlsx
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf8");
        response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + fileName + ".xlsx");
        return response.getOutputStream();
    }
    /**
     * 获取默认表头内容的样式
     *
     * @return
     */
    private static HorizontalCellStyleStrategy getDefaultHorizontalCellStyleStrategy() {
        /** 表头样式 **/
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        // 背景色(浅灰色)
        // 可以参考:https://www.cnblogs.com/vofill/p/11230387.html
        headWriteCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        // 字体大小
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints((short) 10);
        headWriteCellStyle.setWriteFont(headWriteFont);
        //设置表头居中对齐
        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        /** 内容样式 **/
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        // 内容字体样式(名称、大小)
        WriteFont contentWriteFont = new WriteFont();
        contentWriteFont.setFontName("宋体");
        contentWriteFont.setFontHeightInPoints((short) 10);
        contentWriteCellStyle.setWriteFont(contentWriteFont);
//    //设置内容垂直居中对齐
//    contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
//    //设置内容水平居中对齐
//    contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        // 设置边框样式
        contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
        contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
        contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
        contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);
        // 头样式与内容样式合并
        return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
    }
    /**
     * 导出 Excel到指定目录 :单个 sheet,带表头,
     *
     * @param tableData
     * @param fileName  导出的路径+文件名  例如:   file/test.xlsx
     * @param sheetName 导入文件的 sheet 名
     * @throws Exception
     */
    public static void writeExcelAutoColumnWidth(String fileName, List<?> tableData, String sheetName, Class<?> clazz) throws Exception {
        // 根据用户传入字段 假设我们要忽略 date
        EasyExcel.write(fileName, clazz)
                .sheet(sheetName)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .doWrite(tableData);
    }
    /**
     * 导出 Excel到指定目录 :单个 sheet,带表头,
     *
     * @param fileName  导出的路径+文件名  例如:   file/test.xlsx
     * @param tableData
     */
    public static void writeExcelWithOneSheet1(String fileName, List<?> tableData, String sheetName, Class<?> clazz, Set<String> excludeColumnFiledNames) {
        // 根据用户传入字段 假设我们要忽略 date
        EasyExcel.write(fileName, clazz)
                .excludeColumnFiledNames(excludeColumnFiledNames)
                .sheet(sheetName)
                .registerWriteHandler(styleWrite(false))
                .doWrite(tableData);
    }
    public static HorizontalCellStyleStrategy styleWrite(boolean isWrapped) {
        // 头的策略
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        // 背景设置为红色
        // headWriteCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints((short) 18);
        headWriteCellStyle.setWriteFont(headWriteFont);
        // 内容的策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
        //contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
        // 背景绿色
        //contentWriteCellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex());
        WriteFont contentWriteFont = new WriteFont();
        // 字体大小
        contentWriteFont.setFontHeightInPoints((short) 11);
        //设置 自动换行
        contentWriteCellStyle.setWrapped(isWrapped);
        //设置 垂直居中
        contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        contentWriteCellStyle.setWriteFont(contentWriteFont);
        // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
        return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        //EasyExcel.write(fileName, DemoData.class).registerWriteHandler(horizontalCellStyleStrategy).sheet("模板")
        //    .doWrite(data());
    }
}
相关文章
|
JSON easyexcel Java
EasyExcel的简单使用
EasyExcel的简单使用,以及如何通过postman进行导入导出功能的调试
1201 1
|
1月前
|
easyexcel 计算机视觉
|
3月前
|
easyexcel Java
EasyExcel的使用
EasyExcel的使用
54 0
|
3月前
|
存储 easyexcel Java
SpringBoot整合Easyexcel操作Excel,闲暇之余,让我们学习更多
SpringBoot整合Easyexcel操作Excel,闲暇之余,让我们学习更多
108 0
|
5月前
|
XML 编解码 算法
Hutool超级工具类
Hutool超级工具类
47 0
|
8月前
|
存储 easyexcel Java
EasyExcel
EasyExcel
246 0
|
8月前
|
前端开发 Java 索引
从零玩转EasyPoi
从零玩转EasyPoi
313 0
|
8月前
|
easyexcel Java API
POI及EasyExcel【Java提高】
POI及EasyExcel【Java提高】
283 0
|
9月前
|
存储 JavaScript easyexcel
EasyExcel使用与详细说明,EasyExcel工具类(一)
EasyExcel使用与详细说明,EasyExcel工具类
861 0
|
9月前
|
easyexcel
EasyExcel使用与详细说明,EasyExcel工具类(二)
EasyExcel使用与详细说明,EasyExcel工具类
549 0