测试或检查工作表是否存在

Test or check if sheet exists

提问人:yse 提问时间:7/14/2011 最后编辑:BigBenyse 更新时间:6/10/2023 访问量:700188

问:

Dim wkbkdestination As Workbook
Dim destsheet As Worksheet

For Each ThisWorkSheet In wkbkorigin.Worksheets 
    'this throws subscript out of range if there is not a sheet in the destination 
    'workbook that has the same name as the current sheet in the origin workbook.
    Set destsheet = wkbkdestination.Worksheets(ThisWorkSheet.Name) 
Next

基本上,我遍历原始工作簿中的所有工作表,然后在目标工作簿中设置为与原始工作簿中当前迭代的工作表同名的工作表。destsheet

如何测试该表是否存在?像这样:

If wkbkdestination.Worksheets(ThisWorkSheet.Name) Then 
Excel VBA

评论

2赞 sancho.s ReinstateMonicaCellio 9/7/2014
Excel VBA 的可能副本 如果存在 WorkSheet(“wsName”)

答:

244赞 Tim Williams 7/14/2011 #1

有些人不喜欢这种方法,因为“不恰当地”使用错误处理,但我认为它在 VBA 中被认为是可以接受的......另一种方法是遍历所有工作表,直到找到匹配项。

Function WorksheetExists(shtName As String, Optional wb As Workbook) As Boolean
    Dim sht As Worksheet

    If wb Is Nothing Then Set wb = ThisWorkbook
    On Error Resume Next
    Set sht = wb.Sheets(shtName)
    On Error GoTo 0
    WorksheetExists = Not sht Is Nothing
End Function

评论

7赞 Wudang 10/18/2011
完全适当地使用IMO。对于一个被假定为存在但实际上不存在并且具有悠久历史的事物来说,这是一个陷阱 - 参见 perl strict、STAE 等。点赞
22赞 sancho.s ReinstateMonicaCellio 9/7/2014
人们可能应该使用而不是 .后者是指包含宏代码的工作簿,该代码可能与要测试的工作簿不同。我想在大多数情况下会很有用(不过,人为的情况总是可用的)。ActiveWorkbookThisWorkbookActiveWorkbook
4赞 Tim Williams 10/16/2015
sht Is Nothing如果没有具有该名称的工作表,则为 ,但如果具有该名称的工作表,我们希望返回,因此 Not。如果你重新排列一点,它会更容易一些(但无效)TrueTrueSheetExists = sht Is Not Nothing
4赞 Henrik K 12/31/2015
需要注意的是,如果在个人宏工作簿中运行此代码,请将If wb Is Nothing Then Set wb = ThisWorkbookIf wb Is Nothing Then Set wb = ActiveWorkbook
2赞 rory.ap 3/15/2016
这是一种高效的方法(请参阅下面 Rory 回答下我对基准标记的评论),所以谁在乎批评者的想法。请注意(截至目前)您的反对票为零。
23赞 Peter Albert 1/25/2013 #2

由于检查集合的成员是一个普遍问题,以下是 @Tim 答案的抽象版本:

Function Contains(objCollection As Object, strName as String) As Boolean
    Dim o as Object
    On Error Resume Next
    set o = objCollection(strName)
    Contains = (Err.Number = 0)
    Err.Clear
 End Function

此函数可用于任何集合,如对象 (、 、 等)。ShapesRangeNamesWorkbooks

要检查工作表是否存在,请使用If Contains(Sheets, "SheetName") ...

评论

5赞 citizenkong 8/4/2014
这不会捕获集合中的原始类型,因为关键字会引发错误。我发现,与其使用 ,不如要求集合的成员适用于所有情况,即SetSetTypeNameTypeName objCollection(strName)
2赞 jeffreyweir 5/29/2015
@Peter:最好添加一些东西来清除在函数终止之前不存在的情况下会引发的错误 - err.clear 或 On Error Resume Next。否则,在如下情况下,可能会无意中触发调用过程中的错误处理。Sub Test() On Error GoTo errhandler Debug.Print Contains(Workbooks, "SomeBookThatIsNotOpen") errhandler: If Err.Number <> 0 Then Stop End Sub
0赞 Adri 9/23/2023
嗨,我无法让它与 Shapes 一起使用,错过了什么吗?
72赞 fbonetti 3/28/2013 #3

您不需要错误处理即可完成此操作。您所要做的就是遍历所有工作表并检查指定的名称是否存在:

Dim exists As Boolean

For i = 1 To Worksheets.Count
    If Worksheets(i).Name = "MySheet" Then
        exists = True
    End If
Next i

If Not exists Then
    Worksheets.Add.Name = "MySheet"
End If

评论

1赞 LePatay 6/14/2022
请注意,工作表名称不区分大小写:howtoexcel.org/how-to-check-if-a-worksheet-exists-using-vba
2赞 M1NT 8/5/2013 #4
Public Function WorkSheetExists(ByVal strName As String) As Boolean
   On Error Resume Next
   WorkSheetExists = Not Worksheets(strName) Is Nothing
End Function

sub test_sheet()

 If Not WorkSheetExists("SheetName") Then
 MsgBox "Not available"
Else MsgBox "Available"
End If

End Sub
3赞 Martin Carlsson 1/9/2014 #5

将测试放在函数中,您将能够重用它,并且具有更好的代码可读性。

不要使用“On Error Resume Next”,因为它可能与代码的其他部分冲突。

Sub DoesTheSheetExists()
    If SheetExist("SheetName") Then
        Debug.Print "The Sheet Exists"
    Else
        Debug.Print "The Sheet Does NOT Exists"
    End If
End Sub

Function SheetExist(strSheetName As String) As Boolean
    Dim i As Integer

    For i = 1 To Worksheets.Count
        If Worksheets(i).Name = strSheetName Then
            SheetExist = True
            Exit Function
        End If
    Next i
End Function
-5赞 chenaou 3/7/2014 #6

我实际上有一个简单的方法来检查工作表是否存在,然后执行一些指令:

就我而言,我想删除工作表,然后重新创建具有相同名称的相同工作表,但是如果程序无法删除该工作表,则代码会中断,因为它已被删除

Sub Foo ()

    Application.DisplayAlerts = False

    On Error GoTo instructions
    Sheets("NAME OF THE SHEET").Delete

    instructions:

    Sheets.Add After:=Sheets(Sheets.Count)
    ActiveSheet.Name = "NAME OF THE SHEET"

End Sub

评论

0赞 ChrisB 7/26/2018
这个答案的问题在于,在确定工作表确实存在时,它会被删除,因此不再存在。如果将其编写为函数,则它可能具有类似 SheetExistsAfterDeletion 的名称,并且始终返回 FALSE。
5赞 uildriks 8/3/2014 #7

我的解决方案看起来很像 Tims,但也适用于非工作表工作表 - 图表

Public Function SheetExists(strSheetName As String, Optional wbWorkbook As Workbook) As Boolean
    If wbWorkbook Is Nothing Then Set wbWorkbook = ActiveWorkbook 'or ThisWorkbook - whichever appropriate
    Dim obj As Object
    On Error GoTo HandleError
    Set obj = wbWorkbook.Sheets(strSheetName)
    SheetExists = True
    Exit Function
HandleError:
    SheetExists = False
End Function

.

2赞 ScottMcC 1/16/2015 #8

为什么不直接使用一个小循环来确定命名的工作表是否存在呢?假设您是否在当前打开的工作簿中查找名为“Sheet1”的工作表。

Dim wb as Workbook
Dim ws as Worksheet

Set wb = ActiveWorkbook

For Each ws in wb.Worksheets

    if ws.Name = "Sheet1" then
        'Do something here
    End if

Next
127赞 Rory 2/12/2015 #9

如果您只对工作表特别感兴趣,则可以使用简单的“评估”调用:

Function WorksheetExists(sName As String) As Boolean
    WorksheetExists = Evaluate("ISREF('" & sName & "'!A1)")
End Function

评论

18赞 rory.ap 3/15/2016
@Rory 我对此进行了一些基准测试,并与 Tim Williams 的答案进行了测试。超过 500,000 次循环,您的循环需要 22 秒,而 Tim 需要 <1 秒。
28赞 Rory 3/15/2016
@roryap - 如果你需要运行500,000次,你需要重新考虑你的整个方法。;)
11赞 tedcurrent 3/16/2016
@roryap - 但是,使用几种缓慢的方法将开始堆积几秒钟。我会说这是非常有价值的信息,因为 Excel“应用程序”开始使用各种 Range 方法等很容易地积累几秒钟。
5赞 tedcurrent 3/16/2016
@roryap - 这些信息在哪些方面对对话有价值?我只是说,将低效的方法分散在代码周围会使应用程序整体变慢。你测试了这 500k 次真是太棒了,我感谢你这样做,22 秒不是很好。(我同意你的看法)
8赞 Sascha L. 9/8/2017
即使它更慢,它看起来也是一个比公认的答案更干净的解决方案。+1 来自我。
18赞 Shai Alon 2/17/2015 #10

纠正:无错误处理:

Function CheckIfSheetExists(SheetName As String) As Boolean
      CheckIfSheetExists = False
      For Each WS In Worksheets
        If SheetName = WS.name Then
          CheckIfSheetExists = True
          Exit Function
        End If
      Next WS
End Function
0赞 Shai Alon 2/17/2015 #11

我做了另一件事:仅当它存在时才删除工作表 - 如果它不存在,则不会出现错误:

Excel.DisplayAlerts = False 
Dim WS
For Each WS In Excel.Worksheets
    If WS.name = "Sheet2" Then
        Excel.sheets("Sheet2").Delete
        Exit For
    End If
Next
Excel.DisplayAlerts = True
15赞 VirtualMichael 1/7/2016 #12

如果有人想避免 VBA 并测试工作表是否纯粹存在于单元格公式中,则可以使用 和 函数:ISREFINDIRECT

=ISREF(INDIRECT("SheetName!A1"))

如果工作簿包含名为 and 的工作表,则将返回此值。TRUESheetNameFALSE

1赞 MAx Segura 6/28/2016 #13

毫无疑问,上述函数可以工作,我最终得到了以下运行良好的代码:

Sub Sheet_exist ()
On Error Resume Next
If Sheets("" & Range("Sheet_Name") & "") Is Nothing Then
    MsgBox "doesnt exist"
Else
    MsgBox "exist"
End if
End sub

注意:是我要求用户输入名称的地方,所以这对你来说可能不一样。Sheets_Name

4赞 X37V 8/2/2016 #14

晚了很多年,但我只需要这样做,并且不喜欢发布的任何解决方案......所以我编了一个,这要归功于(海绵宝宝彩虹手手势)“Evaluate()”的魔力!

Evaluate("IsError(" & vSheetName & "!1:1)")

如果 Sheet 不存在,则返回 TRUE;如果工作表确实存在,则为 FALSE。 您可以用您喜欢的任何范围来代替“1:1”,但我建议不要使用单个单元格,因为如果它包含错误(例如,#N/A),它将返回 True。

评论

0赞 Sandra Rossi 2/11/2021
我在代码中看到 2 个错误:(1) 如果工作表存在,则存在错误 13,因为 (2) 如果工作表名称包含空格并且存在,则代码返回 False。为了避免 #N/A问题,我使用CELL函数。这对我有用:如果工作表不存在,这里可以退出子:1:1Evaluate("IsError(Cell(""col"",'" + vSheetName + "'!A1))")If Evaluate("IsError(Cell(""col"",'" + vSheetName + "'!A1))") Then Exit Sub
2赞 Shrikant 3/28/2017 #15
    For Each Sheet In Worksheets
    If UCase(Sheet.Name) = "TEMP" Then
    'Your Code when the match is True
        Application.DisplayAlerts = False
        Sheet.Delete
        Application.DisplayAlerts = True
    '-----------------------------------
    End If
Next Sheet
2赞 Vityata 5/23/2017 #16

如果您是非英语 Excel 的粉丝或您在非英语国家/地区工作,这是一个很好的解决方案,有效:WorksheetFunction.

WorksheetFunction.IsErr(Evaluate("'" & wsName & "'!A1"))

或者在这样的函数中:

Function WorksheetExists(sName As String) As Boolean
    WorksheetExists = Not WorksheetFunction.IsErr(Evaluate("'" & sName & "'!A1"))
End Function
1赞 gth826a 7/11/2017 #17

将“数据”更改为您要测试的任何工作表名称...

On Error Resume Next 

Set DataSheet = Sheets("Data")

If DataSheet Is Nothing Then

     Sheets.Add(after:=ActiveSheet).Name = "Data"
     ''or whatever alternate code you want to execute''
End If

On Error GoTo 0
30赞 AOBR 4/17/2018 #18

我写了这个:

Function sheetExist(sSheet As String) As Boolean
On Error Resume Next
sheetExist = (ActiveWorkbook.Sheets(sSheet).Index > 0)
End Function

评论

1赞 ChrisB 6/8/2018
很棒的功能!它不仅速度快,而且是最简洁的。
0赞 Juan Joya 12/3/2018
我相信这是最符合问题的答案
2赞 oddacorn 9/5/2019
我喜欢这个。请注意,它依赖于 sheetExist 的默认值为 False 这一事实,因为它是一个布尔函数。如果工作表不存在,赋值语句实际上不会将 False 值分配给 sheetExist,它只是出错并将默认值保留在原位。如果你愿意,你可以依靠这样一个事实,即分配给布尔变量的任何非零值都会给出一个 True 结果,而省略 > 0 比较,如下所示:sheetExist = ActiveWorkbook.Sheets(sSheet).Index
8赞 ashleedawg 5/12/2018 #19

紧凑的功能依赖错误处理!wsExists

这是一个简短的函数,它不依赖于错误处理来确定工作表是否存在(并且被正确地声明为在任何情况下都有效!

Function wsExists(wsName As String) As Boolean
    Dim ws: For Each ws In Sheets
    wsExists = (wsName = ws.Name): If wsExists Then Exit Function
    Next ws
End Function

用法示例:

下面的示例添加一个名为 的新工作表,如果该工作表尚不存在:myNewSheet

If Not wsExists("myNewSheet") Then Sheets.Add.Name = "myNewSheet"

更多信息:

-1赞 imjordy23 6/14/2018 #20

我想出了一个简单的方法来做到这一点,但我没有为它创建一个新的潜艇。相反,我只是在我正在处理的潜艇中“运行了一次检查”。假设我们要查找的工作表名称是“Sheet_Exist”,如果找到,我们只想激活它:

Dim SheetCounter As Integer

SheetCounter = 1

Do Until Sheets(SheetCounter).Name = "Sheet_Exist" Or SheetCounter = Sheets.Count + 1
 SheetCounter = SheetCounter +1
Loop
If SheetCounter < Sheets.Count + 1 Then
 Sheets("Sheet_Exist").Activate
Else
 MsgBox("Worksheet ""Sheet_Exist"" was NOT found")
End If

我还添加了一个弹出窗口,用于当工作表不存在时。

-1赞 Guest 4/4/2019 #21

我知道这是一篇旧文章,但这是另一个快速的简单解决方案。

Public Function worksheetExists(ByVal wb As Workbook, ByVal sheetNameStr As String) As Boolean

On Error Resume Next
worksheetExists = (wb.Worksheets(sheetNameStr).Name <> "")
Err.Clear: On Error GoTo 0

End Function
4赞 Excel Hero 4/3/2020 #22

短小精悍:

Function IsSheet(n$) As Boolean
    IsSheet = Not IsError(Evaluate("'" & n & "'!a1"))
End Function
0赞 Alex Johnson 7/15/2021 #23

如果需要,我使用此功能检查并返回新的工作表名称。WSname 是所需的工作表名称,WBCur 是要签入的工作簿。我使用它是因为不需要错误处理,并且可以在创建新工作表时调用它。

Public Function CheckNewWorksheetName(WSName As String, WBCur As Workbook) 'Will return New Name if needed
    Dim NewWSNum As Long, A As Integer, B As Integer, WorksheetFound As Boolean
    NewWSNum = 1
    WorksheetFound = False
    For A = 1 To WBCur.Worksheets.Count
        If WBCur.Worksheets(A).Name = WSName Then
            A = WBCur.Worksheets.Count
            WorksheetFound = True
        End If
    Next A
    
    If WorksheetFound = False Then
        CheckNewWorksheetName = WSName
    Else
        Do While WorksheetFound = True
            WorksheetFound = False
            For B = 1 To WBCur.Worksheets.Count
                If WBCur.Worksheets(B).Name = WSName & "_" & NewWSNum Then
                    B = WBCur.Worksheets.Count
                    WorksheetFound = True
                    NewWSNum = NewWSNum + 1
                End If
            Next B
        Loop
        CheckNewWorksheetName = WSName & "_" & NewWSNum
    End If
End Function
0赞 Geoff Kendall 6/10/2023 #24

无需循环或使用我能看到的函数?

如果 wkbkdestination.工作表(ThisWorkSheet.Name)。name = ThisWorksheet.Name 然后

“做事

'转到循环的末尾

如果结束