ASP.NET 核心应用中的第二次读取 NPOI 失败

NPOI fails on second read in ASP.NET Core app

在我的 ASP.NET 核心应用程序中,我正在使用 NPOI 读取 Excel 文件。工作簿是这样创建的:

public void ImportFile()
{    
    using var fileStream = new FileStream("path_to_file.xlsm", FileMode.Open,
            FileAccess.Read, FileShare.ReadWrite);
    var workbook = WorkbookFactory.Create(fileStream);

    // all the reads and persistence stuff
}

所有读取都是这样执行的:

public static DateTime ReadDateTimeAt(IRow row, int columnIndex)
    {
        var cell = row.GetCell(columnIndex, MissingCellPolicy.CREATE_NULL_AS_BLANK);
        try
        {
            return cell.DateCellValue;
        }
        catch
        {
            // handling logic
        }
    }

第一次调用方法 ImportFile() 时一切正常。然后,对它的每次后续调用都会导致错误 - NullReferenceExceptioncell.DateCellValue 抛入 ReadDateTimeAt 函数。只有重新启动整个应用程序才有帮助。

为什么可以呢?我是不是没有正确地释放一些资源(我想我这样做了,但我认为我应该释放的唯一一个是 FileStream,它被打包在 using 中 - 我还检查了 ResourceManager 和文件调用之间不访问)?

我真的分不清哪个参考文献是 null它不是 Cell 对象本身 - 我可以通过调试器访问它的属性。整个工作簿似乎也已正确加载(同样,通过调试器访问它)。

如果相关,读取失败的单元格将引用另一个 Sheet 上的单元格,其类型设置为日期。

On the first call to method ImportFile() it all works just fine. Then, each subsequent call to it results in an error - NullReferenceException is thrown in ReadDateTimeAt function by cell.DateCellValue. Only restart of the whole app helps.

我确实重现了你的错误。这应该是NPOI的内部错误。

可以使用以下方法解决

 public static string GetStringValue(ICell cell)
        {
            switch (cell.CellType)
            {
                case CellType.Numeric:
                    if (DateUtil.IsCellDateFormatted(cell))
                    {
                        return DateTime.FromOADate(cell.NumericCellValue).ToString();
                        //try
                        //{
                        //    return cell.DateCellValue.ToString();
                        //}
                        //catch (NullReferenceException)
                        //{
                        //    return DateTime.FromOADate(cell.NumericCellValue).ToString();
                        //}
                    }
                    return cell.NumericCellValue.ToString();

                case CellType.String:
                    return cell.StringCellValue;

                case CellType.Boolean:
                    return cell.BooleanCellValue.ToString();

                default:
                    return string.Empty;
            }
        }

ReadDateTimeAt 方法:

public static DateTime ReadDateTimeAt(IRow row, int columnIndex)
        {
            var cell = row.GetCell(columnIndex, MissingCellPolicy.CREATE_NULL_AS_BLANK); 
            return DateTime.Parse(GetStringValue(cell));

        }