简体   繁体   English

为什么通过Access数据库中的VBA打开和关闭多个Excel工作簿时偶尔会出现错误91

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

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. 我阅读了文件名列表,并将其存储在Access表中。 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. 我阅读了表格,并为列出的每个文件打开了excel,以便可以获取电子表格的内置文档属性,然后尝试重命名该文件。

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. 该代码有效,但是在某些情况下,我在尝试检索excel文件的“创建日期”的行上收到错误91。 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. 有时只有1个文件时出现错误91。 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. 有时它可以通过5到10的列表正常运行。文件位于网络共享上,我的直觉是也许代码正在尝试将属性完全加载到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. 最初从文件脚本开始,而不是打开excel文件。 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. 但是创建日期的fso属性看起来像在文件系统上创建文件的日期,而不是客户端创建电子表格的日期。

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. 错误91并非总是会发生。 It can occur when 1 file to rename or many. 1个文件重命名或多个文件时可能会发生。 It's not any specific interval that i can tell. 这不是我能告诉的任何特定间隔。 Example, 5 files to process. 例如,要处理5个文件。 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. 第一遍,它重命名2个文件,然后在文件3上出现错误91。20分钟后,我再试一次,所有5个问题都得到处理。 10 minutes later, i try again, and it ERROR 91 on the first file. 10分钟后,我再试一次,并且在第一个文件上出现错误91。 if i msgbox the filename, it seems to work every time. 如果我msgbox文件名,它似乎每次都能工作。 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. 但是当此流程移至生产阶段时,这是不可行的选择,因为我们希望一次处理30至40个文件,每天2至3个客户。

  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. 您早已束手无策,无需使用CreateObject来访问注册表即可保留Excel.Application类型。 Just New it up, the compiler already knows where to find it: 只需New起来,编译器已经知道在哪里可以找到它:

Set xlApp = New Excel.Application

You're discarding the returned Workbook object here: 您将在此处丢弃返回的Workbook对象:

  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: 不合格, ActiveWorkbook隐式地创建了一个没有引用的Excel.Global / Excel.Application对象:该对象不是您的xlApp它是隐式创建的隐式幽灵实例,并且没有活动的工作簿,这将解释错误91。资格成员调用:

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. 关闭Access后,任务管理器中可能存在许多“幽灵” EXCEL.EXE进程:这种情况下,您必须手动杀死这些进程。


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. 如果While...Wend循环(应该是Do While...Loop )运行完成,则xlApp.Quit将运行两次...那是不对的。


 '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 . 错误91并不意味着“属性不存在”,那就是错误438。错误91意味着“ 对象不存在”,例如,您要调用foo.Bar ,但是fooNothing

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM