使用EasyExcel的模板导出复杂表头的Excel- 先单组数据填充,再多组数据填充

前言

最近接手一个需求,需要在现有项目中添加一个菜单栏目,其中有个导出excel的功能,但是格式相对有些复杂,有单组数据的显示,也有多组数据的显示,查了好多文章,都不是很明白.但是这篇文章和我的需求差不多非常相似(链接放在文末),根据这篇文章然后将自己的实现过程记录了下来,以防之后再用到.

这是我需要导出的excel格式
开头是单条数据的展示
之后是多条数据的展示
在这里插入图片描述

1.要想导出复杂的excel样式 需要用到自定义excel模板---->意思就是我们根据自己需要的excel格式,新建一个excel,然后将完整的格式先画出来,将固定的标题内容填好,单元格大小,背景色等等.
2.需要改变的数据用{}花括号包含起来
单个的数据直接{实体对应的属性名}例如:用户名{userName}密码{password}
多条数据{.实体对应的属性名} 例如: 时间{.date} 编号{.id} 加点.的意思就是显示多条数据
3.要注意:
如果一个excel文件中需要显示多个list.之前需要加标识,用来区分哪个数据是谁的.例如: 地址{list1.address}编号{list2.id}

这是我写的excel模板

因为我只需要一个list显示多条数据,所以我.之前没有加标识

在这里插入图片描述

导入依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>2.2.6</version>
</dependency>

前端

import { getParamString } from '/@/api/commn/common';
import { getAppEnvConfig } from '/@/utils/env';

enum Api {
  DOWNLOAD_OPERATIONAL = '/ldmp/report/download/operational',
}

const { VITE_GLOB_API_URL } = getAppEnvConfig();

export function exportOperationalListApi(params: any) {
  console.log('运营数据导出==' + getParamString(params));
  if (import.meta.env.DEV) {
    window.location.href = Api.DOWNLOAD_OPERATIONAL + getParamString(params);
  } else {
    window.location.href = VITE_GLOB_API_URL + Api.DOWNLOAD_OPERATIONAL + getParamString(params);
  }
}

后端

ExcelUtils (自己封装的easyExcel工具类)

public class ExcelUtils {
	/**
	 * 导出固定表头Excel
	 * Author wang.lch
	 * @param response
	 * @param list
	 * @param name
	 * @param sheetName
	 * @param model
	 * @throws Exception
	 */
	public static void exportExcel(HttpServletResponse response, List<? extends BaseRowModel> list,
								   String name, String sheetName, BaseRowModel model) throws Exception{
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm");
		String date = sdf.format(new Date());
		String fileName = new String(name.getBytes(), CommonConstants.UTF8) + date + ".xlsx";
		response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
		EasyExcel.write(response.getOutputStream(), model.getClass()).sheet(sheetName).doWrite(list);
	}

	/**
	 * 导出复杂表头的Excel 先单组数据填充,再多组数据填充
	 * @param response
	 * @param list 多组数据List
	 * @param map 单组数据Map
	 * @param outFileName 导出的Excel名称
	 * @param templateFileName Excel模板的路径名称
	 * @throws Exception
	 */
	public static void exportExcel(HttpServletResponse response, List<? extends BaseRowModel> list, Map<String,Object> map,
								   String outFileName, String templateFileName ) throws Exception{
		//告诉response下载的是excel文件
		response.setContentType("application/vnd.ms-excel");
		//告诉response使用utf-8编码格式
		response.setCharacterEncoding("utf-8");
		//.withTemplate(templateFileName)就是读取模板
		//.write(ExcelUtil.getOutputStream(outFileName, response))是将数据写入文件,并交给response
		ExcelWriter excelWriter = EasyExcel.write(ExcelUtils.getOutputStream(outFileName, response)).withTemplate(templateFileName).build();
		//创建Sheet
		//设置excel Sheet为第几张并设置名称
		//.writerSheet(0,"第一个")中前面的参数为sheetNo,就是第几张sheet
		//第二参数为sheet名称
		//不写就是默认
		WriteSheet writeSheet  = EasyExcel.writerSheet().build();
		// 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行,然后下面的数据往后移动。默认 是false,会直接使用下一行,如果没有则创建。
		// forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了,所以慎用
		// 简单的说 如果你的模板有list,且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
		//.direction(WriteDirectionEnum.VERTICAL)这个是设置list填入的时候是纵向填入
		FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.VERTICAL).forceNewRow(Boolean.FALSE).build();
		//这里是将list填充到excel中。
		//会去找模板上对应的数据填入,例如模板中的{list.getGoodsName}就是下面List集合中名为goodsName字段对应的数据
		//new FillWrapper("list", selectOrderDTO.getSelectOrderGoodsDTOS())前面的参数是设置一个填入的list名
		//后面的参数是获得的list,里面就包含了要填入的数据
		//.fill()主要就是将数据填入excel中
		excelWriter.fill(new FillWrapper(list), fillConfig, writeSheet);
		//这里是将一些普通数据放到map中,方便填入,可以看getStringObjectMap()。
		//map的String是对应的名称,Object就是数据了。
		//将数据填入
		excelWriter.fill(map, writeSheet);
		//关闭
		excelWriter.finish();
	}


	/**
	 * 这是ExcelUtil.getOutputStream
	 * 这里就是将文件下载交给了浏览器
	 * @return
	 */
	public static OutputStream getOutputStream(String Name, HttpServletResponse response) throws Exception {
		//这里是对文件的重命名
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm");
		String date = sdf.format(new Date());
		String fileName = new String(Name.getBytes(), CommonConstants.UTF8) + date + ".xlsx";
		// 这里文件名如果涉及中文一定要使用URL编码,否则会乱码
		response.setContentType("application/force-download");
		response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
		return response.getOutputStream();
	}
}

controller层

调用写好的工具类的 exportExcel 方法 参数: 第一个 response, 第二个list (需要在excel中显示的多条数据的list数据),第三个map (需要在excel中显示的单条数据的map), 第四个 outFileName (导出的excel的文件名)(文件名+时间) , 第五个templateFileName (自己建的excel模板路径)

需要显示的单条数据放在map
需要显示的多条数据放在list

/**
	 * 运营数据信息导出
	 *
	 * @return ApiResult
	 */
	@SysLog("运营数据信息导出")
	@ApiOperation(value = "运营数据信息导出")
	@GetMapping("/download/operational")
	public void downloadOperational(HttpServletResponse response, OperationalDataAnalyticalDto operationalDataAnalyticalDto) {
		try {
			List<OperationalDataAnalyticalModel> OperationalList = operationalDataAnalyticalService.operationalListModel(operationalDataAnalyticalDto);
			OperationalDataAnalyticalDto count = operationalDataAnalyticalService.getNoiseInfoCount(operationalDataAnalyticalDto);
			//创建map将查询的数据get后方在map中 一一对应excel模板中的属性名
			HashMap<String, Object> map = new HashMap<>();
			map.put("thisTimeInstallCount", count.getThisTimeInstallCount());
			map.put("addInstallCount", count.getAddInstallCount());
			map.put("nowLeaveCount", count.getNowLeaveCount());
			map.put("installDateStar", count.getInstallDateStar());
			map.put("installDateEnd", count.getInstallDateEnd());
			map.put("district", count.getDistrict());
			map.put("isLeakCount", count.getIsLeakCount());
			map.put("isDoubtCount", count.getIsDoubtCount());
			map.put("isNormalCount", count.getIsNormalCount());
			map.put("isOfflineCount", count.getIsOfflineCount());
			//excel模板路径
			String templateFileName = "/opt/services/file/OperationalTemplate.xlsx";
			System.out.println(templateFileName);
			ExcelUtils.exportExcel(response, OperationalList, map, FileName.OPERATIONAL_INFO, templateFileName);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

serviceImpl层

想要对查询的数据先一步进行处理,可以在serviceImpl中编写

	/**
	 * 导出噪声设备拆装历史信息列表信息导出
	 *
	 * @return List<OperationalDataAnalyticalModel>
	 */
	@Override
	public List<OperationalDataAnalyticalModel> operationalListModel(OperationalDataAnalyticalDto operationalDataAnalyticalDto){
		return baseMapper.getOperationalExcel(operationalDataAnalyticalDto);
		//对查询的数据进行复杂的处理
	}

结果展示:
在这里插入图片描述

参考文章:https://blog.csdn.net/weixin_44459007/article/details/115555795?

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暴走的山交

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值