将 Datagridview 复制到 excel - 使 excel 进程保持打开状态

Copying Datagridview to excel - leaves excel process open

谁能指出是什么导致 excel 进程在我的代码完成后保持打开状态?

我已经研究了关于这个主题的所有内容,重点似乎是避免使用 excel 互操作的 3 个点,但我相信我已经做到了,但我仍然看不到我在哪里出错了。

我的过程是将datagridview复制到剪贴板,然后粘贴到新创建的excel文件中,保存,关闭excel,然后给用户一个打开的选项文件。

两种情况。首先,当我 运行 通过代码并且不打开 excel 文件时,它使进程保持打开状态。其次,如果我打开工作簿然后关闭工作簿,它不会留下进程 运行ning。我不明白其中的区别,因为工作簿的打开是在我尝试关闭并释放对 excel.

的所有引用之后发生的
    Private Sub CopyDGVtoClipBoard()
    Me.DataGridView1.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText
    Me.DataGridView1.RowHeadersVisible = False
    Me.DataGridView1.SelectAll()
    Dim dataObj As DataObject = Me.DataGridView1.GetClipboardContent
    If dataObj IsNot Nothing Then
        Clipboard.SetDataObject(dataObj)
    End If
    Me.DataGridView1.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableWithAutoHeaderText
    Me.DataGridView1.RowHeadersVisible = True
    Me.DataGridView1.ClearSelection()
End Sub

Private Sub ExportToExcel()
    If Me.DataGridView1.Rows.Count < 1 Then Exit Sub
    CopyDGVtoClipBoard()             

    SaveFileDialog1.Filter = "Excel File|*.xlsx"
    SaveFileDialog1.Title = "Save In"
    SaveFileDialog1.FileName = "Generic name"

    If SaveFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then

            If SaveFileDialog1.FileName <> "" Then
            Dim xlExcel As excel.Application
            Dim xlWorkBooks As excel.Workbooks
            Dim xlWorkBook As excel.Workbook
            Dim xlWorkSheet As excel.Worksheet
            Dim CR As excel.Range
            Dim misValue As Object = System.Reflection.Missing.Value

            xlExcel = New excel.Application
            xlExcel.Visible = True
            xlWorkBooks = xlExcel.Workbooks
            xlWorkBook = xlWorkBooks.Add(misValue)
            xlWorkBook.Application.DisplayAlerts = False
            xlWorkSheet = xlWorkBook.ActiveSheet
            CR = xlWorkSheet.Cells(1, 1)
            CR.Select()
            xlWorkSheet.PasteSpecial(CR, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, True)
            xlWorkBook.SaveAs(SaveFileDialog1.FileName())
            xlWorkBook.Close(False)

            misValue = Nothing
            ReleaseExcel(CR)
            ReleaseExcel(xlWorkSheet)
            ReleaseExcel(xlWorkBook)
            ReleaseExcel(xlWorkBooks)
            xlExcel.Quit()
            ReleaseExcel(xlExcel)

            Dim OpenCheck As MsgBoxResult = MsgBox("Would you like to open the file?", MsgBoxStyle.YesNo, "Open File")
            Dim fPath As String = SaveFileDialog1.FileName
            If OpenCheck = MsgBoxResult.Yes Then
                Process.Start(fPath)
            End If
        End If
   End If

    Private Sub ReleaseExcel(ByVal O As Object)
    Do While System.Runtime.InteropServices.Marshal.ReleaseComObject(O) >= 0
        System.Runtime.InteropServices.Marshal.ReleaseComObject(O)
    Loop
    O = Nothing
End Sub

我已将问题缩小到以下代码。如果除了指定范围和添加数据之外我做了所有事情,它会关闭并结束进程但是一旦我引用 CR = xlWorkSheet.Cells(1,1) 它就会挂起一个进程

            CR = xlWorkSheet.Cells(1, 1)
        CR.Select()
        xlWorkSheet.PasteSpecial(CR, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, True)

编辑 因此,我将我的代码与 Karen 发布的代码进行了比较,并对我的代码进行了一些细微的调整(完整代码加上下面列出的更改),但由于某种原因,它可以工作并且不会让进程处于打开状态!不确定如何,但我会接受。

Private Sub CopyDGVtoClipBoard()
    Me.DataGridView1.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText
    Me.DataGridView1.RowHeadersVisible = False
    Me.DataGridView1.SelectAll()
    Dim dataObj As DataObject = Me.DataGridView1.GetClipboardContent
    If dataObj IsNot Nothing Then
        Clipboard.SetDataObject(dataObj)
    End If
    Me.DataGridView1.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableWithAutoHeaderText
    Me.DataGridView1.RowHeadersVisible = True
    Me.DataGridView1.ClearSelection()
End Sub

Private Sub ExportToExcel()
    If Me.DataGridView1.Rows.Count < 1 Then Exit Sub
    CopyDGVtoClipBoard()

    Dim DateCon As DateTime = DateTime.ParseExact(Today.ToShortDateString, "M/d/yyyy", Nothing)


    SaveFileDialog1.Filter = "Excel File|*.xlsx"
    SaveFileDialog1.Title = "Save In"
    SaveFileDialog1.FileName = "Generic Name"

    If SaveFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
        If SaveFileDialog1.FileName <> "" Then
            Dim xlExcel As excel.Application = Nothing
            Dim xlWorkBooks As excel.Workbooks = Nothing
            Dim xlWorkBook As excel.Workbook = Nothing
            Dim xlWorkSheet As excel.Worksheet = Nothing
            Dim CR As excel.Range = Nothing
            Dim misValue As Object = System.Reflection.Missing.Value

            xlExcel = New excel.Application
            xlExcel.Visible = False
            xlExcel.DisplayAlerts = False

            xlWorkBooks = xlExcel.Workbooks
            xlWorkBook = xlWorkBooks.Add(misValue)

            xlWorkSheet = xlWorkBook.ActiveSheet
            CR = xlWorkSheet.Range("A1")
            CR.PasteSpecial(excel.XlPasteType.xlPasteAll)
            CR.Select()
            xlWorkBook.SaveAs(SaveFileDialog1.FileName)
            Clipboard.Clear()

            ReleaseExcel(CR)
            CR = Nothing
            ReleaseExcel(xlWorkSheet)
            xlWorkSheet = Nothing
            xlWorkBook.Close(False)
            ReleaseExcel(xlWorkBook)
            xlWorkBook = Nothing
            ReleaseExcel(xlWorkBooks)
            xlWorkBooks = Nothing
            xlExcel.Quit()
            ReleaseExcel(xlExcel)
            xlExcel = Nothing

            Dim OpenCheck As MsgBoxResult = MsgBox("Would you like to open the file?", MsgBoxStyle.YesNo, "Open File")
            Dim fPath As String = SaveFileDialog1.FileName
            If OpenCheck = MsgBoxResult.Yes Then
                Process.Start(fPath)
            End If

        End If
    End If

End Sub

Private Sub ReleaseExcel(ByVal O As Object)
    Try
        Do Until System.Runtime.InteropServices.Marshal.FinalReleaseComObject(O) = 0
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(O)
        Loop
    Catch ex As Exception
    Finally
        GC.Collect()
        GC.WaitForPendingFinalizers()
    End Try
End Sub

以下仅使用两个点。工作完成后excel妥善处理。

Option Strict On
Option Infer Off
Imports Excel = Microsoft.Office.Interop.Excel
Imports Microsoft.Office
Imports System.Runtime.InteropServices
Module Demo1
    Public Sub DoPaste()
        Dim FileName As String = IO.Path.Combine(Application.StartupPath, "SomeFile.xlsx")

        Dim SheetName As String = "Sheet1"

        Dim Proceed As Boolean = False
        Dim xlApp As Excel.Application = Nothing
        Dim xlWorkBooks As Excel.Workbooks = Nothing
        Dim xlWorkBook As Excel.Workbook = Nothing
        Dim xlWorkSheet As Excel.Worksheet = Nothing
        Dim xlWorkSheets As Excel.Sheets = Nothing
        Dim xlCells As Excel.Range = Nothing

        xlApp = New Excel.Application
        xlApp.DisplayAlerts = False
        xlWorkBooks = xlApp.Workbooks
        xlWorkBook = xlWorkBooks.Open(FileName)

        xlApp.Visible = False

        xlWorkSheets = xlWorkBook.Sheets

        For x As Integer = 1 To xlWorkSheets.Count
            xlWorkSheet = CType(xlWorkSheets(x), Excel.Worksheet)

            If xlWorkSheet.Name = SheetName Then

                Dim xlRange1 As Excel.Range = Nothing
                xlRange1 = xlWorkSheet.Range("A1:B6")
                xlRange1.Select()
                xlRange1.Copy()

                Dim xlDestination As Excel.Range = Nothing
                xlDestination = xlWorkSheet.Range("C1:D6")

                xlDestination.PasteSpecial(Excel.XlPasteType.xlPasteAll, Excel.XlPasteSpecialOperation.xlPasteSpecialOperationNone)

                Marshal.FinalReleaseComObject(xlDestination)
                xlDestination = Nothing

                Marshal.FinalReleaseComObject(xlRange1)
                xlRange1 = Nothing

                xlWorkSheet.SaveAs(FileName)
                Marshal.FinalReleaseComObject(xlWorkSheet)
                xlWorkSheet = Nothing
                Exit For
            End If

        Next

        xlWorkBook.Close()
        xlApp.UserControl = True
        xlApp.Quit()

        ReleaseComObject(xlCells)
        ReleaseComObject(xlWorkSheets)
        ReleaseComObject(xlWorkSheet)
        ReleaseComObject(xlWorkBook)
        ReleaseComObject(xlWorkBooks)
        ReleaseComObject(xlApp)

    End Sub
    Private Sub ReleaseComObject(ByVal obj As Object)
        Try
            If obj IsNot Nothing Then
                System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
                obj = Nothing
            End If
        Catch ex As Exception
            obj = Nothing
        End Try
    End Sub
End Module