You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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; 
}

关键逻辑说明

  1. 日期解析优化:

    • 优先判断单元格值是否为DateTime类型(EPPlus会自动解析Excel内置日期格式),直接提取日期部分。
    • 对字符串格式的日期,用DateTime.TryParseExact指定多种常见格式,提升兼容性,避免解析失败。
  2. 枚举转换逻辑:

    • 使用Enum.TryParse并开启ignoreCase: true,支持大小写不敏感转换(比如Excel中写"annual"也能匹配LeaveType.Annual)。
    • 若模型中LeaveType是byte类型,只需将枚举值强转为byte即可:(byte)leaveType。
  3. 错误处理与校验:

    • 加入try-catch捕获意外异常,用failedRows记录失败行号,方便后续排查或反馈给用户。
    • 对EmployeeId做非空校验,避免无效数据进入数据库。
  4. 细节修正:

    • 修正循环条件为row <= totalRows,避免漏掉最后一行数据。
    • 给Id赋值Guid.NewGuid(),解决数据库主键为空的问题。

内容的提问来源于stack exchange,提问作者Ayobamilaye

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 13:19:07