excel - 为什么在 Access 数据库中使用 VBA 打开和关闭多个 Excel 工作簿时偶尔会出现错误 91

标签 excel vba ms-access

我从客户那里收到各种电子表格。我想重命名源文件以将客户端创建文件的日期包含在文件名中。我读取了文件名列表,并将它们存储在 Access 表中。我阅读了表格,对于列出的每个文件,我打开 excel 以便我可以获得电子表格的内置文档属性,然后尝试重命名文件。

该代码有效,但在某些情况下,我在尝试检索 excel 文件的“创建日期”的行上收到 ERROR 91。我无法确定它发生的具体原因。有时它可以通过完整的文件列表工作,有时则不能。当只有 1 个文件时,有时我会收到 ERROR 91。有时它通过 5 到 10 个列表运行良好。这些文件位于网络共享上,我的直觉是代码可能在文件完全加载到 Excel 之前尝试 Access 该属性。那可能吗?我试过制造一个人为的停顿。问题依然存在。我实际上尝试使电子表格处于事件状态,即使我认为我不应该这样做。我已关闭更新和警报。到目前为止,这些都不重要。最初是从文件脚本开始,而不是打开 excel 文件。但是创建日期的 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

错误 91 并不总是发生。当要重命名 1 个文件或多个文件时,可能会发生这种情况。这不是我能说出的任何特定间隔。例如,要处理 5 个文件。第一遍,它重命名了 2 个文件,然后在文件 3 上出现错误 91。20 分钟后,我再试一次,所有 5 个都得到处理没有问题。 10 分钟后,我再次尝试,第一个文件出现 ERROR 91。如果我 msgbox 文件名,它似乎每次都有效。但是当这个过程转移到生产中时,这不是一个可行的选择,因为我们希望一次处理 30 到 40 个文件,每天处理 2 到 3 个客户。

最佳答案

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


你早熟了,没必要用 CreateObject 去注册表获取Excel.Application类型。只需 New它,编译器已经知道在哪里找到它:
Set xlApp = New Excel.Application

您正在丢弃返回的 Workbook对象在这里:

    xlApp.Workbooks.Open FileName:=strFileName


改为捕获它:
Dim xlBook As Workbook
Set xlBook = xlApp.Workbooks.Open(strFileName)

这是个问题:

strCreation = ActiveWorkbook.BuiltinDocumentProperties("Creation Date")


不合格,ActiveWorkbook正在隐式创建 Excel.Global/Excel.Application您没有引用的对象:该对象不是您的xlApp - 它是隐式创建的隐式 ghost 实例,并且没有事件的工作簿,这将解释错误 91。限定成员调用:
strCreation = xlApp.ActiveWorkbook.BuiltinDocumentProperties("Creation Date")

但实际上,如果您捕获了工作簿变量,您就不会关心事件工作簿是什么:
strCreation = xlBook.BuiltinDocumentProperties("Creation Date")

同样在这里:

ActiveWorkbook.Close SaveChanges:=False


转到:
xlBook.Close SaveChanges:=False

关闭 Access 后,任务管理器中可能会出现许多“幽灵”EXCEL.EXE 进程:如果是这种情况,您将不得不手动终止这些进程。

这也可能存在问题:

    xlApp.Quit


RenameImportFiles_Exit:
    xlApp.Quit


如果 While...Wend循环(应该是 Do While...Loop )运行到完成,然后 xlApp.Quit运行两次......那是不对的。

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


错误 91 并不表示“属性不存在”,而是错误 438。错误 91 表示“对象不存在”,例如,您要调用 foo.Bar , 但是 fooNothing .

关于excel - 为什么在 Access 数据库中使用 VBA 打开和关闭多个 Excel 工作簿时偶尔会出现错误 91,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57677782/

相关文章:

vba - excel vba dir函数查找doc而不是docx

excel - 单击单元格时运行一个宏,双击单元格时运行另一个宏

VBA 'set typelib = createobject("scriptlet.typelib")'权限被拒绝

vba - 根据用户选择一次打印多个工作表

excel - 文件名通配符的返回值

mysql - [hy000][mysql][odbc 3.51 驱动程序]无法连接到 'mysql8.namesco.net' (10061) 上的 MYSQL 服务器

vba - 导入带分隔符的文本

string - VBA 范围和字符串混淆

vba - 确定实际传递给 VBA 函数的(可选)参数有多少?

sql - 使用 SQLite 数据库作为后端,前端使用 MS Access,超过 2 演出数据