解析excel电子表格时,对象引用未设置为对象的实例

时间:2015-02-26 21:28:16

标签: c# sql office-interop import-from-excel

我从excel方法编写了我自己的导入,用于我公司用于显示商店中不同部门的预算的Excel工作表。我从表中得到的所有关注的是与我们部门的日期和预算相关的两个栏目。

public static string[][] ImportBudgets(string filename)
{
    var xlApp = new Application();
    var xlWorkBook = xlApp.Workbooks.Open(filename, 0, true, 5, "", "", true, XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
    var xlWorkSheet = (Worksheet)xlWorkBook.Worksheets.Item[1];
    var range = xlWorkSheet.UsedRange;

    var budgetsArray = new string[range.Rows.Count][];

    // loop through excel spreadsheet and get data
    for (var rCnt = 3; rCnt <= range.Rows.Count; rCnt++)
    {
        var budgetDate = (string)((Range)range.Cells[rCnt, 1]).Value2;
        var budgetAmount = (decimal)((Range)range.Cells[rCnt, 8]).Value2;
        budgetsArray[rCnt - 3] = new[] { budgetDate, budgetAmount.ToString(CultureInfo.CurrentCulture) };
    }

    // cleanup 
    xlWorkBook.Close(true, null, null);
    xlApp.Quit();

    Marshal.ReleaseComObject(xlWorkSheet);
    Marshal.ReleaseComObject(xlWorkBook);
    Marshal.ReleaseComObject(xlApp);

    return budgetsArray;
}

public string ImportBudgets(string filename)
{
    try
    {
        // get dates and budgets from excel in array
        var budgets = CExcel.ImportBudgets(filename);

        using (var oDc = new StatTrackerTablesDataContext())
        {
            foreach (var innerArray in budgets)
            {
                var budget = new tblBudget();
                DateTime budgetdate;
                if (DateTime.TryParse(innerArray[0], out budgetdate) != true) continue;
                budget.Budget_ID = Guid.NewGuid();
                budget.Budget_Date = budgetdate;
                budget.Budget_Amount = decimal.Parse(innerArray[1]);
                budget.Budget_Goal = decimal.Parse(innerArray[1]) * (decimal)1.1;

                oDc.tblBudgets.InsertOnSubmit(budget);
                oDc.SubmitChanges();
            }
        }
        return "Budgets imported without problems.";
    }
    catch (SqlException ex)
    {
        if (ex.Number == 2627)
        {
            return "Budget already existed for a date in batch. Import aborted.";
        }
        else
        {
            return ex.Message;
        }
    }
    catch (Exception ex)
    {
        if (ex.Message.Contains("Object reference not set to an instance of an object."))
            return "Budgets imported without problems.";
        return ex.Message;
    }
}

导入将正确运行并导入所有日期和预算,但在最后一个正确填充之后到达行后将始终具有空对象。我引入了对象引用消息的错误处理,但如果导入过程确实存在问题,那显然不是一个好策略。我只是看到是否有人可以帮助我改进它以防止消息发生。

1 个答案:

答案 0 :(得分:0)

好吧,我有一段时间没有访问过此代码,因为它确实完成了工作。这只是解决方法,我不喜欢在那里避免错误消息。我注意到我为数组确定了excel文档的整个行数,但该文档包含未针对预算进行解析的行,因为它们不是实际日期。每个文档有2-3行被跳过,因为“日期”列表示类似“第2周”的内容。这导致预算数组有2-3个null innerArrays,我的辅助预算导入方法将尝试解析空数组。我想代码:

if (DateTime.TryParse(innerArray[0], out budgetdate) != true) continue;

会使数组不被解析,但忽略了在返回false之前抛出异常的事实。我刚刚添加了

 if (innerArray == null) continue;

在foreach循环的开头,现在它导入而不需要

catch (Exception ex)
{
    if (ex.Message.Contains("Object reference not set to an instance of an object."))
        return "Budgets imported without problems.";
    return ex.Message;
}