Проверьте или проверьте, существует ли лист

74
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
excel
scripting

20 ответов

127
Лучший ответ

Некоторым людям не нравится этот подход из-за "неулокального" использования обработки ошибок, но я считаю, что он считается приемлемым в VBA... Альтернативный подход состоит в том, чтобы зацикливать все листы, пока вы не найдете совпадение.

 Function SheetExists(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
     SheetExists = Not sht Is Nothing
 End Function
  • 5
    Целиком ценим использование ИМО. Это ловушка для вещи, которая позиционируется как существующая и не имеет, и имеет долгую историю - ср строгий perl, STAE и т. Д.
  • 9
    Вероятно, следует использовать ActiveWorkbook вместо ThisWorkbook . Последнее относится к книге, содержащей код макроса, который может отличаться от книги, чем кто-либо хочет проверить. Я предполагаю, что ActiveWorkbook был бы полезен в большинстве случаев (однако, всегда существуют надуманные ситуации).
Показать ещё 11 комментариев
78

Если вас интересуют только рабочие листы, вы можете использовать простой вызов Evaluate:

Function WorksheetExists(sName As String) As Boolean
    WorksheetExists = Evaluate("ISREF('" & sName & "'!A1)")
End Function
  • 2
    ++ Еще один хороший!
  • 0
    Вам не нужно указывать рабочую книгу?
Показать ещё 11 комментариев
32

Для этого вам не нужна обработка ошибок. Все, что вам нужно сделать, это перебрать все листы и проверить, существует ли указанное имя:

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

Поскольку проверка элементов коллекции является общей проблемой, вот абстрагированная версия ответа Тима:

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

Эта функция может использоваться с любым объектом, подобным коллекции (Shapes, Range, Names, Workbooks и т.д.).

Чтобы проверить наличие листа, используйте If Contains(Sheets, "SheetName") ...

  • 5
    Это не перехватывает примитивные типы в коллекциях, так как ключевое слово Set вызывает ошибку. Я обнаружил, что вместо использования Set , запрос TypeName члена коллекции работает для всех случаев, т.е. TypeName objCollection(strName)
  • 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
12

Исправлено: Без обработки ошибок:

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
10

В случае, если кто-то хочет избежать VBA и проверить, существует ли рабочая таблица исключительно внутри формулы ячейки, возможно использование функций ISREF и INDIRECT:

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

Это вернет TRUE, если книга содержит лист с именем SheetName и FALSE в противном случае.

4

Мое решение очень похоже на 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

Если вы являетесь поклонником WorksheetFunction. или работаете в неанглийской стране с неанглийским Excel, это хорошее решение, которое работает:

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

Или в такой функции:

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

Поместите тест в функцию, и вы сможете его повторно использовать, и у вас будет более хорошая читаемость кода.

НЕ используйте "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
1

Я написал это:

Function sheetExist(sSheet As String) As Boolean
On Error Resume Next
sheetExist = (ActiveWorkbook.Sheets(sSheet).Index > 0)
End Function
  • 0
    Отличная функция! Это не только быстро, но и максимально лаконично.
  • 0
    Я считаю, что это ответ, который соответствует вопросу наиболее
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
    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

Много лет поздно, но мне просто нужно было это сделать, и мне не понравилось, что какие-либо решения были отправлены... Итак, я сделал все, благодаря магии (жестом в форме радуги SpongeBob) "Evaluate()"

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

Возвращает TRUE, если лист НЕ существует; FALSE, если лист существует. Вы можете заменить любой диапазон, который вам нравится, на "1:1", но я советую не использовать одну ячейку, потому что если он содержит ошибку (например, # N/A), он вернет True.

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 - это то, где я прошу пользователя ввести имя, так что это может быть не для вас.

1

Я сделал другое: удалите лист только в том случае, если он существует - не получить ошибку, если это не так:

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
1

Почему бы просто не использовать небольшой цикл, чтобы определить, существует ли именованный лист? Скажем, если вы искали Рабочую таблицу с именем "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
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
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

Функция Compact 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"

Больше информации:

-3

У меня действительно был простой способ проверить, существует ли лист, а затем выполнить некоторую инструкцию:

В моем случае я хотел удалить лист, а затем воссоздал один и тот же лист с тем же именем, но код был прерван, если программа не смогла удалить лист, поскольку он уже был удален.

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
    Проблема с этим ответом состоит в том, что после определения того, что лист действительно существует, он удаляется и, следовательно, больше не существует. Если бы это было написано как функция, оно могло бы иметь имя типа SheetExistsAfterDeletion и всегда возвращало бы FALSE.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню