通过EasyExcel设置自定义表头及设置特定单元格样式、颜色

前言

   在项目开发中,我们会遇到各种文件导出的开发场景,但是这种情况并都不常用,于是本人将自己工作中所用的代码封装成工具类,旨在记录工具类使用方法和技术分享。

实战代码

导出效果:

1、导入依赖

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

2、导出代码

	/**
	 * 导出打卡报表
	 *
	 * @param request  请求参数
	 * @param response 返回参数
	 */
	@PostMapping("/export")
	public void exportOaPersonOpenCardRecord(@RequestBody OaPersonOpenCardRecordRequest request, HttpServletResponse response) {
		List<OaPersonOpenCardRecord> oaPersonOpenCardRecordList = oaOpenCardRecordService.findOaPersonOpenCardRecordExportList(request);
		List<List<String>> headList = new ArrayList<>();
		try {
			// 设置动态头
			buildExportHead(oaPersonOpenCardRecordList, headList);
			// 获取动态数据
			List<List<Object>> exportList = new ArrayList<>();
			for (int i = 0; i < oaPersonOpenCardRecordList.size(); i++) {
				List<Object> valueList = new ArrayList<>();
				valueList.add(i + 1);
				valueList.add(oaPersonOpenCardRecordList.get(i).getUserName());
				valueList.add(oaPersonOpenCardRecordList.get(i).getOverWordCount());
				List<OaOpenCardInfo> oaOpenCardInfoList = oaPersonOpenCardRecordList.get(i).getOpenCardInfoList();
				oaOpenCardInfoList.forEach(oaOpenCardInfo -> {
					StringBuilder stringBuilder = new StringBuilder();
					if (StringUtils.isNotBlank(oaOpenCardInfo.getStartTime()) && request.getOpenTimeStatus() == 1) {
						stringBuilder.append(oaOpenCardInfo.getStartTime()).append("\n");
					}
					if (StringUtils.isNotBlank(oaOpenCardInfo.getEndTime()) && request.getOpenTimeStatus() == 1) {
						stringBuilder.append(oaOpenCardInfo.getEndTime()).append("\n");
					}
					if (StringUtils.isNotBlank(oaOpenCardInfo.getOpenCardStatus())) {
						stringBuilder.append(oaOpenCardInfo.getOpenCardStatus());
					}
					valueList.add(stringBuilder.toString());
				});
				exportList.add(valueList);
			}
			response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
			response.setCharacterEncoding("utf-8");
			String fileName = URLEncoder.encode("考勤报表", "UTF-8").replaceAll("\\+", "%20");
			response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
			EasyExcel.write(response.getOutputStream())
				.head(headList)
				.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
				.registerWriteHandler(new CellWriteHandler() {
					@Override
                    //设置特定样式
					public void afterCellDispose(CellWriteHandlerContext context) {
						Workbook workbook = context.getWriteWorkbookHolder().getWorkbook();
						CellStyle cellStyle = workbook.createCellStyle();
						// 设置换行
						cellStyle.setWrapText(true);
						// 设置表格内容垂直居中
						cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
						// 设置表格内容水平居中
						cellStyle.setAlignment(HorizontalAlignment.CENTER);
						// 设置带框线
						cellStyle.setBorderTop(BorderStyle.THIN);
						cellStyle.setBorderRight(BorderStyle.THIN);
						cellStyle.setBorderBottom(BorderStyle.THIN);
						cellStyle.setBorderLeft(BorderStyle.THIN);
						context.getCell().setCellStyle(cellStyle);
						if (BooleanUtils.isNotTrue(context.getHead())) {
							List<String> headNameList = context.getHeadData().getHeadNameList();
							String headName = headNameList.get(NumberConstant.ZERO);
							if (!headName.contains("考勤")) {
								return;
							}
							Cell cell = context.getCell();
							String stringCellValue = cell.getStringCellValue();
							if (!stringCellValue.contains("加班") && !stringCellValue.contains("正常") && !stringCellValue.contains("休息")) {
								//红色
								setCellStyle(context, IndexedColors.RED);
							} else if (stringCellValue.contains("加班")) {
								//绿色
								setCellStyle(context, IndexedColors.GREEN);
							}
						}
					}
				})
				.sheet("考勤报表").doWrite(exportList);

		} catch (Exception e) {
			log.error("导出失败", e);
		}
	}

	/***
	 * 设置特定单元格的颜色及字体
	 * @param context
	 * @param color
	 */
	private void setCellStyle(CellWriteHandlerContext context, IndexedColors color) {
		Workbook workbook = context.getWriteWorkbookHolder().getWorkbook();
		CellStyle oldCellStyle = context.getCell().getCellStyle();
		CellStyle newCellStyle = workbook.createCellStyle();
		// Copy existing style properties
		newCellStyle.cloneStyleFrom(oldCellStyle);
		// Set new font color
		Font font = workbook.createFont();
		font.setColor(color.getIndex());
		newCellStyle.setFont(font);
		// Apply new style
		context.getCell().setCellStyle(newCellStyle);
	}

	private static void buildExportHead(List<OaPersonOpenCardRecord> oaPersonOpenCardRecordList, List<List<String>> headList) {
		List<String> head0 = new ArrayList<>();
		head0.add("序号");
		List<String> head1 = new ArrayList<>();
		head1.add("姓名");
		List<String> head2 = new ArrayList<>();
		head2.add("晚上19:30以后打卡次数");
		headList.add(head0);
		headList.add(head1);
		headList.add(head2);
		if (!oaPersonOpenCardRecordList.isEmpty()) {
			List<OaOpenCardInfo> openCardInfoList = oaPersonOpenCardRecordList.get(0).getOpenCardInfoList();
			openCardInfoList.forEach(openCardInfo -> {
				List<String> head = new ArrayList<>();
				head.add("考勤");
				head.add(openCardInfo.getTitle());
				headList.add(head);
			});
		}
	}

实体类

package com.sansint.oa.param;

import com.sansint.oa.domain.OaPersonOpenCardRecord;
import lombok.Data;

/**
 * @author DJY
 * @date 2024/8/29
 */
@Data
public class OaPersonOpenCardRecordRequest extends OaPersonOpenCardRecord {

	/***
	 * 开始时间
	 */
	private String startDate;
	/***
	 * 结束时间
	 */
	private String endDate;
	/**
	 * 上班时间
	 */
	String startWorkTime = "";
	/**
	 * 下班时间
	 */
	String endWorkTime = "";
	/**
	 * 加班时刻
	 */
	String overWorkTime = "";

	/**
	 * 打开时间状态
	 */
	 Integer openTimeStatus;
}
package com.sansint.oa.domain;

import lombok.Data;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

/**
 * @author DJY
 * @date 2024/8/29
 */
@Data
public class OaPersonOpenCardRecord implements Serializable {
	private static final long serialVersionUID = 1L;
	/****
	 * 姓名
	 */
	private String userName;
	/****
	 * 晚上7.30以后打卡次数
	 */
	private long overWordCount;
	/***
	 * 考勤信息
	 */
	private List<OaOpenCardInfo> openCardInfoList;

	/***
	 * 考勤信息
	 */
	private Map<String,Object> openCardInfoMap;
}
package com.sansint.oa.domain;

import lombok.Data;

import java.io.Serializable;

/**
 * @author DJY
 * @date 2024/8/29
 */
@Data
public class OaOpenCardInfo implements Serializable {
	private static final long serialVersionUID = 1L;
	/****
	 * 姓名
	 */
	private String userName;
	/****
	 * 最早打卡时间
	 */
	private String startTime;
	/****
	 * 最晚打卡时间
	 */
	private String endTime;
	/****
	 * 标题
	 */
	private String title;
	/****
	 * 打卡状态
	 */
	private String openCardStatus;
	/****
	 * 打卡状态颜色
	 */
	private String openCardColor;
	/***
	 * 排序
	 */
	private Long sort;
}

### 实现 EasyExcel 自定义表头 #### 使用 `@ExcelProperty` 注解实现基本表头定制 对于基础的表头定制,可以通过使用 `@ExcelProperty` 注解来指定列名及其顺序。然而当面对不同维度下的动态变化需求时,仅依靠此注解难以满足灵活性的要求[^1]。 ```java public class DataModel { @ExcelProperty("固定字段一") private String fieldOne; @ExcelProperty("可变维度A/B/C") // 这里希望根据实际业务逻辑改变 private Integer dimensionValue; // getter and setter methods... } ``` #### 动态生成表头方案 针对上述提到的不同维度统计场景,推荐采用编程方式构建数据模型而非硬编码多个实体类。具体做法是在写入 Excel 前先组装好带有正确标题的数据集合: ```java // 定义一个通用的数据载体接口/抽象类 public abstract class DynamicHeaderData { public List<String> getHeaders(); // 返回当前实例对应的表头列表 } // 针对每种可能的变化情况创建具体的子类实现 public class SpecificDimension extends DynamicHeaderData { private final String fixedFieldLabel = "固定字段"; private final String dynamicDimenstionName; public SpecificDimension(String dimName){ this.dynamicDimenstionName=dimName; } @Override public List<String> getHeaders(){ return Arrays.asList(fixedFieldLabel, dynamicDimenstionName); } } ``` 接着,在执行导出操作之前,依据实际情况初始化相应的 `SpecificDimension` 对象并调用其 `getHeaders()` 方法获取即时所需的表头配置。 #### 应用样式策略以增强视觉效果 为了进一步美化输出文档,还可以利用 `HorizontalCellStyleStrategy` 或者其他类似的 API 来应用自定义格式化规则给整个工作簿或是特定区域内的单元格。这涉及到设置字体大小、背景色等外观特性[^2]。 ```java WriteCellStyle headWriteCellStyle = new WriteCellStyle(); headWriteCellStyle.setFillForegroundColor(IndexedColors.LIGHT_YELLOW.getIndex()); FontData fontData = new FontData(); fontData.setFontHeightInPoints((short) 14); // 设置字号为14磅 fontData.setBold(true); // 加粗显示文字 headWriteCellStyle.setWriteFont(fontData); // 创建水平方向上的样式策略 HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, null /* 默认正文无特殊样式 */); EasyExcel.write(fileName).registerWriteHandler(horizontalCellStyleStrategy)...build(); ``` 以上代码片段展示了如何设定头部样式的细节,并将其应用于即将被写出的工作薄上。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

瑞奇儿

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

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

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

打赏作者

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

抵扣说明:

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

余额充值