EasyExcel使用方法大全 -- 未完结

1. 通用实体类

public class User {
    @ExcelIgnore
    private String id;
    @ExcelProperty("用户名称")
    private String userName;
    @ExcelProperty("用户密码")
    private String password;
    @ExcelProperty("用户生日")
    private String birthday;
    @ExcelProperty("用户性别")
    private Integer sex;
}

2. 导出

2.1. 导出 -- 列宽策略 && 指定导出排除的字段

即导出用户名称,用户密码,用户生日,用户性别字段。

public void exportData(HttpServletResponse response) throws IOException {
	//设置不需要的字段
	Set<String> excludedFields = new HashSet<>();
	excludedFields.add("password");

	response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
	response.setCharacterEncoding("utf-8");
	//encode防止中文乱码,与easyexcel无关
	String fileName = URLEncoder.encode("用户指定不需要导出字段模板测试","UTF-8").replaceAll("\\+", "%20");
	response.addHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
	//防止获取不到文件名称
	response.addHeader("Access-Control-Expose-Headers", "Content-disposition");
	//写到第一个sheet,文件流自动关闭
	//users为自己数据库的查询结果集,类型为List<?>
	EasyExcel.write(response.getOutputStream(), User.class)
	.sheet("模板")
	//列宽策略 宽25
	.registerWriteHandler(new SimpleColumnWidthStyleStrategy(25))
	//排除不需要的字段
	.excludeColumnFiledNames(excludedFields)
	// 写数据
	.doWrite(users);
}

结果:

  1. 仅有列宽策略

  1. 列宽策略 && 排除字段(密码)

2.2. 导出 -- 指定写入的列
public class User {
    @ExcelIgnore
    private String id;
    @ExcelProperty(value = "用户名称",index = 0)
    private String userName;
    @ExcelProperty(value = "用户密码",index = 1)
    private String password;
    @ExcelProperty(value = "用户生日",index = 5)
    private String birthday;
    @ExcelProperty(value = "用户性别",index = 2)
    private Integer sex;
}

通过 index 来指定写入到哪列,导出代码不变。

结果:

2.3. 导出 -- 复杂头写入

将用户名称、用户密码、用户生日设为用户的基本信息
用户性别设为用户的个人信息。

public class User {
    @ExcelIgnore
    private String id;
    @ExcelProperty(value = {"用户基本信息","用户名称"})
    private String userName;
    @ExcelProperty(value = {"用户基本信息","用户密码"})
    private String password;
    @ExcelProperty(value = {"用户基本信息","用户生日"})
    private String birthday;
    @ExcelProperty(value = {"用户个人信息","用户性别"})
    private Integer sex;
}

其他代码正常写,只需修改实体类。

结果:

2.4. 导出 -- 写入单个或多个 sheet(一个对象写入多个 sheet,不同对象写入不同 sheet)
2.4.1. 多个相同的对象写入一个 sheet

业务场景:假设表中数据存在 100 条,分页查询一次只返回 20 条,现在需要将表中数据全部写入到 excel 的一个 sheet 中。

实现:

  1. 前端可以添加 boolean 类型的 page 字段,true 代表后端开启 pagehelper 分页,false 代表不开启。(最优)
  2. 后端循环插入。(官网使用的此方式)

实现 2 后端循环插入:

public void exportAllData(HttpServletResponse response) throws Exception {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        //encode防止中文乱码,与easyexcel无关
        String fileName = URLEncoder.encode("用户分页插入模板","UTF-8").replaceAll("\\+", "%20");
        response.addHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        //防止获取不到文件名称
        response.addHeader("Access-Control-Expose-Headers", "Content-disposition");

        //模拟查询所有数据分页场景
		//循环里为模拟数据方法,每个业务不同,无需管理
        List<User> allData = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            init();
            allData.addAll(users);
        }

        EasyExcel.write(response.getOutputStream(), User.class)
                .sheet("模板")
                .doWrite(allData);
    }

结果:

2.4.2. 多个相同的对象写入不同的 sheet

业务场景:假设表中数据存在 100 条,分页查询一次只返回 20 条,需要将一次分页查询的结果写入到一个 sheet 中,可能存在多个 sheet

实现:

		response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        //encode防止中文乱码,与easyexcel无关
        String fileName = URLEncoder.encode("用户分页插入模板","UTF-8").replaceAll("\\+", "%20");
        response.addHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        //防止获取不到文件名称
        response.addHeader("Access-Control-Expose-Headers", "Content-disposition");

        ExcelWriter writer = EasyExcel.write(response.getOutputStream(), User.class).build();
        //模拟数据不用管
        init();
        //假设总共需要5个sheet页,每页3条数据
        for (int i = 0; i < 5; i++) {
            //创建sheet时,必须指定编号和名称 并且 sheet名称必须不一样
            WriteSheet sheet = EasyExcel.writerSheet(i + 1, "模板" + (i + 1)).build();
            writer.write(users,sheet);
        }
        // 这边一定要finish,否则导出有问题
        writer.finish();

结果:

2.4.3. 多个不同的对象写入到不同的 sheet 中

业务场景:假设有三个查询结果集,需要分别写入到不同的 sheet 中

实现: 就是在 ii.多个相同的对象写入不同的 sheet 中 代码的 13 ~ 17 行进行修改即可。

2.5. 导出 -- 日期、数字或者自定义格式转换。

业务场景:假设在数据库中性别存的是枚举值,但要求输出到 excel 中为男或女....

2.5.1. 实体类
public class People {
    @ExcelProperty(value = "用户名称",converter = PeopleNameConvert.class,index = 0)
    private String name;
    /**
     * 1:男 0: 女
     */
    @ExcelProperty(value = "用户性别",converter = SexConvert.class,index = 1)
    private Integer sex;

    /**
     * 用百分比表示
     */
    @NumberFormat("#.##%")
    @ExcelProperty(value = "余额",index = 2)
    private Double balance;

    @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
    @ExcelProperty(value = "创建时间",index = 3)
    private Date createdTime;
}
2.5.2. PeopleNameConvert
public class PeopleNameConvert implements Converter<String> {
    @Override
    public Class supportJavaTypeKey() {
        return String.class;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }

    @Override
    public String convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        return cellData.getStringValue() + "多加两个字";
    }

    @Override
    public CellData convertToExcelData(String value, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        return new CellData(value + "少加两个字");
    }
}
2.5.3. SexConvert
public class SexConvert implements Converter<Integer> {
    @Override
    public Class supportJavaTypeKey() {
        return Integer.class;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }

    @Override
    public Integer convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        return "男".equals(cellData.getStringValue()) ? 1 : 0;
    }

    @Override
    public CellData convertToExcelData(Integer value, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        return new CellData(value.equals(1) ? "男" : "女");
    }
}
2.5.4. 导出代码
public void exportAllData4(HttpServletResponse response) throws Exception {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        //encode防止中文乱码,与easyexcel无关
        String fileName = URLEncoder.encode("用户格式转换模板","UTF-8").replaceAll("\\+", "%20");
        response.addHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        //防止获取不到文件名称
        response.addHeader("Access-Control-Expose-Headers", "Content-disposition");
        //模拟数据不用管
        init2();
        EasyExcel.write(response.getOutputStream(), People.class).sheet("模板").doWrite(peoples);
    }

结果:

2.6. 导出 -- 图片

业务场景:需要导出图片到 excel 中

2.6.1. 实体类
@NoArgsConstructor
@AllArgsConstructor
@Data
@ContentRowHeight(100)
@ColumnWidth(100 / 8)
public class ImageData {
    @ExcelProperty(value = "名称")
    @ColumnWidth(20)
    private String fileName;

    @ExcelProperty(value = "图片")
    @ColumnWidth(20)
    private URL imagePath;

}
2.6.2. 导出代码
public void exportImage(HttpServletResponse response) throws Exception {
    //初始化从数据库查的数据,不用管
    init3();
    response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    response.setCharacterEncoding("utf-8");
    //encode防止中文乱码,与easyexcel无关
    String fileName = URLEncoder.encode("图片导出测试","UTF-8").replaceAll("\\+", "%20");
    response.addHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
    //防止获取不到文件名称
    response.addHeader("Access-Control-Expose-Headers", "Content-disposition");
    EasyExcel.write(response.getOutputStream(), ImageData.class).sheet("模板").doWrite(images);
}
2.6.3. 测试

2.7. 导出 -- 超链接、备注、指定单元格多个样式
2.7.1. 实体类
@Data
@EqualsAndHashCode
public class WriteCellDemoData {
    /**
     * 超链接
     *
     * @since 3.0.0-beta1
     */
    private WriteCellData<String> hyperlink;

    /**
     * 备注
     *
     * @since 3.0.0-beta1
     */
    private WriteCellData<String> commentData;

    /**
     * 指定单元格的样式。当然样式 也可以用注解等方式。
     *
     * @since 3.0.0-beta1
     */
    private WriteCellData<String> writeCellStyle;

}
2.7.2. 导出代码
 public void exportCellData(HttpServletResponse response) throws IOException {
        WriteCellDemoData cellDemoData = new WriteCellDemoData();
        //超链接
        WriteCellData<String> cellData = new WriteCellData<>("百度");
        cellDemoData.setHyperlink(cellData);
        HyperlinkData hyperlinkData = new HyperlinkData();
        hyperlinkData.setAddress("https://www.baidu.com/");
        hyperlinkData.setHyperlinkType(HyperlinkData.HyperlinkType.URL);
        cellData.setHyperlinkData(hyperlinkData);
        //设置备注
        cellData = new WriteCellData<>("单元格显示的信息");
        cellDemoData.setCommentData(cellData);
        CommentData commentData = new CommentData();
        cellData.setCommentData(commentData);
        commentData.setAuthor("gsx");
        commentData.setRichTextStringData(new RichTextStringData("这是一条备注"));
        // 备注的默认大小是按照单元格的大小 这里想调整到4个单元格那么大 所以向后 向下 各额外占用了一个单元格
        commentData.setRelativeLastColumnIndex(1);
        commentData.setRelativeLastRowIndex(1);
        //设置单个单元格的样式
        cellData = new WriteCellData<>("单元格样式");
        cellData.setType(CellDataTypeEnum.STRING);
        cellDemoData.setWriteCellStyle(cellData);
        WriteCellStyle style = new WriteCellStyle();
        cellData.setWriteCellStyle(style);
        //设置填充样式
        style.setFillPatternType(FillPatternType.BIG_SPOTS);
        //设置背景颜色
        style.setFillForegroundColor(IndexedColors.GREEN.getIndex());

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        //encode防止中文乱码,与easyexcel无关
        String fileName = URLEncoder.encode("图片导出测试","UTF-8").replaceAll("\\+", "%20");
        response.addHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        //防止获取不到文件名称
        response.addHeader("Access-Control-Expose-Headers", "Content-disposition");
        EasyExcel.write(response.getOutputStream(),WriteCellDemoData.class)
                .sheet()
                .doWrite(Arrays.asList(cellDemoData));
    }
2.8. 列宽、行高

@ContentRowHeight: 设置 row 高度,不包含表头,标记在 类上。

@HeadRowHeight(int):设置表头高度,标记在类上。

@ColumnWidth(int): 设置列宽

2.9. 注解自定义样式

@HeadStyle:设置标题样式

dataFormat 日期格式
hidden 设置单元格使用此样式隐藏
locked 设置单元格使用此样式锁定
quotePrefix 在单元格前面增加`符号,数字或公式将以字符串形式展示
horizontalAlignment 设置是否水平居中
wrapped 设置文本是否应换行。将此标志设置为true通过在多行上显示使单元格中的所有内容可见
verticalAlignment 设置是否垂直居中
rotation 设置单元格中文本旋转角度。03版本的Excel旋转角度区间为-90°90°,07版本的Excel旋转角度区间为0°180°
indent 设置单元格中缩进文本的空格数
borderLeft 设置左边框的样式
borderRight 设置右边框样式
borderTop 设置上边框样式
borderBottom 设置下边框样式
leftBorderColor 设置左边框颜色
rightBorderColor 设置右边框颜色
topBorderColor 设置上边框颜色
bottomBorderColor 设置下边框颜色
fillPatternType 设置填充类型
fillBackgroundColor 设置背景色
fillForegroundColor 设置前景色
shrinkToFit 设置自动单元格自动大小

@HeadFontStyle:标题字体样式

参数 含义
fontName 设置字体名称
fontHeightInPoints 设置字体高度
italic 设置字体是否斜体
strikeout 是否设置删除线
color 设置字体颜色
typeOffset 设置偏移量
underline 设置下划线
charset 设置字体编码
bold 设置字体是否加粗

@ContentStyle: 用于定制标题字体格式

参数:
dataFormat 日期格式
hidden 设置单元格使用此样式隐藏
locked 设置单元格使用此样式锁定
quotePrefix 在单元格前面增加`符号,数字或公式将以字符串形式展示
horizontalAlignment 设置是否水平居中
wrapped 设置文本是否应换行。将此标志设置为true通过在多行上显示使单元格中的所有内容可见
verticalAlignment 设置是否垂直居中
rotation 设置单元格中文本旋转角度。03版本的Excel旋转角度区间为-90°90°,07版本的Excel旋转角度区间为0°180°
indent 设置单元格中缩进文本的空格数
borderLeft 设置左边框的样式
borderRight 设置右边框样式
borderTop 设置上边框样式
borderBottom 设置下边框样式
leftBorderColor 设置左边框颜色
rightBorderColor 设置右边框颜色
topBorderColor 设置上边框颜色
bottomBorderColor 设置下边框颜色
fillPatternType 设置填充类型
fillBackgroundColor 设置背景色
fillForegroundColor 设置前景色
shrinkToFit 设置自动单元格自动大小

@ContentFontStyle:内容字体样式

参数:
fontName 字体名称
fontHeightInPoints 字体高度
italic 是否斜体
strikeout 是否设置删除水平线
color 字体颜色
typeOffset 偏移量
underline 下划线
bold 是否加粗
charset 编码格式

2.10. 合并单元格
 // 这一列 每隔2行 合并单元格 加在属性上
@ContentLoopMerge(eachRow = 2)
// 将第6-7行的2-3列合并成一个单元格 加在类上
@OnceAbsoluteMerge(firstRowIndex = 5, lastRowIndex = 6, firstColumnIndex = 1, lastColumnIndex = 2)
2.11. 自定义拦截器
2.11.1. 下拉选择框
2.11.1.1. 拦截器
public class CustomSheetWriteHandler implements SheetWriteHandler {
    @Override
    public void afterSheetCreate(SheetWriteHandlerContext context) {
        // 区间设置 第一列第一行和第二行的数据。由于第一行是头,所以第一、二行的数据实际上是第二三行
        CellRangeAddressList cellRangeAddressList = new CellRangeAddressList(1, 2, 0, 0);
        DataValidationHelper helper = context.getWriteSheetHolder().getSheet().getDataValidationHelper();
        DataValidationConstraint constraint = helper.createExplicitListConstraint(new String[] {"测试1", "测试2"});
        DataValidation dataValidation = helper.createValidation(constraint, cellRangeAddressList);
        context.getWriteSheetHolder().getSheet().addValidationData(dataValidation);
    }
}
2.11.1.2. 导出代码
public void exportPullDown(HttpServletResponse response) throws IOException {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        //encode防止中文乱码,与easyexcel无关
        String fileName = URLEncoder.encode("图片导出测试","UTF-8").replaceAll("\\+", "%20");
        response.addHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        //防止获取不到文件名称
        response.addHeader("Access-Control-Expose-Headers", "Content-disposition");
        EasyExcel.write(response.getOutputStream(),User.class)
                .sheet()
                .registerWriteHandler(new CustomSheetWriteHandler())
                .doWrite(users);
    }
2.11.1.3. 测试

使用 EasyExcel 合并单元格需要使用 `@ExcelIgnoreUnmergedRegions` 注解来忽略未合并的单元格,否则会抛出异常。然后使用 `merge()` 方法来合并单元格。 以下是一个示例代码: ```java @ExcelIgnoreUnmergedRegions public class MergeCellDemo { public static void main(String[] args) { // 写法一:合并指定范围的单元格 EasyExcel.write("merge-cell.xlsx") .sheet("Sheet1") .head(head()) .registerWriteHandler(new MergeCellWriteHandler()) .doWrite(data()); // 写法二:使用注解合并单元格 EasyExcel.write("merge-cell-annotation.xlsx") .sheet("Sheet1") .head(head()) .doWrite(dataWithAnnotation()); } private static List<List<String>> head() { List<List<String>> head = new ArrayList<>(); List<String> row1 = new ArrayList<>(); row1.add("姓名"); row1.add("年龄"); row1.add("性别"); head.add(row1); return head; } private static List<List<Object>> data() { List<List<Object>> data = new ArrayList<>(); List<Object> row1 = new ArrayList<>(); row1.add("张三"); row1.add(20); row1.add("男"); data.add(row1); List<Object> row2 = new ArrayList<>(); row2.add("李四"); row2.add(22); row2.add("女"); data.add(row2); List<Object> row3 = new ArrayList<>(); row3.add("王五"); row3.add(25); row3.add("男"); data.add(row3); return data; } @MergeStrategy(name = "name", mergeType = MergeStrategy.MergeType.HORIZONTAL) @ExcelIgnoreUnmergedRegions private static List<MergeCellDemo> dataWithAnnotation() { return Arrays.asList( new MergeCellDemo("张三", 20, "男"), new MergeCellDemo("李四", 22, "女"), new MergeCellDemo("王五", 25, "男") ); } private String name; private Integer age; private String gender; public MergeCellDemo(String name, Integer age, String gender) { this.name = name; this.age = age; this.gender = gender; } // 省略 getter 和 setter 方法 } ``` 其中,`MergeCellWriteHandler` 是自定义的一个合并单元格处理器,代码如下: ```java public class MergeCellWriteHandler implements WriteHandler { @Override public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { } @Override public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { } @Override public void afterWorkbookCreate(WriteWorkbookHolder writeWorkbookHolder) { } @Override public void beforeWrite(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder) { } @Override public void afterWrite(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder) { } @Override public void afterRowCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer rowIndex, Integer relativeRowIndex, Boolean isHead) { if (isHead) { // 合并第一行的前三列 CellRangeAddress region = new CellRangeAddress(0, 0, 0, 2); writeSheetHolder.getSheet().addMergedRegion(region); } } } ``` 注意,在写入 Excel 文件时,需要调用 `registerWriteHandler()` 方法注册合并单元格处理器。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值