Du har problem med resurshanteringen i ditt program. Har inte lusläst din kod, men här är några generella tips.
När man använder en resurs (i ditt fall excel-objektet), vill man stänga den vid avslut. Det finns en konstruktion för det i .Net, try-finally, som du borde använda. Syftet är att man öppnar en resurs (fil, socket, excel-instans via com-interop etc.) och är garanterad att den stängs.
Private Sub Foo()
Dim stream As StreamWriter
Try
stream = New StreamWriter("c:\test.txt")
stream.WriteLine("test")
Finally
' Du är garanterad att finally-satsen körs (om inte
' konstruktorn till streamwritern kastat exception)
stream.Close()
End Try
End Sub
På det här sättet vet du att resursen stängs, även om du går ur metoden med ett exception. Läs om Close() Dispose() och IDisposable i MSDN på http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemidisposableclassdisposetopic.asp?frame=true och http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconfinalizedispose.asp?frame=true. På samma sätt borde du göra med ditt excel-objekt istället för att som nu göra .Save() och sätta till Nothing. Genom att sätta till Nothing säger du åt GCn att "det här objektet är färdiganvänt, städa bort det när du vill". Vad händer då?
När du gör GC.Collect() säger MSDN att
All objects, regardless of how long they have been in memory, are considered for collection
Det är troligt att ditt excel-objekt fortfarande håller i filen även när GC.Collect() körts. Det finns även en GC.WaitForPendingFinalizers() som du kan läsa om i MSDN. Observera att det är oftast är dålig kodning att tvinga garbage collection. Det dödar prestanda och du kommer förmodligen göra felaktiga antaganden i din kod. (Att forcera garbage collection i test-syfte och för att lära sig är förstås helt ok). Det finns fall då man tvingar fram GC av prestandaskäl men då ska man vara väldigt säker på vad man gör.
Så du vill förmodligen göra wb.Close() i din finally-sats.
Tänk på:
- Alla gånger du sätter "r = Nothing" är helt onödiga, jag skulle ta bort dessa.
- Du instansierar ea vid varje anrop. Överväg att ha en pool av sådana instanser istället för att skapa en ny varje gång. Det kommer troligtvis döda prestanda att skapa om dessa. (Dock tycker jag du ska göra detta först när du fått allt annat att fungera - en sak i taget)
- Du har en funktion ExportToExcel som är läskigt lång och gör många saker. Överväg att dela in den i logiska del-metoder, typ
Private Sub ExportToExcel(ByVal unit As String)
Dim wb As Excel.Workbook
Try
wb = ...
DoStuffWithExcel(wb)
DoOtherStuff(wb, filnamn)
Finally
wb.Close()
End Try
End Sub