【问题标题】:C# Application.Excel.Quit Not functioning because of 1 line of codeC# Application.Excel.Quit 由于 1 行代码而无法运行
【发布时间】:2016-05-26 12:09:16
【问题描述】:

所以我有以下代码。如果我注释掉该行,它应该可以正常工作,但是一旦我取消注释该行 Excel 将无法正常关闭。

我不确定接下来要尝试什么。我远离 2 点问题,并试图坚持 1 点。但现在我不确定现在该怎么办。

代码中的 dt 是我正在填充的 DataTable。

Excel.Application app = null;
        Excel.Workbooks books = null;
        Excel.Workbook book = null;
        Excel.Sheets sheets = null;
        Excel.Worksheet sheet = null;
        Excel.Range range = null;

        try
        {
            app = new Excel.Application();
            books = app.Workbooks;
            book = books.Open(FilePath);
            sheets = book.Sheets;
            sheet = book.ActiveSheet;

            int rcount = 45;
            UpdateProgressBarMaxMethod(pbAssets, rcount);

            int i = 0;

            for (; i < rcount; i++)
            {
                //Comment out the below line and it works fine
                dt.Rows.Add(sheet.Cells[i + 1, 1].Value, 
                    sheet.Cells[i + 1, 2].Value, 
                    sheet.Cells[i + 1, 3].Value, 
                    sheet.Cells[i + 1, 4].Value, 
                    sheet.Cells[i + 1, 5].Value, 
                    sheet.Cells[i + 1, 6].Value, 
                    sheet.Cells[i + 1, 7].Value, 
                    sheet.Cells[i + 1, 8].Value, 
                    sheet.Cells[i + 1, 9].Value);

                UpdateProgressBarMethod(pbAssets, i);
            }
            UpdateProgressBarMethod(pbAssets, 0);
            book.Close();
            app.Quit();
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
        }
        finally
        {
            if (range != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(range);
            if (sheet != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(sheet);
            if (sheets != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(sheets);
            if (book != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(book);
            if (books != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(books);
            if (app != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
        }

【问题讨论】:

  • 对不起,我会解释更多。 DT 是一个数据表
  • 我假设您已正确初始化数据表。然后,是单元格的内容(至少其中一个)与数据表列类型的类型不匹配。
  • 是不是因为您在sheet.Cells[i + 1, 2].Value 上使用了“2 个点”,因此没有清理对sheet.Cells[i + 1, 2] 返回的Range 的引用?
  • 是的,我已初始化 DataTable 并正常工作。运行此代码时唯一无法正常工作的部分是关闭 excel。但如果我评论那条线。 Excel 可以正常运行和关闭。
  • @petelids 我什至没有想到这一点。但不确定需要做什么清理......因为我仍然在释放对象。还剩下什么?

标签: c# excel


【解决方案1】:

您实际上并没有遵循两点规则。 sheet.Cells[i + 1, 2].Value - 那是两个点。它创建对Range 对象(单元格)的引用。

显然,为每个单元格创建和清理 Range 对象是一件很痛苦的事情。 This link 展示了如何创建 one Range 并将值读入数组。

另一个选择是根本不使用Excel.Interop,因为处理所有这些 COM 对象会非常痛苦。

Here's a link 加上EPPlus 的一些代码,在没有 COM 对象的情况下也能做同样的事情。还有一些关于使用命名范围的建议,这样您就不必处理所有这些行号和列号。

【讨论】:

  • 我希望人们不要再传播关于使用 ReleaseComObject 和“两点规则”的坏建议。有人说去试试这个,每个人都复制了那个例子,但这不是处理它的正确方法。见this post from the visual studio team。真正需要做的就是让 GC 收集您的对象,有关如何执行此操作的正确说明,请参阅this answer
  • 非常有趣。在那种情况下,那里有大量的不良信息,其中大部分在 MSDN 上。如果我真的必须使用Excel.Interop,我会更加担心。但在我看来,它的存在只是因为 Excel 几年前还不是 XML 格式。既然是这样,我敦促任何愿意倾听的人甚至不要打扰自动化 Excel。我觉得很烦人的是,a) 来自 Microsoft 和 b) 被认为是正常做法的建议与 Microsoft 在其他地方相矛盾。没有多少人会忽略 MS 文档并注意 其他 MS 文档。
  • 虽然 GC.Collect 和一切都在工作。我离开了 Excel.Interop。并将加载数据的结果加快 10 倍。谢谢
【解决方案2】:

Essential XlsIO 可以将数据从 Excel 导入 Datatable。

Example code

//The first worksheet object in the worksheets collection is accessed.
IWorksheet sheet = workbook.Worksheets[0];
//Get as DataTable
DataTable datatable = sheet.ExportDataTable(sheet.UsedRange, ExcelExportDataTableOptions.ColumnNames);
//Upload to dataset
DataSet ds = new DataSet();
ds.Tables.Add(datatable);

如果您符合条件(收入低于 100 万美元),整套控件可通过community license 计划免费获得(也可用于商业应用)。社区许可证是没有限制或水印的完整产品。

注意:我为 Syncfusion 工作。

【讨论】:

    猜你喜欢
    • 2021-09-03
    • 2021-06-15
    • 1970-01-01
    • 1970-01-01
    • 2019-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多