EasyExcel 导出动态表格

本文详细介绍了两种在Java中使用EasyExcel进行动态表格导出的方法,包括通过反射获取实体字段信息的方法一和使用`@ExcelProperty`注解的简单方法二。方法一灵活性高但复杂,方法二适用于常规场景,推荐在大多数业务中使用。
摘要由CSDN通过智能技术生成

EasyExcel 导出动态表格

一般推荐使用方法二,但方法一也一定要看,会有很多收获。

需求

:前端选择对应列,导出对应列的数据,比如前端选择了 姓名、名称、学号列
那么就需要导出如下表格:

在这里插在这里插入图片描述
入图片描述

ok,需求明确。

方法一 (推荐待选字段过多不用写VO的情况)

① 通过反射拿到实体对应的字段、属性等信息,返给前端供前端选择。
这里利用了@TableField 、@ApiModelProperty注解拿到对应的
注释(name)、字段名(filedName)、数据库字段名(key)

    public List<Map<String, String>> getFields() {
        Field[] declaredFields = HbProjectInfo.class.getDeclaredFields();
        List<Map<String, String>> resultList = new ArrayList<>();

        for (Field field : declaredFields) {
            if (field.isAnnotationPresent(TableField.class) && field.getAnnotation(TableField.class).exist()) {
                Map<String, String> map = new HashMap<>();
                String key = field.getAnnotation(TableField.class).value();
                String name = null;

                if (field.isAnnotationPresent(ApiModelProperty.class)) {
                    name = field.getAnnotation(ApiModelProperty.class).value();
                }
                map.put("key", key);
                map.put("name", name);
                map.put("filedName", field.getName());
                resultList.add(map);
            }
        }
        return resultList;
    }

结果JSON

[
    {
        "filedName": "name",
        "name": "名字",
        "key": "NAME"
    },
    {
        "filedName": "age",
        "name": "年龄",
        "key": "AGE"
    },
    {
        "filedName": "studentId",
        "name": "学号",
        "key": "STUDENT_ID"
    }
]

② 前端选择后,传给后端

后端传入的 JSON ,比如他选了 年龄、年龄两个字段

[
    {
        "filedName": "name",
        "name": "名字",
        "key": "NAME"
    },
    {
        "filedName": "age",
        "name": "年龄",
        "key": "AGE"
    }
]

③ 后端接口:
studentService 是自己的实现类,自己 @AutoWired 出来即可

    @PostMapping("/export")
    @ApiOperation(value = "学员信息导出", notes = "")
    public AjaxResult export(HttpServletResponse response, @RequestBody List<Map<String,String>> headList) throws Exception {
        studentService.export(response,headList);
        return AjaxResult.success("导出成功!");
    }

④ 实现我们的 export 方法 下面是正文,请好好看

public void export(HttpServletResponse response,List<Map<String,String>> headList) throws Exception {

        if(CollectionUtils.isEmpty(headList)){
            headList = hbProjectInfoService.getFields();
        }
        List<String> names = headList.stream().map(m -> m.get("name")).collect(Collectors.toList());
        List<String> keys = headList.stream().map(m -> m.get("key")).collect(Collectors.toList());
        List<String> filedNames = headList.stream().map(m -> m.get("filedName")).collect(Collectors.toList());

        //表头
        List<List<String>> heads = new ArrayList<>();
        String title = "数据导出";
        for (String name : names) {
            List<String> head0 = new ArrayList<>();
            head0.add(title);
            head0.add(name);
            heads.add(head0);
        }

        //填充数据
        List<List<Object>> dataList = new LinkedList<>();
        String join = String.join(",", keys);
        List<Student>  list = studentService.getColumnsData(join);

        for (Student student: list) {
            List<Object> objectList = new LinkedList<>();
            Class<? extends Student> ac = Student.getClass();
            for (String name : filedNames) {
                Field field = ac.getDeclaredField(student);
                field.setAccessible(true);
                Object o = field.get(student);
                objectList.add(o);
            }
            dataList.add(objectList);
        }

        // 头的策略
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        // 背景设置为白色
        headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints((short)16);
        headWriteCellStyle.setWriteFont(headWriteFont);

        // 内容的策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
        contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
        //设置边框
        contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
        contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);
        contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
        contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);

        //居中
        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        // 背景白色
        contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
        WriteFont contentWriteFont = new WriteFont();

        // 字体大小
        contentWriteFont.setFontHeightInPoints((short)12);
        contentWriteCellStyle.setWriteFont(contentWriteFont);
        // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
        HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);


        // 设置响应头
        // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
        response.setContentType("application/vnd.ms-excel");
        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()).head(heads)
                .registerWriteHandler(horizontalCellStyleStrategy)
                //列宽自适应
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                //设置头部和内容的行高
                .registerWriteHandler(new SimpleRowHeightStyleStrategy((short)50,(short)30))
                .sheet("学员信息表").doWrite(dataList);
    }

结果就是:
在这里插入图片描述

你也可以了解各种策略,来实现你的目的,但是我是真的没再官网知道 EasyExcel 的所有 策略,网上也找不到适合我的,就只能从官网上拼拼凑凑这么个东西。

方法二 (一般情况下推荐)

使用 includeColumnFieldNames

includeSet 为动态表头的 code 是个 Set<String>dataList 为数据,这里需要一个 List <Student >
让实体的字段名称与 includeSet 的 code 对应上即可。

@Data
public class Student {

	@ExcelProperty(value = {"学员基本信息","姓名"},order = 0)
	private String name;

	@ExcelProperty(value = {"学员基本信息","年龄"},order = 1)
	private String age;

	@ExcelProperty(value = {"学员基本信息","学号"},order = 2)
	private String studentID;
}

具体实现代码:

    public void getStudent(HttpServletResponse response) throws Exception {
        //这里我是写死的,你可以让前端传
        Set<String> headList = new HashSet<>();
        headList.add("name");
        headList.add("age");

        //数据
         List<Student> dataList = new LinkedList<>();
        Student student = new Student();
        student.setName("张三");
        student.setAge("12");
        student.setStudentID("12123213");
        dataList.add(student);
        Student student1 = new Student();
        student1.setName("李四");
        student1.setAge("13");
        student1.setStudentID("32432432");
        dataList.add(student1);


        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("学员基本信息", "UTF-8").replaceAll("\\+", "%20");
        // 设置Content-Disposition属性值
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

         EasyExcel.write(response.getOutputStream(), Student.class)
                .includeColumnFieldNames(headList)
                .registerWriteHandler(new ExcelWidthStyleStrategy())
                .registerWriteHandler(new ExcelHeightStyleStrategy())
                .registerWriteHandler(new HbTableStyle()).sheet("学员基本信息").doWrite(dataList);
    }

HbTableStyle 类:方法一的头部策略、内容策略一致,直接使用改类即可,他们都共同继承了 AbstractVerticalCellStyleStrategy

public class HbTableStyle extends AbstractVerticalCellStyleStrategy {

	public HbTableStyle() {
	}

	@Override
	protected WriteCellStyle headCellStyle(Head head) {
		// 头的策略
		WriteCellStyle headWriteCellStyle = new WriteCellStyle();
		// 背景设置为白色
		headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
		WriteFont headWriteFont = new WriteFont();
		headWriteFont.setFontHeightInPoints((short)16);
		headWriteCellStyle.setWriteFont(headWriteFont);
		return headWriteCellStyle;
	}

	@Override
	protected WriteCellStyle contentCellStyle(Head head) {
		// 内容的策略
		WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
		// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
		contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);

		//设置边框
		this.setBorderStyle(contentWriteCellStyle);

		//居中
		contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
		// 背景白色
		contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());

		WriteFont contentWriteFont = new WriteFont();
		// 字体大小
		contentWriteFont.setFontHeightInPoints((short)12);
		contentWriteCellStyle.setWriteFont(contentWriteFont);
		return contentWriteCellStyle;
	}


	private static void setBorderStyle(WriteCellStyle contentWriteCellStyle){
		//设置边框样式
		contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
		contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
		contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
		contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);
	}
}

总结:

区别:方法一灵活,想怎么玩怎么玩,不用定义实体,有点复杂
方法二,简单方便,实用于大部分业务,比起方法一可能没那么灵活,但也够用了。

更多的API使用请查询官网:EasyExcel官网
我就是没仔细看官网API下面有很多的参数配置,只看了基础文档,才写出的方法一。希望大家以后看文档,仔细认真。

EasyExcel是一个用于导出复杂表格的工具。它的优势在于可以通过模板导出符合项目使用习惯的表格,并且支持大数据量导出,性能较好。相比于其他导出方式,如poi方式,EasyExcel可以大大提高开发效率并简化代码。 使用EasyExcel导出复杂表格的步骤如下: 1. 首先,你需要定义一个符合要求的导出模板,模板可以包含合并行、统计汇总等复杂的表格样式和功能。 2. 然后,你需要在代码中使用EasyExcel提供的API来实现导出功能。根据你的需求,你可以在模板中填充数据、设置样式、合并单元格等操作。 3. 最后,你可以将生成的表格保存到指定的位置,或者直接输出给用户。 EasyExcel还提供了详细的文档和示例代码,你可以参考官方网站(https://easyexcel.opensource.alibaba.com/docs/current/)获取更多使用方法和实例。通过使用EasyExcel,你可以轻松地实现复杂表格导出功能,并满足业务的需求。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [easyexcel复杂模板导出(合并行统计汇总)](https://blog.csdn.net/weixin_39172079/article/details/129500460)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [java基于模板导出Excel表格](https://download.csdn.net/download/Silenchen11/86517315)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值