VB.NET Excel程序在完成后使EXCEL.EXE浮动

asj*_*son 7 .net vb.net excel

我正在编写一个循环遍历Excel工作簿中所有工作表的程序,并将每个工作表保存为自己的工作簿.事实证明它比我想象的要复杂一些,因为该Sheet.Copy方法会创建一个奇怪的对象(请参阅此处的MSDN讨论,我相信这是相关的:http://msdn.microsoft.com/en-us/library/ms178779. aspx).

无论如何,我发现另一个Stack Overflow帖子让我到了我的位置,这基本上是完整的,在程序完成后留下的一个挂起的EXCEL.EXE进程之外(检查更新还有一个问题,但是我认为他们是相关的).

这是我的代码:

Imports System.Data
Imports System.IO
Imports Microsoft.Office.Interop
Imports Office = Microsoft.Office.Core
Imports xlNS = Microsoft.Office.Interop.Excel
Imports System.Runtime.InteropServices

Class Form1

Private Sub Button1_Click(ByVal sender As System.Object, ByVal 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
    Dim locs As Excel.Workbook

    Dim exportsheet As Excel.Worksheet
    xlApp1 = New Excel.Application
    xlApp1.Visible = True
    xlApp1.Application.DisplayAlerts = False
    locs = xlApp1.Workbooks.Open(InputLocation)

    'locsws = locs.ActiveSheet
    Dim wkshtcount = locs.Worksheets.Count - 1
    Dim fileNames As New ArrayList

    For counter = 1 To wkshtcount + 1
        'identify and copy sheet to move
        exportsheet = CType(locs.Worksheets(counter), Excel.Worksheet)
        fileNames.Add(exportsheet.Name)
        exportsheet.Copy(Type.Missing, Type.Missing)

        exportsheet = xlApp1.Workbooks("Book" & counter).Sheets(1)

        exportsheet.SaveAs(Filename:=OutputLocation & "\" & fileNames(counter - 1) & ".xlsx")

        'close excel and release com objects
        System.Runtime.InteropServices.Marshal.ReleaseComObject(exportsheet)
        exportsheet = Nothing
        System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp1.ActiveWorkbook)
        xlApp1.ActiveWorkbook.Close(False)

    Next
    'close excel and release com objects
    locs.Close(False)
    System.Runtime.InteropServices.Marshal.ReleaseComObject(locs)
    locs = Nothing
    xlApp1.Quit()
    System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp1)
    xlApp1 = Nothing


End Sub
End Class
Run Code Online (Sandbox Code Playgroud)

现在我认为问题来自循环结束,我尝试关闭导出文件和它创建的新工作表:

        'close excel and release com objects
        System.Runtime.InteropServices.Marshal.ReleaseComObject(exportsheet)
        exportsheet = Nothing
        xlApp1.Workbooks(fileNames(counter - 1)).Close(False)
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚如何释放ComObject创建的新工作表.我一直在尝试各种各样的事情,但是当我这样做时它总是抛出一个COM错误,并且如果我试图将它定义为什么(就像我对exportheet一样)是说它只是默认只读,所以我可以'做到了.看起来应该是这样简单:

System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp1.Workbooks(fileNames(counter - 1)))
Run Code Online (Sandbox Code Playgroud)

但事实并非如此.我已经尝试了一些这方面的变种,我认为它与上面的MSDN链接有关,但我不能完全理解该怎么做.因此代码适用于我的目的,在完成后留下一个EXCEL.EXE.

至于测试文件,我只是使用3张Excel文件,我在每个文件上放了一些信息并更改了工作表名称,因此很容易看出它是否正常工作.

任何想法都将不胜感激,谢谢.

更新:我刚刚从我的主Excel应用程序关闭了可见性,但仍然会弹出一些东西,这让我相信我正在使用的方式Copy是创建一个新的Excel应用程序,但我不确定如何引用它.如果有人知道如何关闭那里的能见度,那将非常感激.

最后更新:关于一些可怜的灵魂遇到我遇到的同一问题的机会,第一次更新应解决它,但同样重要的是要注意excel.exe将挂起,直到你关闭应用程序.我将自动化代码报告为Windows窗体应用程序(因此同事可以提供文件位置等),并且在您关闭程序弹出窗口之前,将会运行excel.exe进程.可能垃圾收集在您关闭应用程序窗口之前不会运行,或者由于某些其他原因它只是挂起到excel.exe的实例.

asj*_*son 1

我最终遇到的解决方案是添加

System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp1.ActiveWorkbook)
xlApp1.ActiveWorkbook.Close()
Run Code Online (Sandbox Code Playgroud)

到循环。我在另一个堆栈溢出帖子的第一个答案的评论中找到了这个答案。基本上,我遇到的问题是 worksheet.copy 方法创建了一个没有引用的工作簿对象,但事实证明它可以通过引用活动表来引用。如果您想用它做更多的事情,而不仅仅是像我一样将其踢出门,我想您可以创建一个新的工作簿对象并分配它,或者正如我链接到的帖子所建议的那样,您也可以将其另存为其他内容。就我的目的而言,保存我想要的工作表后释放它就可以了,这会删除我的 excel.exe 挂起进程。

如果您想要更优雅的代码选项,您应该查看 ron Tornambe 帖子,他在其中执行了我未能正确完成的 for every 循环,而不是我创建的古怪的东西。基本上你会想在我的代码中使用他的循环,然后你就可以把它全部设置好。一如既往地感谢堆栈溢出。