测试或检查表是否存在


115
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 

Answers:


173

有些人不喜欢这种方法,因为错误地使用了错误处理,但是我认为这在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

5
完全适合使用IMO。这是一个存在的陷阱,它假定存在并且不存在并且历史悠久-比照perl strict,STAE等。推荐
Wudang

13
可能应该使用ActiveWorkbook而不是ThisWorkbook。后者是指包含宏代码的工作簿,该宏代码可能与要测试的工作簿不同。我想ActiveWorkbook对于大多数情况都是有用的(尽管人为情况总是可用的)。
sancho.s ReinstateMonicaCellio 2014年

3
sht Is NothingTrue如果没有片使用该名称,但我们想回到True如果该名称的表,因此不。如果您重新安排一下,会容易一些(但无效)SheetExists = sht Is Not Nothing
Tim Williams

3
请注意,如果您在个人宏工作簿中运行此代码,请从更改If wb Is Nothing Then Set wb = ThisWorkbookIf wb Is Nothing Then Set wb = ActiveWorkbook
Henrik K

2
这是一种高效的方法(请参阅下面有关Rory的回答,我对基准的评论),所以谁在乎批评者的想法。请注意(截至目前)您的零首票赞成。
rory.ap

107

如果您仅对工作表特别感兴趣,可以使用一个简单的Evaluate调用:

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

14
@Rory我对蒂姆·威廉姆斯的答案进行了一些基准测试。超过500,000次循环,您的循环花费了22秒,而Tim的循环花费了<1。
rory.ap '16

17
@roryap-如果您需要运行500,000次,则需要重新考虑整个方法。;)
罗里

9
@roryap-但是,使用几种慢速方法将开始累积数秒。我会说这是非常有价值的信息,因为Excel“应用程序”开始使用各种Range方法等非常容易地累积秒数
。– tedcurrent

4
@roryap-该信息以什么方式对对话有价值?我只是在说,在代码周围散布低效的方法会使整个应用程序变慢。您测试了500k次非常棒,我感谢您这样做,22秒不是很好。(我同意你的
观点

6
即使速度较慢,它也比接受的答案看起来更干净。向我+1。
Sascha L.

49

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

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

21

由于检查集合的成员是一个普遍的问题,因此这是蒂姆答案的抽象版本:

函数包含(objCollection作为对象,strName作为字符串)作为布尔值
    暗淡为对象
    关于错误继续
    设置o = objCollection(strName)
    包含=(错误编号= 0)
    错误清除
 结束功能

此功能可与像对象的任何集合中使用(ShapesRangeNamesWorkbooks,等等)。

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


5
这不能捕获Collections中的原始类型,因为Set关键字将引发错误。我发现,而不是使用Set,要求对TypeName集合适用于所有的情况下,即成员的TypeName objCollection(strName)
citizenkong

2
@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
jeffreyweir 2015年

16

已纠正: 没有错误处理:

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

14

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

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

TRUE如果工作簿包含一个名为的工作表,则将返回SheetNameFALSE否则返回。


12

我写了这个:

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

1
功能强大!它不仅速度快,而且最简洁。
ChrisB

我相信这是最与问题相对应的答案
Juan Joya

我喜欢这一个。请注意,它依赖于这样的事实,因为sheetExist是布尔函数,所以它的默认值将为False。如果工作表不存在,则赋值语句实际上不会为工作表Exist分配False值,它只会出错并保留默认值。如果需要,您可以依靠以下事实:分配给布尔变量的任何非零值都将给出True结果,而忽略了> 0的比较,如下所示: sheetExist = ActiveWorkbook.Sheets(sSheet).Index
–odacorn

5

我的解决方案看起来很像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


3

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

不要使用“ 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

3

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

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

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


3

紧凑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"

更多信息:


2

为什么不仅仅使用一个小循环来确定命名工作表是否存在?假设您正在当前打开的工作簿中查找名为“ 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

2

如果您WorksheetFunction.是非英语国家的拥护者或您使用非英语Excel在非英语国家/地区工作,那么这是一个不错的解决方案,它可以:

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

或像这样的函数:

Function WorksheetExists(sName As String) As Boolean
    WorksheetExists = Not WorksheetFunction.IsErr(Evaluate("'" & sName & "'!A1"))
End Function

1
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

1
    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

1

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

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

1

毫无疑问,上面的功能可以正常工作,我最终得到了下面的代码,效果很好:

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是我要求用户输入名称的地方,因此这可能与您有所不同。


0

我做了另一件事:仅在工作表存在的情况下删除工作表-如果工作表不存在,则不出错:

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

0

我想出了一种简单的方法来做,但是我没有为其创建新的子对象。取而代之的是,我只是在正在处理的子程序中“运行了检查”。假设我们要查找的工作表名称为“ 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

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


0

我知道这是一个老帖子,但这是另一个快速的简单解决方案。

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

0

简短而干净:

Function IsSheet(n$) As Boolean
    IsSheet = Not IsError(Evaluate(n & "!a1"))
End Function

-4

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

在我的情况下,我想删除工作表,然后用相同的名称重新创建同一工作表,但是如果程序无法删除工作表(因为已删除工作表),则代码会中断

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

该答案的问题在于,一旦确定该工作表确实存在,便将其删除,因此不再存在。如果将此作为函数编写,则其名称可能类似于SheetExistsAfterDeletion,并且始终返回FALSE。
ChrisB
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.