Я пишу программу, которая перебирает все листы в книге Excel и сохраняет каждый лист как свою собственную книгу.Это оказалось немного хитрее, чем я ожидал, поскольку метод Sheet.Copy
создает странный объект (см. Здесь обсуждение MSDN, которое, я считаю, имеет отношение: http://msdn.microsoft.com/en-us/library/ms178779.aspx).
В любом случае, янайдено еще одно сообщение о переполнении стека , которое привело меня туда, где я нахожусь, что по сути завершено, за пределами одного зависшего процесса 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
Теперь я думаю, что проблема возникает в конце цикла, где я пытаюсь закрыть файл экспортаи новый рабочий лист, который он создает:
'close excel and release com objects
System.Runtime.InteropServices.Marshal.ReleaseComObject(exportsheet)
exportsheet = Nothing
xlApp1.Workbooks(fileNames(counter - 1)).Close(False)
Я не могу понять, что делать, чтобы выпустить ComObject
для нового созданного рабочего листа. Я пробовал все виды вещей, но этовсегда выдает ошибку COM, когда я делаю это, и если я пытаюсь определить это как ничего (как я делаю с помощью таблицы экспорта), это говорит о том, что по умолчанию это только чтение, поэтому я не могу этого сделать. Похоже, это должно быть что-тотак просто, как:
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp1.Workbooks(fileNames(counter - 1)))
Но это не так.Я попробовал несколько вариантов этого, и я думаю, что это имеет отношение к ссылке MSDN выше, но я не могу полностью разобраться, что делать.Таким образом, код работает для моих целей, не выходя из одного файла EXCEL.EXE после его завершения.
Что касается тестового файла, я просто использую файл Excel с 3 листами и помещаю некоторую информацию в каждыйи измените имя листа, чтобы было легко увидеть, работает он или нет.
Любые мысли будут оценены, спасибо.
Обновление: я только что отключил видимость из своего основного приложения Excel, и все еще всплывающие окна, что наводит меня на мысль, что способ, которым я используюCopy
создает новое приложение Excel, но я не совсем уверен, как на него ссылаться.Если кто-то и знает, как отключить видимость, это было бы очень полезно.
Окончательное обновление: если вероятность того, что какая-то бедная душа столкнется с той же проблемой, с которой я столкнулся, первое обновление должно решить,это, но также важно отметить, что excel.exe будет зависать, пока вы не закроете приложение.Я сообщаю код автоматизации в виде приложения Windows Form (чтобы сотрудники могли указать местоположение файла и т. Д.), И будет процесс Excel.exe, работающий, пока вы не закроете всплывающее окно из программы.Возможно, сборщик мусора не запускается до тех пор, пока вы не закроете окно приложения, или просто по какой-то другой причине просто зависает на экземпляре excel.exe.