VB.NET Excel Program Leaves EXCEL.EXE floating after completion

前端 未结 4 1832
醉酒成梦
醉酒成梦 2020-12-04 01:51

I am writing a program that loops through all of the sheets in an Excel workbook and saves each sheet as its own workbook. It turned out to be a bit trickier than I expected

相关标签:
4条回答
  • 2020-12-04 02:19

    Below is code that works for me (NOTE order that I release objects, which is important)

    xlWorkBook.Close()
    xlApp.Quit()
    ReleaseObject(xlWorkSheet)
    ReleaseObject(xlWorkBook)
    ReleaseObject(xlApp)
    
    Private Sub ReleaseObject(ByVal obj As Object)
      Try
        System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
        obj = Nothing
      Catch ex As Exception
        obj = Nothing
      Finally
        GC.Collect()
      End Try
    End Sub
    
    0 讨论(0)
  • 2020-12-04 02:21

    Okay, this works form me for a very simple worksheet. Let me know if you have any questions.

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        'Get information from text boxes
        Dim InputLocation As String
        Dim OutputLocation As String
    
        InputLocation = InputLoc.Text & "\" & Filename.Text
    
        If OutputLoc.Text = "" Then
            OutputLocation = InputLoc.Text
        Else
            OutputLocation = OutputLoc.Text
        End If
    
        'Make file to save files in
        ' Get date and time in filename as well
        Dim TLDateTime As String
        Dim TLDay As String
        Dim TLMonth As Integer
        Dim TLYear As Integer
        Dim TLHour As Integer
        Dim TLMinute As Integer
        Dim TLDate As String
        Dim TLTime As String
        Dim TLSecond As Integer
    
        TLDay = DateTime.Now.Day
        TLMonth = DateTime.Now.Month
        TLYear = DateTime.Now.Year
        TLHour = DateTime.Now.Hour
        TLMinute = DateTime.Now.Minute
        TLSecond = DateTime.Now.Second
    
        Dim MyDate As New DateTime(TLYear, TLMonth, TLDay, TLHour, TLMinute, TLSecond)
        Dim MyString As String = MyDate.ToString("MMMddyyyy_HHmmss")
        TLDate = TLMonth.ToString + TLDay.ToString + TLYear.ToString
        TLTime = TLHour.ToString + TLMinute.ToString
        TLDateTime = TLDate + "_" + TLTime
    
        Try
            Directory.CreateDirectory(OutputLocation & "\" & "Field Sales Report Graphs " & TLDateTime)
            OutputLocation = OutputLocation & "\" & "Field Sales Report Graphs " & TLDateTime
        Catch
            MsgBox("Trying to create a file that exists, please delete it. If the file does not exist check to make sure your output location exists")
        End Try
    
        'Open up excel file with information in it
        Dim xlApp1 As Excel.Application = New Excel.Application
        xlApp1.Visible = True
        xlApp1.Application.DisplayAlerts = False
    
        Dim locs As Excel.Workbook
        locs = xlApp1.Workbooks.Open(InputLocation)
        Dim fileNames As New ArrayList
        Dim counter As Integer = 1
        For Each ws As Excel.Worksheet In locs.Worksheets
            fileNames.Add(ws.Name)
            ws = xlApp1.Workbooks(counter).Sheets(1)
            ws.SaveAs(Filename:=OutputLocation & "\" & fileNames(counter - 1) & ".xlsx")
            'close excel and release com objects
            System.Runtime.InteropServices.Marshal.ReleaseComObject(ws)
            xlApp1.Workbooks(counter).Close(False)
            counter += 1
        Next
        System.Runtime.InteropServices.Marshal.ReleaseComObject(locs)
        locs = Nothing
        xlApp1.Quit()
        System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp1)
        xlApp1 = Nothing
    End Sub
    
    0 讨论(0)
  • 2020-12-04 02:23

    You might need to do the following if you have unreferenced COM objects that are being created:

    GC.Collect()
    GC.WaitForPendingFinalizers()
    

    Taken from this MSDN forum post: http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/cb5f7948-c229-483e-846b-a1cfbbcd86ca/

    0 讨论(0)
  • 2020-12-04 02:34

    The solution I finally came across was to add

    System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp1.ActiveWorkbook)
    xlApp1.ActiveWorkbook.Close()
    

    to the loop. I found this answer in the comments of The first answer on another stack overflow post. Basically, the problem I was having is that the worksheet.copy method creates a workbook object with no reference, but it turns out it can be referenced by referring to the activesheet. If you wanted to do more with it than just kick it out the door like I am, I imagine you could create a new workbook object and assign it or as the post I link to suggests, you can save it as something as well. For my puposes, it is just fine to release it after saving the worksheet I want and this removed my excel.exe hanging process.

    If you want a bit more elgant code option you should check out the ron tornambe post where he does the for each loop I managed to not get right instead of the wonky thing I create. Basically you would want to use his loop in my code and you would have it all set up. Thanks as always stack overflow.

    0 讨论(0)
提交回复
热议问题