Excel VBA错误处理仅在第一次通过时有效

Excel VBA错误处理仅在第一次通过时有效,excel,vba,Excel,Vba,我的代码是: Sub zaa() 'code to find another open file that has the defined name "data" ' - useful where the name changes each month or week For Each wb In Workbooks On Error GoTo abcd x = wb.Name Workbooks(x).Activate If Range("Data").Address

我的代码是:

Sub zaa()
'code to find another open file that has the defined name "data" 
'    - useful where the name changes each month or week

For Each wb In Workbooks
  On Error GoTo abcd
  x = wb.Name
  Workbooks(x).Activate
  If Range("Data").Address <> "" Then y = wb.Name

  Exit Sub

abcd:
Next wb

End Sub
Sub-zaa()
'查找另一个具有定义名称“data”的打开文件的代码'
'-在名称每月或每周更改时非常有用
对于工作簿中的每个wb
关于错误转到abcd
x=wb.Name
工作簿(x)。激活
如果范围(“数据”).Address”,则y=wb.Name
出口接头
abcd:
下一个wb
端接头
基本目标是,当我知道某个Excel文件存在但不知道文件名时,查找具有特定命名范围的Excel文件,因为该文件每周或每月都会更改。目标是找到文件并在该点退出子文件(或者在该文件上执行其他代码并退出,而不是转到其他文件)

我发现如果我只打开了两个文件就可以了,但如果有更多的文件就不行了(除非目标文件是第二行的)。虽然我可以用我所拥有的东西来运行,但我认为其他人可能会从我所拥有的东西中受益,我可以有一个更强大的解决方案

更新: 感谢所有回复的人&感谢米奇将原始帖子以可读的格式发布!(从那以后,我学会了如何纠正这个问题,并能够直接复制代码——我在下面的一些评论中指出了我遇到的问题。) 我取得了不同程度的成功——PaulStock和Reafidy的代码最初都为我工作,但PaulStock代码已经停止为我工作。Jean-François Corbett和Chris Neilsen的回复和代码对我很有帮助,但目前当我运行代码(按原样)时,它似乎什么都没做——ie没有离开我运行代码的工作表(范围名称数据也没有出现)。我最初是在Excel 2007的工作表中使用其他宏运行代码的,但为了尝试获得不同的结果,我将它们移动到一个独立的工作表中,而没有打开其他宏文件。还尝试从保存为'97-'03格式的文件中运行它们。两者都没有产生不同的结果。其他比我更有经验的人(见我在与Reafidy的评论讨论中所犯的错误,请记住,我最初发布的代码是通过谷歌找到的材料的结果,并由我针对特定任务和应用程序进行了修改,这意味着我没有足够的悟性来独立完成)可能会找到其他更适合他们的解决方案,但目前:

我非常高兴Reafidy的代码对我有用

由于我没有注册(我尝试过,但没有成功),而且没有足够的声望点数,我不能投票,但我在Reafidy的解决方案旁边打了一个复选标记

进一步更新: 我现在发现PaulStock&Jean François Corbett的代码对我来说不起作用,因为我有一个很小的差异——代码包含“数据”,而我命名的范围是“数据”。在他们的代码中进行此更改(考虑到区分大小写)意味着他们的两个解决方案现在都适用于我,因此我尝试在他们的解决方案中添加一个勾号!不幸的是,我发现只有一个解决方案有问题

我还了解到,我把克里斯的密码看得太过字面。为了“按原样”测试每个代码,我就是这么做的。在他有“do stuff”的部分中添加了一个简单的“wb.activate”,使代码可以执行我想要的操作


再次感谢您的四点贡献。

您不能这样使用错误处理。将错误处理移出循环或在每次发生时重置错误处理程序,因此使用如下错误处理:

一个更受欢迎的选择是:

Sub Test()

    For Each wb In Workbooks
        x = wb.Name
        Workbooks(x).Activate            

        If RangeExists("Data") Then
            y = wb.Name
            Exit Sub
        End If

    Next wb

End Sub
Function RangeExists(s As String) As Boolean
    On Error Resume Next
    RangeExists = Range(s).Count > 0
End Function
编辑:

Sub Test()

    For Each wb In Workbooks
        x = wb.Name
        Workbooks(x).Activate            

        If RangeExists("Data") Then
            y = wb.Name
            Exit Sub
        End If

    Next wb

End Sub
Function RangeExists(s As String) As Boolean
    On Error Resume Next
    RangeExists = Range(s).Count > 0
End Function
@让·弗朗索瓦·科贝特,我得说,你可以很快按下投票按钮。我发布的第一个解决方案是因为我假设OP没有发布他的全部代码,因此我没有像通常那样尝试简化或“清理”。我同意我没有很好地表达我的答案,但是关于第一个解决方案,我试图证明他需要重置错误处理程序。不幸的是,我应该说“更喜欢的选择是”

@德里克,很抱歉我没能及时回答你进一步的问题。显然,你可以自由选择任何你喜欢的方法。在我看来,其他人提供的挖掘工作簿名称集合的多循环解决方案是不必要的,也是冗长的。现在更重要的是,名称集合可以包含引用常量、公式或范围的名称。我假设您只想检查定义的名称是否是一个特定的命名范围,这意味着其他人提供的循环方法需要调整以使其可靠

我同意其他人的意见,即应该避免错误处理,但excel中不必要的循环可能与使用错误处理一样有害,我个人像瘟疫一样避免它

上面的函数可以放在它自己的模块中,并且可以任意重用。它快速、可靠,避免了不必要的循环,专门检查工作簿中的命名范围,是检查excel vba社区中是否存在命名范围的最广泛接受/使用的方法(我的意思是使用函数和错误处理通过名称集合进行循环)。如果你不相信我,在谷歌上搜索“检查命名范围是否存在”。如果您需要其他excel vba专家的意见,请访问www.ozgrid.com/forum

现在我知道您已经发布了全部代码,并且不打算激活每个工作簿,您可以使用此代码激活第一个命名范围为“data”的工作簿:


我完全理解积极批评的必要性,如果正确使用否决票制度,我相信否决票制度。然而,我认为这是一个合理的解决方案,我投了两张反对票,再加上我在ops格式问题上的帮助——不幸的是,我忍不住觉得我想与这个论坛保持距离。

这里有一个替代方法,我不想对错误处理程序产生幻想

Sub zaa()
    Dim wb As Workbook
    Dim CheckForNamedRange As Boolean
    Dim nm As Name

    On Error GoTo EH

    For Each wb In Workbooks
        CheckForNamedRange = True
        Set nm = wb.Names("data")
        If CheckForNamedRange Then
            ' Name found
            ' do stuff

            Exit For
        End If
    Next
Exit Sub
EH:
    If CheckForNamedRange Then
        ' Name not found
        Err.Clear
        CheckForNamedRange = False
        Resume Next
    Else
        ' Some other error occured, so handle it
        '...
    End If
End Sub

试试这个代码。不必担心出错Sub zaa() For Each wb In Workbooks x = wb.Name Workbooks(x).Activate For Each n In Workbooks(x).Names If n.Name = "Data" Then y = wb.Name Exit Sub End If Next Next wb End Sub
x = wb.Name
Workbooks(x).Activate
Sub zaa2()
    Dim wb As Workbook
    Dim nm As Name

    For Each wb In Workbooks
        For Each nm In wb.Names
           If nm.Name = "Data" Then
                wb.Activate
                Exit Sub
           End If
        Next
    Next wb
End Sub
' A workbook containing a range named "Data" is now activated 
' (if one is found amongst the open workbooks). 
' Note that there may be more than one, but only the first found is activated...
If StrComp(nm.Name, "data", vbTextCompare) = 0 Then
If LCase(nm.Name) = "data" Then