如何在Spring Boot中提取Excel列数据并实现员工周工时统计及邮件提醒
Spring Boot 实现Excel工时统计与异常推送方案
一、依赖引入
核心功能涉及Excel解析、定时任务、邮件推送三个模块,推荐依赖如下(Maven示例):
<!-- EasyExcel:内存占用低,适合解析大体积Excel --> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.3.2</version> </dependency> <!-- Spring官方邮件依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency>
定时任务直接使用Spring自带的@Scheduled注解即可,无需额外引入依赖。
二、5个工作日工时提取逻辑
要准确统计周工时,按以下步骤处理即可:
- 先定义Excel映射实体,至少包含员工ID、员工姓名、考勤日期、当日工时四个核心字段
- 读取Excel全量月度工时数据后,按「员工ID + 周起始日期」做分组,周起始日期可以取当周周一作为唯一标识
- 每个分组内过滤出周一到周五的工作日数据:通过
LocalDate.getDayOfWeek()判断,排除值为SATURDAY、SUNDAY的行 - 对过滤后的5天工时求和,判断总和是否小于40,符合条件的归入异常待推送名单
注意:如果Excel本身已剔除周末数据,直接按周分组求和即可,仅需额外校验每个分组的有效数据条数是否为5,避免节假日等特殊场景导致统计错误。
三、核心代码示例
1. Excel映射实体类
@Data public class EmployeeWorkHour { @ExcelProperty("员工ID") private String empId; @ExcelProperty("姓名") private String empName; @ExcelProperty(value = "考勤日期", converter = LocalDateConverter.class) private LocalDate attendanceDate; @ExcelProperty("当日工时") private BigDecimal workHour; }
2. 工时统计核心方法
public List<Map<String, Object>> getAbnormalEmpList(String excelPath) { // 读取Excel全量数据 List<EmployeeWorkHour> allData = EasyExcel.read(excelPath) .head(EmployeeWorkHour.class) .sheet() .doReadSync(); // 按员工+周维度分组 Map<String, List<EmployeeWorkHour>> weekGroupMap = allData.stream() .collect(Collectors.groupingBy(data -> { // 取当周周一作为周唯一标识 LocalDate weekStart = data.getAttendanceDate() .with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); return data.getEmpId() + "_" + weekStart; })); List<Map<String, Object>> abnormalList = new ArrayList<>(); for (Map.Entry<String, List<EmployeeWorkHour>> entry : weekGroupMap.entrySet()) { // 过滤工作日并求和 BigDecimal totalHour = entry.getValue().stream() .filter(d -> !d.getAttendanceDate().getDayOfWeek().equals(DayOfWeek.SATURDAY) && !d.getAttendanceDate().getDayOfWeek().equals(DayOfWeek.SUNDAY)) .map(EmployeeWorkHour::getWorkHour) .reduce(BigDecimal.ZERO, BigDecimal::add); // 筛选工时不足40小时的员工 if (totalHour.compareTo(new BigDecimal(40)) < 0) { Map<String, Object> item = new HashMap<>(); item.put("empId", entry.getValue().get(0).getEmpId()); item.put("empName", entry.getValue().get(0).getEmpName()); item.put("weekTotalHour", totalHour); item.put("weekStart", entry.getKey().split("_")[1]); abnormalList.add(item); } } return abnormalList; }
3. 每周一邮件推送实现
首先在application.yml中配置邮件参数:
spring: mail: host: smtp.xxx.com username: 发件人邮箱 password: 邮箱授权码 port: 465 properties: mail: smtp: ssl: enable: true
定时任务代码:
@Component @Slf4j public class WorkHourPushTask { @Resource private JavaMailSender javaMailSender; // cron表达式:每周一上午9点执行 @Scheduled(cron = "0 0 9 ? * MON") public void pushAbnormalList() { // 调用统计方法获取异常名单,excel路径填你本地硬编码的固定路径 List<Map<String, Object>> abnormalList = getAbnormalEmpList("/xxx/月度工时表.xlsx"); // 构造邮件内容 SimpleMailMessage message = new SimpleMailMessage(); message.setFrom("发件人邮箱"); message.setTo("收件人邮箱"); message.setSubject("上周工时不足40小时员工明细"); String content = abnormalList.stream() .map(item -> "员工ID:" + item.get("empId") + ",姓名:" + item.get("empName") + ",周总工时:" + item.get("weekTotalHour")) .collect(Collectors.joining("\n")); message.setText("上周工时不足40小时的员工明细如下:\n" + content); javaMailSender.send(message); } }
最后在Spring Boot启动类上添加@EnableScheduling注解开启定时任务功能即可。
四、额外优化点
- 如果需要排除法定节假日,可提前维护节假日列表,过滤逻辑额外排除节假日日期即可
- 可添加Excel读取异常捕获逻辑,避免文件格式错误导致任务执行失败
内容的提问来源于stack exchange,提问作者rubysunn
相关产品推荐
相关产品推荐

