在子中访问打开的工作簿有时会生成错误 1004“对象 '_Global' 的 'Sheets' 方法未失败”

Posted

技术标签:

【中文标题】在子中访问打开的工作簿有时会生成错误 1004“对象 \'_Global\' 的 \'Sheets\' 方法未失败”【英文标题】:Accessing open workbook in a sub generates Error 1004 "Method of 'Sheets' of Object '_Global' not failed" sometimes在子中访问打开的工作簿有时会生成错误 1004“对象 '_Global' 的 'Sheets' 方法未失败” 【发布时间】:2018-09-01 22:18:01 【问题描述】:

当我尝试引用活动工作簿时,我得到不一致的结果。大约一半的时间我得到“对象'_Global'的'Sheets'方法没有失败”错误,其他时候代码工作正常。我没有看到模式。

VBA 代码是 Word 文档的一部分,它允许用户打开模板 Excel 文件并将 Word 文档中的文本选择/复制到 Excel 文件的行中。

在之前的 sub 中,我成功打开了一个 Excel 模板文件(我称之为 RTM 模板)。在下面的代码中,我想激活“RTM”工作表,选择第一个单元格,模板中可能已经包含先前执行的数据,如果有,则计算存在多少行数据。这样,新数据将发布在没有任何数据的第一行。我在工作簿中使用命名范围来引用起始单元格(“First_Cell_For_Data”)。

当我运行我的代码时,有时它运行时没有错误,而其他时候它在“Sheets(”RTM").Activate”处停止并给我“方法....”错误。当我将 wb_open 的变量定义更改为 Object 时,也会出现相同的结果。我也尝试过使用“wb_open.Sheets("RTM").Activate" 获得相同的结果。

按照下面的 cmets 中的建议,我添加了“如果 wb_open 什么都不是……”来调试问题。我还添加了子 List_Open_Workbooks 枚举打开的工作簿(其中只有 1 个)并激活与具有正确文件名的工作簿名称匹配的工作簿。这是成功的。但是在返回 Check_Excel_RTM_Template 后,我仍然在“Sheets("RTM").Activate" 行中遇到方法错误。

第二次更新:经过更多时间诊断问题(仍然间歇性发生)后,我添加了一些可能有助于找到问题根源的代码。在“List_Open_Workbooks”子中,我测试了xlApp.Workbooks.Count = 0。因此,对打开的 Excel 工作簿的所有引用都将失败。此时我的模板工作簿已在 Windows 中打开。我得出正确的结论吗?

第三次更新:我尝试了Set wb_open = GetObject(str_filename),其中str_filename 包含我刚刚打开的Excel 模板文件的名称。

我收到以下错误消息。

另外,我注意到,如果我从新发布的 Word 和 Excel 开始,它似乎运行得很好。

    Sub Check_Excel_RTM_Template(b_Excel_File_Has_Data As Boolean, i_rows_of_data As Integer)
    Dim i_starting_row_for_data As Integer
    Dim wb_open As Object
    Set wb_open = ActiveWorkbook
    i_rows_of_data = 0
    If wb_open Is Nothing Then
        MsgBox "RTM Workbook not open in Check_Excel_RTM_Template"
        Call List_Open_Workbooks(b_Excel_File_Has_Data, i_rows_of_data)
    Else
 '   On Error GoTo Err1:
 '       Sheets("RTM").Activate
 '      range("First_Cell_For_Data").Select
        Workbooks(wb_open.Name).Worksheets("RTM").range("First_Cell_For_Data").Select
        If Trim(ActiveCell.Value) <> "" Then
           b_Excel_File_Has_Data = True
          Do Until Trim(ActiveCell.Value) = ""
               ActiveCell.Offset(1, 0).Select
               i_rows_of_data = i_rows_of_data + 1
           Loop
           Else
                b_Excel_File_Has_Data = False
        End If
    End If
    Exit Sub
Err1:
    MsgBox getName(str_Excel_Filename) & "  is not a RTM template file."
    b_abort = True
End Sub 

Sub 枚举所有打开的工作簿

Sub List_Open_Workbooks(b_Excel_File_Has_Data As Boolean, i_rows_of_data As Integer)
Dim xlApp As Excel.Application
Set xlApp = GetObject(, "Excel.Application")
Dim str_filename As String

Dim xlWB As Excel.Workbook
If xlApp.Workbooks.Count = 0 Then
    MsgBox "Error: Windows thinks there are no workbooks open in List_Open_Workbooks"
    b_abort = True
    Exit Sub
End If
For Each xlWB In xlApp.Workbooks
    Debug.Print xlWB.Name
    str_filename = getName(str_Excel_Filename)
    If Trim(xlWB.Name) = Trim(str_filename) Then
        xlWB.Activate
        If xlWB Is Nothing Then
            MsgBox "Workbook still not active in List_Open_Workbooks"
            b_abort = True
            Exit Sub
        Else
 '               Sheets("RTM").Activate
                Workbooks(xlWB.Name).Worksheets("RTM").range("First_Cell_For_Data").Select
                range("First_Cell_For_Data").Select
                If Trim(ActiveCell.Value) <> "" Then
                    b_Excel_File_Has_Data = True
                    Do Until Trim(ActiveCell.Value) = ""
                        ActiveCell.Offset(1, 0).Select
                        i_rows_of_data = i_rows_of_data + 1
                    Loop
                Else
                    b_Excel_File_Has_Data = False
                End If
        End If
    End If
Next xlWB

Set xlApp = Nothing
Set xlWB = Nothing
End Sub

从路径/文件名中提取文件名的功能

Function getName(pf)
getName = Split(Mid(pf, InStrRev(pf, "\") + 1), ".")(0) & ".xlsx"
End Function

【问题讨论】:

Sheets("RTM") 行上设置条件断点,条件为Sheets Is Nothing,这将帮助您诊断问题。我怀疑没有单个活动工作簿时正在调用您的宏。 @Dai - 您如何获得多个活动工作簿? @Jeeped 可能是没有打开工作簿,或者工作簿已打开但它在 Excel 中未处于活动状态 - 或者打开了另一个没有名为“RTM”的工作表的工作簿。 @Dai 最后一种情况是 index out of bounds (9),而不是 object 或未设置块变量 (91)。 Kaiser,Sheets(...)隐式引用ActiveWorkbook,您应该使用显式Workbook 对象来限定它,例如wb_open.Sheets(...) - 否则 wb_open 毫无用处。在对它进行成员调用之前,还要验证它是否是Nothing。如果没有活动的工作簿,If wb_open Is Nothing Then Exit Sub 将退出。 如果您打开了多个 Excel 实例,GetObject 将返回第一个匹配进程。这可能是也可能不是您调用List_Open_Workbooks 来自 的实例。如果从 Excel 内部调用此代码,则没有理由使用 GetObject - 只需在需要的地方使用 Application 对象即可。 【参考方案1】:

我希望我找到了问题的根源并解决了它。

我相信在 Dim wb_open As ObjectSet wb_open = ActiveWorkbook 中使用 Check_Excel_RTM_Template 子中的打开的工作簿会导致我出现不一致的问题......也许这是 Word 中的 VBA 实现中的异常(错误) .

在我在下面发布的修改后的代码中,我从调用例程传递了o_Excel 对象,并使用oExcel.Activesheet.xxx 来引用范围和值。

现在我的下一个问题是我在表单控制按钮代码上出现错误,该代码也使用Dim wb_open As ObjectSet wb_open = ActiveWorkbook 方法来引用打开的工作簿。但我会把它作为一个新问题发布。

感谢所有评论和提供建议的人。

Sub Check_Excel_RTM_Template(oExcel As Object)
    Dim i_starting_row_for_data As Integer
    Dim str_filename As String
    i_rows_of_data = 0
    On Error GoTo Err1:

        oExcel.ActiveSheet.range("First_Cell_For_Data").Select
        If Trim(oExcel.ActiveCell.Value) <> "" Then
           b_Excel_File_Has_Data = True
          Do Until Trim(oExcel.ActiveCell.Value) = ""
               oExcel.ActiveCell.Offset(1, 0).Select
               i_rows_of_data = i_rows_of_data + 1
           Loop
           Else
                b_Excel_File_Has_Data = False
        End If
    Exit Sub
Err1:
    Documents(str_doc_index).Activate
    MsgBox getName(str_Excel_Filename) & "  is not a RTM template file."
    b_abort = True
End Sub

【讨论】:

以上是关于在子中访问打开的工作簿有时会生成错误 1004“对象 '_Global' 的 'Sheets' 方法未失败”的主要内容,如果未能解决你的问题,请参考以下文章

错误处理中的 Excel VBA 运行时错误 1004

在私有子中引用公共变量时遇到问题

如果打开后发现错误,如何避免打开工作簿?

在同一活动工作簿中从一个工作表复制和粘贴到另一个工作表时出现错误 1004

VBA 打开工作簿错误?

为啥 PasteSpecial 方法有时会抛出错误 1004?