ASP.NET Core 6 Web API中使用EPPlus导入Excel时,如何转换日期格式与枚举对应值
解决EPPlus Excel上传中的日期与枚举类型转换问题
你遇到的核心问题是类型不匹配:StartDate/EndDate是DateTime类型,LeaveType是底层为byte的枚举,不能直接将字符串赋值给它们。下面是包含安全解析和错误处理的完整解决方案:
第一步:补全模型遗漏属性
先修正你的LeaveApplication模型——代码里赋值了LeaveType但原模型中没有这个属性,需要补充:
public class LeaveApplication { public Guid Id { get; set; } public string EmployeeId { get; set; } public DateTime StartDate { get; set; } public DateTime EndDate { get; set; } public PaymentStatus PaymentStatus { get; set; } // 补充对应属性,可选择枚举类型或byte类型(根据数据库存储需求) public EnumList.LeaveType LeaveType { get; set; } // 若数据库存byte类型,改为:public byte LeaveType { get; set; } }
第二步:修改Import方法,加入类型转换逻辑
下面是优化后的完整方法,包含日期解析、枚举转换和基础错误处理:
using System.Globalization; public async Task<List<LeaveApplication>> Import(IFormFile file) { var leaveApplications = new List<LeaveApplication>(); var failedRows = new List<int>(); // 记录解析失败的行号,方便后续排查 using (var stream = new MemoryStream()) { await file.CopyToAsync(stream); using (var package = new ExcelPackage(stream)) { ExcelWorksheet worksheet = package.Workbook.Worksheets[0]; var totalRows = worksheet.Dimension?.Rows ?? 0; var totalCols = worksheet.Dimension?.Columns ?? 0; // 修正循环条件:row <= totalRows,避免漏掉最后一行数据 for (int row = 2; row <= totalRows; row++) { try { // 1. 处理EmployeeId,先做非空校验 var employeeId = worksheet.Cells[row,1].Value?.ToString().Trim(); if (string.IsNullOrWhiteSpace(employeeId)) { failedRows.Add(row); continue; } // 2. 解析StartDate:兼容Excel直接返回的DateTime,或字符串格式 DateTime startDate; var startDateVal = worksheet.Cells[row,2].Value; if (startDateVal is DateTime dtStart) { startDate = dtStart.Date; // 只保留日期部分,剔除时间 } else { // 支持多种常见日期格式,可根据实际Excel格式调整 if (!DateTime.TryParseExact( startDateVal?.ToString().Trim(), new[] {"yyyy-MM-dd", "MM/dd/yyyy", "dd-MM-yyyy"}, CultureInfo.InvariantCulture, DateTimeStyles.None, out startDate)) { failedRows.Add(row); continue; } } // 3. 解析EndDate:逻辑同StartDate DateTime endDate; var endDateVal = worksheet.Cells[row,3].Value; if (endDateVal is DateTime dtEnd) { endDate = dtEnd.Date; } else { if (!DateTime.TryParseExact( endDateVal?.ToString().Trim(), new[] {"yyyy-MM-dd", "MM/dd/yyyy", "dd-MM-yyyy"}, CultureInfo.InvariantCulture, DateTimeStyles.None, out endDate)) { failedRows.Add(row); continue; } } // 4. 将LeaveType文本转换为枚举值(支持大小写不敏感) EnumList.LeaveType leaveType; var leaveTypeText = worksheet.Cells[row,4].Value?.ToString().Trim(); if (!Enum.TryParse<EnumList.LeaveType>(leaveTypeText, ignoreCase: true, out leaveType)) { failedRows.Add(row); continue; } // 若模型中LeaveType是byte类型,强转即可:(byte)leaveType // 添加到集合 leaveApplications.Add(new LeaveApplication { Id = Guid.NewGuid(), // 生成主键Guid,避免数据库主键为空报错 EmployeeId = employeeId, StartDate = startDate, EndDate = endDate, LeaveType = leaveType, PaymentStatus = PaymentStatus.Pending // 给PaymentStatus设置默认值 }); } catch (Exception ex) { failedRows.Add(row); // 可添加日志记录:_logger.LogError(ex, "解析第{Row}行数据失败", row); } } } } // 批量写入数据库(只有有效数据才执行) if (leaveApplications.Any()) { _dbContext.LeaveApplications.AddRange(leaveApplications); // 注意是LeaveApplications而非Countries await _dbContext.SaveChangesAsync(); } // 可根据failedRows做后续处理,比如返回错误行信息给前端 // if (failedRows.Any()) { /* 处理失败行逻辑 */ } return leaveApplications; }
关键逻辑说明
日期解析优化:
- 优先判断单元格值是否为
DateTime类型(EPPlus会自动解析Excel内置日期格式),直接提取日期部分。 - 对字符串格式的日期,用
DateTime.TryParseExact指定多种常见格式,提升兼容性,避免解析失败。
- 优先判断单元格值是否为
枚举转换逻辑:
- 使用
Enum.TryParse并开启ignoreCase: true,支持大小写不敏感转换(比如Excel中写"annual"也能匹配LeaveType.Annual)。 - 若模型中
LeaveType是byte类型,只需将枚举值强转为byte即可:(byte)leaveType。
- 使用
错误处理与校验:
- 加入
try-catch捕获意外异常,用failedRows记录失败行号,方便后续排查或反馈给用户。 - 对
EmployeeId做非空校验,避免无效数据进入数据库。
- 加入
细节修正:
- 修正循环条件为
row <= totalRows,避免漏掉最后一行数据。 - 给
Id赋值Guid.NewGuid(),解决数据库主键为空的问题。
- 修正循环条件为
内容的提问来源于stack exchange,提问作者Ayobamilaye
相关产品推荐
相关产品推荐

