VB.NET 读取后释放 Excel 文件以便覆盖

VB.NET Releasing Excel file after reading so it can be overwritten

我遇到的问题和我之前的许多人遇到的问题一样,我发现了几个关于这个问题的话题,但我对他们的修复程序的应用没有产生任何变化。

我正在读取一个 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

这是保存块(这是生成 "File in Use" 错误的代码):

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(),它们会去哪里?

非常感谢您的帮助,并深表歉意,因为我无法成功实施来自类似主题的其他答案。

您需要编组以释放 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 文件扩展名是错误的...

普通连接字符串:(适用于 xls 文件)

"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=\"Excel 8.0;HDR=是;\""

Office 2007 连接字符串:(适用于 xlsx 文件)

"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0;HDR=是;\""

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

我的 OleDB 连接的连接字符串需要添加花絮:OLE DB Services = -4 禁用连接池。碰巧的是,当连接关闭时,连接并没有被释放(这是最初的假设),而是将连接转储回池中。

另一个论坛建议 OLE DB Services = -2 应该做同样的事情,但在我的实例中没有效果。它可能因版本而异,但我还没有对此进行研究以得出某些结论(或某个论坛中有人输入错误)

我的程序中不需要更多代码来转储 OleDB 连接对文件的保留。 MyConnection = Nothing 和排干水池的管道,然后是 GC.Collect 也被推荐,但没有解决我的症状。

感谢大家的意见