Home » excel » Why do i occasionally get Error 91 when opening and closing multiple Excel workbooks thru VBA in Access database

Why do i occasionally get Error 91 when opening and closing multiple Excel workbooks thru VBA in Access database

Posted by: admin May 14, 2020 Leave a comment

Questions:

I receive various spreadsheets from clients. I want to rename the source files to include the date the file was created by the client into the filename. I read a list of the file names, and store them in an Access table. I read the table, and for each file listed, i open excel so that i can get the built-in document property for the spreadsheet, and then attempt to rename the file.

The code works, but on some occasions, i get an ERROR 91 on the line that tries to retrieve the “creation date” of the excel file. I cannot determine a specific reason why it happens. Sometimes it works thru the full list of files, sometimes it does not. Sometimes I get ERROR 91 when there is only 1 file. And sometimes it runs fine thru a list of 5 to 10. The files are located on a network share, and my intuition is maybe the code is trying to access the property before the file is fully loaded into Excel. Is that possible? I have tried creating an artificial pause. Issue still exists. I tried actually making the spreadsheet active, even though i didn’t think i should have to do this. I have turned off updating and alerts. None of this matters so far. Originally started with file scripting, instead of opening the excel files. but fso property for creation date looks like the date the file was created on our file system, NOT the date the client created the spreadsheet.

Private Sub RenameImportFiles()
'On Error GoTo ErrorHandler
    Dim dbMedent As Database
    Dim oFS As Object
    Dim strFileParts() As String
    Dim strDateParts() As String
    Dim strDayParts() As String
    Dim strTimeParts() As String

    Dim strCreation As String

    Dim strSQL As String
    Dim rsRead As Recordset
    Dim strFileName As String
    Dim strFileNameNew As String

    Dim intTime As Integer
    Dim intRecExpect As Integer
    Dim intRecCurr As Integer
    Dim intRecComp As Integer

    Me.txtProcWindow = "Renaming Import Files ..."

    intRecExpect = 0
    intRecCurr = 0
    intRecComp = 0


    'This creates an instance of the MS Scripting Runtime FileSystemObject class
    Set oFS = CreateObject("Scripting.FileSystemObject")

    strSQL = "SELECT * FROM Files_In_Folders ORDER BY FileName"
    Set dbMedent = CurrentDb
    Set rsRead = dbMedent.OpenRecordset(strSQL)
    intRecExpect = rsRead.RecordCount
    Me.txtFileCnt_Expect = intRecExpect

    With rsRead
        .MoveLast
        .MoveFirst
        If .RecordCount < 1 Then
            '/*****************   ERROR HANDLING ****************
        End If


        Dim xlApp As Excel.Application
        Set xlApp = CreateObject("Excel.Application")


        While Not .EOF
            intRecCurr = intRecCurr + 1
            Me.txtFileCnt_Current = intRecCurr
            Me.txt_Curr_FileNm = strFileName
            Me.txtCurr_FileID = rsRead![FileID]

            strFileName = ![FilePath] & ![FileName]

            xlApp.ScreenUpdating = False
            xlApp.DisplayAlerts = False
            xlApp.EnableEvents = False
            xlApp.Visible = False

            xlApp.Workbooks.Open FileName:=strFileName
            'for debugging errror #91 pops up occasionally;  why does it sometimes think property doesn't exist
            'force excel to activate a sheet, then get property;  or force excel to wait a few seconds???
            Call WaitFor(1)
            xlApp.Worksheets(1).Activate

            'MsgBox "trying to open:  " & strFileName

            ***strCreation = ActiveWorkbook.BuiltinDocumentProperties("Creation Date")***
            strFileParts = Split(strCreation)
            strDayParts = Split(strFileParts(0), "/")
            strTimeParts = Split(strFileParts(1), ":")
            If strFileParts(2) = "PM" Then
                intTime = CInt(strTimeParts(0)) + 12
            Else
                intTime = CInt(strTimeParts(0))
            End If
            strFileNameNew = ![FilePath] & ![FilePracticeTIN] & "_" & _
                            strDayParts(2) & Format(strDayParts(0), "00") & Format(strDayParts(1), "00") & _
                            Format(intTime, "00") & Format(strTimeParts(1), "00") & Format(strTimeParts(2), "00") & _
                            "_" & ![FileMeas] & ![FileType]
            ActiveWorkbook.Close SaveChanges:=False
            oFS.CopyFile strFileName, strFileNameNew, True

            rsRead.Edit
            ![FileName] = ![FilePracticeTIN] & "_" & _
                            strDayParts(2) & Format(strDayParts(0), "00") & Format(strDayParts(1), "00") & _
                            Format(intTime, "00") & Format(strTimeParts(1), "00") & Format(strTimeParts(2), "00") & _
                            "_" & ![FileMeas] & ![FileType]
            ![FileRptDate] = strDayParts(2) & Format(strDayParts(0), "00") & Format(strDayParts(1), "00")
            ![FileRptTime] = Format(intTime, "00") & Format(strTimeParts(1), "00") & Format(strTimeParts(2), "00")

            rsRead.Update
            intRecComp = intRecComp + 1
            Me.txtFileCnt_Good = intRecComp
            Me.txtFileCnt_Bad = intRecExpect - intRecComp
            Me.txt_Curr_FileNm = strFileName
            DoEvents
            rsRead.MoveNext
        Wend
    End With

    xlApp.ScreenUpdating = True
    xlApp.DisplayAlerts = True
    xlApp.EnableEvents = True

    xlApp.Quit


RenameImportFiles_Exit:
    xlApp.Quit
    Set dbMedent = Nothing
    Set oFS = Nothing
    Me.txtProcWindow = Me.txtProcWindow & vbCrLf & SPACE8 & "Expected " & intRecExpect & " files." & _
                        vbCrLf & SPACE8 & "Renamed " & intRecComp & " files." & _
                        vbCrLf & SPACE8 & (intRecExpect - intRecComp) & " files had Errors or other issues." & _
                        vbCrLf & SMALL_DONE

    Call HideProgressBar(True)
    Exit Sub

ErrorHandler:
    MsgBox "Error #: " & Err.Number & vbCrLf & vbCrLf & Err.Description
    Resume RenameImportFiles_Exit
End Sub

Error 91 does not always happen. It can occur when 1 file to rename or many. It’s not any specific interval that i can tell. Example, 5 files to process. 1st pass, it renames 2 files, then error 91 on file 3. 20 minutes later, i try again, and all 5 get processed no problem. 10 minutes later, i try again, and it ERROR 91 on the first file. if i msgbox the filename, it seems to work every time. but when this process is moved to production, that is not a feasible option, since we expect to process 30 to 40 files at a time, from 2 to 3 clients a day.

How to&Answers:
    Dim xlApp As Excel.Application
    Set xlApp = CreateObject("Excel.Application")

You’re early-bound, there’s no need to hit the registry with CreateObject to get a hold of the Excel.Application type. Just New it up, the compiler already knows where to find it:

Set xlApp = New Excel.Application

You’re discarding the returned Workbook object here:

    xlApp.Workbooks.Open FileName:=strFileName

Capture it instead:

Dim xlBook As Workbook
Set xlBook = xlApp.Workbooks.Open(strFileName)

This is a problem:

strCreation = ActiveWorkbook.BuiltinDocumentProperties("Creation Date")

Unqualified, ActiveWorkbook is implicitly creating an Excel.Global/Excel.Application object to which you hold no reference: that object is not your xlApp – it’s an implicit ghost instance that gets created implicitly, and it has no workbook that’s active, which would explain error 91. Qualify the member call:

strCreation = xlApp.ActiveWorkbook.BuiltinDocumentProperties("Creation Date")

But really if you captured the workbook variable, you couldn’t care less what the active workbook is:

strCreation = xlBook.BuiltinDocumentProperties("Creation Date")

Same here:

ActiveWorkbook.Close SaveChanges:=False

Turn to:

xlBook.Close SaveChanges:=False

There may be a number of “ghost” EXCEL.EXE processes lingering in Task Manager after Access is closed: you’ll have to manually kill these processes if that’s the case.


This is also potentially problematic:

    xlApp.Quit


RenameImportFiles_Exit:
    xlApp.Quit

If the While...Wend loop (should be Do While...Loop) runs to completion, then xlApp.Quit gets to run twice… that can’t be right.


'for debugging errror #91 pops up occasionally;  why does it sometimes think property doesn't exist

Error 91 doesn’t mean “property doesn’t exist”, that would be error 438. Error 91 means “object doesn’t exist”, as in, you want to invoke foo.Bar, but foo is Nothing.