Reputation: 27
I used the following Access VBA code to open four different excel workbooks in a loop while I need to edit the excel data and then update the Access table through recordset.
xl.Application.DisplayAlerts = False
Set wb = xl.Workbooks.Open(fileName, ReadOnly = True, editable = True, notify = False)
Set ws = wb.Sheets("Sheet1")
Set ws2 = wb.Worksheets.Add
cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & fileName & ";Extended Properties=""Excel 8.0;HDR=YES;IMEX=1;"";"
*****Other Codes******
wb.Close savechanges:=False
Set wb = Nothing
Set xlc = Nothing
Set ws = Nothing
Set ws2 = Nothing
Set xl = Nothing
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing
However, even though I close the excel file without saving for all the four files, I still receive the following notice after the full loop.
with Set wb = xl.Workbooks.Open(fileName, ReadOnly = True, editable = True, notify = False)
, I was still not able to turn off the notice.
PS. I did not receive the read-write notification for all the four files, normally one or two, which really confused me.
Any recommendations for solving the issue?
Thanks in advance for all the help!
Upvotes: 2
Views: 1313
Reputation: 5805
You can't manually control garbage collection in VBA but you can structure your data so that garbage collection is more predictable. The first thing I recommend is to place the Excel inter-op code in to it's own procedure that is called from your main loop. The reason is that when the procedure ends, the garbage collection will occur. Next time the loop calls the open procedure you will be working with a fresh set of object handles, instead of recycling the objects as you are currently doing. If you do it this way you never have to set your objects to nothing because they are destroyed as they go out of scope at the end of the procedure. Just be sure to always use local variables.
In order to do this without closing and opening Excel repetitively you need to get a handle on the currently running Excel instance. That is provided by the GetExcelApp
procedure below.
EXAMPLE:
Private Sub YourMainLoop()
For Each fileName in fileNames
ProcessExcelData fileName
Next fileName
End Sub
Private Sub ProcessExcelData(ByVal fileName as String)
Dim xl As Object
Set xl = GetExcelApp
xl.Application.DisplayAlerts = False
Set wb = xl.Workbooks.Open(fileName, ReadOnly = True, editable = True, notify = False)
Set ws = wb.Sheets("Sheet1")
Set ws2 = wb.Worksheets.Add
cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & fileName & ";Extended Properties=""Excel 8.0;HDR=YES;IMEX=1;"";"
' Process the data, blah blah blah
wb.Close savechanges:=False
rs.Close
cn.Close
End Sub
Public Function GetExcelApp() As Object
' Returns open excel instance.
' If it doesn't exist, creates one to return
On Error GoTo ErrHandler
Const ERR_APP_NOTRUNNING As Long = 429
Set GetExcelApp = GetObject(, "Excel.Application")
CleanExit:
Exit Function
ErrHandler:
If Err.number = ERR_APP_NOTRUNNING Then
Set GetExcelApp = CreateObject("Excel.Application")
Resume CleanExit
Else
ShowErrorMessageBox
End If
End Function
Upvotes: 1