EasyExcel web动态表格导出

该博客主要介绍了如何在Java中利用EasyExcel库实现动态表头的Excel导出,无需预先创建实体类。内容包括从JSON数据中解析表单字段,封装表头和数据,以及处理动态无对象的数据写入Excel的过程。示例代码详细展示了整个流程,适用于需要动态导出数据的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

场景:

需求:动态表头,web导出
实体类不适应,可以用EasyExcel提供的不创建对象写出

表单字段表:

结果表:
在这里插入图片描述
form_content内容实例:(需要取出的是value的值)

[
    {
        "id": 45,
        "activityId": 165353669805091,
        "formField": "姓名",
        "inputType": 0,
        "value": "1",
        "ztAppValue": "姓名:1\n"
    },
    {
        "id": 46,
        "activityId": 165353669805091,
        "formField": "联系方式",
        "inputType": 0,
        "value": "1",
        "ztAppValue": "联系方式:1\n"
    },
    {
        "id": 47,
        "activityId": 165353669805091,
        "formField": "爱好",
        "inputType": 2,
        "optionContent": [
            "吃饭",
            "睡觉",
            "打豆豆"
        ],
        "value": [
            "睡觉"
        ],
        "ztAppValue": "爱好:睡觉"
    },
    {
        "id": 48,
        "activityId": 165353669805091,
        "formField": "性别",
        "inputType": 1,
        "optionContent": [
            "男",
            "女"
        ],
        "value": "女",
        "ztAppValue": "性别:女\n"
    },
    {
        "id": 49,
        "activityId": 165353669805091,
        "formField": "学科",
        "inputType": 2,
        "optionContent": [
            "语",
            "数",
            "英",
            "物",
            "化"
        ],
        "value": [
            "数"
        ],
        "ztAppValue": "学科:数"
    },
    {
        "id": 50,
        "activityId": 165353669805091,
        "formField": "不良嗜好",
        "inputType": 1,
        "optionContent": [
            "睡觉",
            "打豆豆",
            "磨牙"
        ],
        "value": "打豆豆",
        "ztAppValue": "不良嗜好:打豆豆\n"
    },
    {
        "id": 51,
        "activityId": 165353669805091,
        "formField": "学生身份证",
        "inputType": 0,
        "optionContent": "352314200305028375",
        "value": "1",
        "ztAppValue": "学生身份证:1\n"
    },
    {
        "id": 52,
        "activityId": 165353669805091,
        "formField": "父亲姓名",
        "inputType": 0,
        "optionContent": "张三",
        "value": "1",
        "ztAppValue": "父亲姓名:1\n"
    },
    {
        "id": 53,
        "activityId": 165353669805091,
        "formField": "父亲电话",
        "inputType": 0,
        "optionContent": "12387324635",
        "value": "1",
        "ztAppValue": "父亲电话:1\n"
    }
]

注意点:

  1. 表头、数据封装成以下形式
//封装表头
List<List<String>> headList = new ArrayList<>();
//封装数据
List<List<String>> data = new ArrayList<>();
  1. 表单list长度必须和一条数据List长度对应

代码:

@RequestMapping(value = "/exportData", method = RequestMethod.GET)
    public Map<String, Object> exportData(Long activityId,HttpServletResponse response) throws Exception {

        try {
            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");

            // 取表头
            // 查出数据库的表头字段
            List<ActivityForm> activityFormList = activityFormService.getByActivityId(activityId);
            List<String> fieldList = new ArrayList<>();
            for (ActivityForm activityForm : activityFormList) {
                fieldList.add(activityForm.getFormField());
            }

            // 封装表头
            List<List<String>> headList = new ArrayList<>();
            for (String str : fieldList) {
                List<String> head = new ArrayList<>();
                head.add(str);
                headList.add(head);
            }
            List<String> head0 = new ArrayList<>();
            head0.add("报名状态");
            List<String> head1 = new ArrayList<>();
            head1.add("签到");
            List<String> head2 = new ArrayList<>();
            head2.add("签退");
            headList.add(head0);
            headList.add(head1);
            headList.add(head2);


            // 动态无对象封装数据
            List<List<String>> data = new ArrayList<>();

            // 将所有的formContent数据封装成一个list
            List<ActivityFormResult> resultList = activityFormResultService.getResultListExcel(activityId);
            List<String> resultString = new ArrayList<>();
            for (ActivityFormResult activityFormResult : resultList) {
                String formContent = activityFormResult.getFormContent();
                resultString.add(formContent);
            }


            for (int i = 0; i < resultList.size(); i++) {
                // 处理formContent数据
                JSONArray jsonArray = JSONArray.fromObject(resultString.get(i));
                List<String> valueList = new ArrayList<>();
                for (int j = 0; j < jsonArray.size(); j++) {
                    JSONObject jsonObject = jsonArray.getJSONObject(j);
                    Object value = jsonObject.get("value");
                    valueList.add(value.toString());

                }
                // 处理固定字段:报名状态、签到、签退
                valueList.add(resultList.get(i).getAuthState().toString());
                if (resultList.get(i).getSignIn() != null) {
                    valueList.add(resultList.get(i).getSignIn().toString());
                } else {
                    valueList.add("");
                }
                if (resultList.get(i).getSignOff() != null) {
                    valueList.add(resultList.get(i).getSignOff().toString());
                } else {
                    valueList.add("");
                }
                data.add(valueList);
            }

            // 写出Excel
            EasyExcel.write(response.getOutputStream())
                    .autoCloseStream(Boolean.FALSE)
                    .head(headList)
                    .sheet("data")
                    .doWrite(data);

            resultMap.put("status", 200);
            resultMap.put("message", "请求成功!");
        } catch (Exception e) {
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            resultMap.put("status", 500);
            resultMap.put("message", "请求失败!");
            LoggerUtils.fmtError(getClass(), e, "请求失败。");
        }

        return resultMap;
    }
### 使用 EasyExcel 实现复杂/多表头的数据导出 #### 创建 Maven 项目并引入依赖 为了使用 EasyExcel 进行开发,首先需要创建一个 Maven 项目,并在 `pom.xml` 中添加如下依赖: ```xml <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.0.5</version> </dependency> ``` #### 定义实体类 假设要导出一份销售记录报表,其中包含多个层次的表头。可以通过定义对应的实体类来映射这些字段。 ```java import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; @Data public class SalesRecordData { @ExcelProperty(value = {"基本信息", "日期"}) private String date; @ExcelProperty(value = {"基本信息", "地区"}) private String region; @ExcelProperty(value = {"产品详情", "名称"}) private String productName; @ExcelProperty(value = {"产品详情", "数量"}) private Integer quantity; } ``` 此部分展示了如何通过注解的方式指定复杂的表头结构[^1]。 #### 编写控制器逻辑 接下来,在 Spring Boot 控制器中编写用于触发文件下载的方法。这里会根据请求参数动态调整 Excel 版本。 ```java import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class ExportController { @GetMapping("/export/sales-record") public void exportSalesRecord(@RequestParam String fileType) throws IOException { // 设置响应头信息以便浏览器识别为文件下载 HttpServletResponse response = ServletActionContext.getResponse(); response.setContentType("application/vnd.ms-excel"); response.setCharacterEncoding("utf-8"); // 判断后缀名决定输出哪种类型的 Excel 文件 if ("xls".equalsIgnoreCase(fileType)) { response.setHeader("Content-Disposition", "attachment;filename=sales_record.xls"); EasyExcel.write(response.getOutputStream()) .excelType(ExcelTypeEnum.XLS) .sheet("Sheet1") .doWrite(data()); } else { // 默认xlsx格式 response.setHeader("Content-Disposition", "attachment;filename=sales_record.xlsx"); EasyExcel.write(response.getOutputStream()) .sheet("Sheet1") .doWrite(data()); } } private List<SalesRecordData> data(){ List<SalesRecordData> list = new ArrayList<>(); for (int i = 0; i < 10; i++) { SalesRecordData record = new SalesRecordData(); record.setDate(LocalDate.now().toString()); record.setRegion("华东区"); record.setProductName("商品A-" + i); record.setQuantity(i * 100); list.add(record); } return list; } } ``` 上述代码片段实现了根据不同客户端的需求选择不同版本的 Excel 文件进行导出的功能[^4]。 #### 自动调整列宽与样式定制 为了让生成的 Excel 表格更加美观实用,还可以进一步优化表格外观。比如自动调整各列宽度以及应用统一的样式模板。 ```java // 在 write 方法调用前加入以下配置项 write(ServletOutputStream out).registerWriteHandler(new WidthAdjustmentListener()).autoCloseStream(false); // 或者单独注册样式处理器 write(ServletOutputStream out).registerWriteHandler(createTableStyle()); private WriteHandler createTableStyle() { HorizontalCellStyleStrategy strategy = new HorizontalCellStyleStrategy( contentRow -> {}, headerColumn -> {} ); return strategy; } class WidthAdjustmentListener implements WriteHandler { @Override public void sheet(int sheetNo, Sheet sheet){ sheet.setAutoWidth(true); } } ``` 这段代码说明了怎样利用监听器机制来自动生成适合内容显示的最佳列宽,并且提供了简单的样式控制接口[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值