为什么EPPlus在访问工作簿时抛出Null参考异常

时间:2019-04-26 20:57:44

标签: c# excel nullreferenceexception epplus

我正在C#.NET Core 2.2中进行编码。我正尝试在我的代码中用EPPlusCore替换Excel Interop,以确保可靠性和可移植性。我有使用EPPlus打开的一系列发票,但是其中一些在访问Excel软件包的Workbook属性时会引发“空引用”异常。

这仅在运行代码而不调试时发生。调试时,如果将鼠标悬停在ExcelPackage项上,它将刷新对工作簿的引用,并且我可以运行其余代码。

public object[,] GetExcelDataEpplus(string filePath, int index,
            bool sheetByName = false, string name = null, string password = null)
        {
            var remoteFileInfo = new FileInfo(filePath);

            if (!remoteFileInfo.Exists)
            {
                throw new Exception("File does not exist: " + filePath);
            }

            var currentPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "temp-excel");

            if (!Directory.Exists(currentPath))
            {
                Directory.CreateDirectory(currentPath);
            }

            var localFileInfo = new FileInfo(Path.Combine(currentPath, remoteFileInfo.Name));

            if (!localFileInfo.Exists)
            {
                File.Copy(filePath, localFileInfo.FullName);
            }

            object[,] values = null;
            try
            {
                if (!File.Exists(localFileInfo.FullName))
                {
                    _logger.LogInformation(DbLog, "Cannot find file : " + localFileInfo.FullName);
                    return null;
                }
                else
                {
                    _logger.LogInformation(DbLog, "Found file : " + localFileInfo.FullName);
                }

                _logger.LogInformation(DbLog, "Initializing EPPlus...");

                using (var package = string.IsNullOrEmpty(password)
                    ? new ExcelPackage(localFileInfo)
                    : new ExcelPackage(localFileInfo, password))
                {

                    _logger.LogInformation(DbLog, "Opening Workbook...");

                    //todo Error Thrown Here

                    try
                    {
                        package.Workbook.FormulaParserManager.LoadFunctionModule(new ImporterFunctionModule());
                    }
                    catch (Exception e)
                    {
                        _logger.LogWarning(DbLog, e, $"Could not load workbook : Loading file again...");

                        try
                        {
                            System.Threading.Thread.Sleep(1000);
                            package.Workbook.FormulaParserManager.LoadFunctionModule(new ImporterFunctionModule());
                        }
                        catch (Exception ex)
                        {
                            _logger.LogError(DbLog, ex, "Could not load workbook");
                            throw;
                        }
                    }

                    var workbook = package.Workbook;

                    _logger.LogInformation(DbLog, $"Calculating formulas...");

                    workbook.Calculate();

                    _logger.LogInformation(DbLog, "Finding Worksheet...");

                    var worksheet = sheetByName ? workbook.Worksheets.FirstOrDefault(x => x.Name == name) : workbook.Worksheets[index];

                    if (worksheet == null)
                    {
                        throw new Exception($"Could not find worksheet : {name}");
                    }

                    _logger.LogInformation(DbLog, $"Reading from worksheet : {worksheet.Name}...");


                    var start = worksheet.Dimension.Start;
                    var end = worksheet.Dimension.End;

                    values = worksheet.Cells[start.Row, start.Column, end.Row, end.Column].ToMultiDimensionalArray();
                }
            }
            catch (Exception e)
            {
                _logger.LogError(DbLog, e, $"GetExcelInvoiceDataEpplus from {filePath} ({localFileInfo.FullName})"); //todo propogate error
            }
            finally
            {
                File.Delete(localFileInfo.FullName);
            }

            var rowCount = values?.GetLength(0) ?? 0;
            _logger.LogInformation(DbLog, $"EPPLus found {rowCount} rows in the spreadsheet");
            return values;
        }

在大多数文件上,这可以正常工作,并且我从指定的工作表选项卡中获得了值的多维数组。但是,在某些文件上,它不起作用,我不知道为什么。

我能够找到的最接近的类似问题是:https://github.com/JanKallman/EPPlus/issues/416

但是,如果这是正确的话,我怎么不先访问工作簿就知道哪些工作表名称具有错误的引用?

1 个答案:

答案 0 :(得分:0)

我找到了解决方案。出现问题的excel文件大于平均文件。

解决方案是等待更长的时间。


try
{
    package.Workbook.FormulaParserManager.LoadFunctionModule(new ImporterFunctionModule());
}
catch (Exception e)
{
    for (var i=1; i < 6; i++)
    {
        _logger.LogWarning(DbLog, e, $"Could not load workbook : Loading file again (Attempt #{i})...");
        try
        {
            System.Threading.Thread.Sleep(2000);
            package.Workbook.FormulaParserManager.LoadFunctionModule(new ImporterFunctionModule());
            break;
        }
        catch (Exception ex)
        {
            if (i < 5) continue;

            _logger.LogError(DbLog, ex, "Could not load workbook after 5 attempts");
            throw;
        }
    }
}