VB.NET读取后释放Excel文件,可以覆盖它

时间:2015-03-15 00:32:12

标签: vb.net excel datagridview garbage-collection oledb

我遇到的问题与我之前的许多问题相同,而且我已经找到了几个关于这个问题的线程,但我的修复程序的应用并没有产生任何变化。

我正在阅读一个excel文件并用它填充DataGridView。很简单,用户可以修改它然后保存它。与其他线程一样,问题是程序对文件有如此严格的控制,我无法覆盖它。

在提供的众多修复程序中,垃圾收集是最常提到的,但我的结果没有变化。我尝试过处理OLEDB连接,命令,适配器和数据集也没有成功。

我已经运行了几个不同的示例和教程来编写这个程序,所以如果需要这些修复,我显然已经在错误的位置实现了它们。

这是在表单加载时发生的读取块(我已经删除了所有我修复它以整理代码的尝试):

Private Sub Inventory_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    Using MyConnection = New System.Data.OleDb.OleDbConnection("provider=Microsoft.Jet.OLEDB.4.0;Data Source='c:\AllTrade\Inventory.xlsx';Extended Properties=Excel 8.0;")
        Using MyCommand = New System.Data.OleDb.OleDbDataAdapter("select * from [InventorySheet$]", MyConnection)
            DtSet = New System.Data.DataSet
            MyCommand.Fill(DtSet)
            InventoryGridView.DataSource = DtSet.Tables(0)
            MyConnection.Close()
        End Using
    End Using
End Sub

以下是保存块(这是生成“正在使用的文件”错误的代码):

Private Sub UpdateInventory_Click(sender As Object, e As EventArgs) Handles UpdateInventory.Click

    Dim ExcelApp As New Excel.Application()
    ExcelApp.Application.Workbooks.Add(Type.Missing)

    For i As Integer = 0 To InventoryGridView.Rows.Count - 1
        Dim row As DataGridViewRow = InventoryGridView.Rows(i)
        For j As Integer = 0 To row.Cells.Count - 1
            ExcelApp.Cells(i + 1, j + 1) = row.Cells(j).Value
        Next
    Next

    ExcelApp.ActiveWorkbook.SaveAs("C:\Alltrade\Inventory.xlsx")
    ExcelApp.ActiveWorkbook.Saved = True
    ExcelApp.Quit()

End Sub

放弃文件的诀窍是什么?如果需要GC.Collect()GC.WaitForPendingFinalizers(),他们会去哪里?

我感谢任何帮助并道歉,因为我无法从类似的线程成功实现其他答案。

2 个答案:

答案 0 :(得分:0)

您需要编组以释放COM对象:ExcelApp ...

 Private Sub ReleaseObject(ByVal obj As Object)
Try
    Dim intRel As Integer = 0
    Do
        intRel = System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
    Loop While intRel > 0
Catch ex As Exception
    MsgBox("Error releasing object" & ex.ToString)
    obj = Nothing
Finally
    GC.Collect()
End Try
 End Sub

您可以在子资源的末尾调用此方法。

 ReleaseObject(ExcelApp)

你可以在这里获得更多Excel application not quitting after calling quit

<强> 修改

我还注意到你的连接字符串对于较新的.xlxs文件扩展名是错误的......

正常ConnectionString :(适用于xls文件)

“Provider = Microsoft.Jet.OLEDB.4.0;数据源= {0};扩展属性= \”Excel 8.0; HDR = YES; \“”

Office 2007 ConnectionString :(适用于xlsx文件)

“Provider = Microsoft.ACE.OLEDB.12.0;数据源= {0};扩展属性= \”Excel 12.0; HDR = YES; \“”

答案 1 :(得分:0)

经过大量研究和挫折,我找到了解决方案。

我的OleDB连接的连接字符串需要添加的tidbit:OLE DB Services = -4,它会禁用连接池。实际上,当连接关闭时,连接不会被丢弃(这是初始假设),而是将连接转储回池中。

另一个论坛建议OLE DB Services = -2应该做同样的事情,但在我的实例中没有效果。它可能因版本不同而有所不同,但我没有研究过这一点,以确定某些(或某个论坛中的某人被打错)

我的程序中不需要进一步的代码来转储OleDB连接对文件的保留。 MyConnection = Nothing以及排除合并后跟GC.Collect的行也被推荐但未解决我的症状。

感谢大家的输入