Перевірте чи перевірте, чи існує аркуш


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 

Відповіді:


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
Цілком доречно використовувати ІМО. Це пастка для речі, яка розміщується як існуюча і не має і має довгу історію - cf perl строгий, STAE і т. Д. Upvoted
Wudang

13
Напевно, слід використовувати ActiveWorkbookзамість цього ThisWorkbook. Остання стосується робочої книги, що містить макрокод, який може відрізнятися від робочої книги, ніж те, що хочеться перевірити. Я думаю, це ActiveWorkbookбуло б корисно у більшості випадків (хоча надумані ситуації завжди доступні).
sancho.s ReinstateMonicaCellio

3
sht Is Nothingбуде, Trueякщо немає аркуша з цим іменем, але ми хочемо повернутись, Trueякщо є аркуш з таким ім'ям, отже, Не. Трохи простіше (але не вірно), якщо ви трохи домовитесь про цеSheetExists = sht Is Not Nothing
Тім Вільямс

3
Приємно зауважити, що якщо ви запускаєте цей код у своїй особистій макроробочій книжці, перейдіть If wb Is Nothing Then Set wb = ThisWorkbookнаIf wb Is Nothing Then Set wb = ActiveWorkbook
Генрік К

2
Це високоефективний підхід (дивіться мої коментарі щодо бальних оцінок під відповіддю Рорі нижче), тож кому все одно, що думають зловмисники. Зауважте (на даний момент) у вас є нульові голоси.
rory.ap

107

Якщо ви зацікавлені лише в робочих аркушах, ви можете скористатися простим викликом оцінювання:

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

14
@ Рорі Я провів кілька тестових тестів на цю відповідь проти відповіді Тіма Вільямса. Більше 500 000 циклів, вашим знадобилося 22 секунди, а Тиму <1.
rory.ap

17
@roryap - якщо вам потрібно виконати це 500 000 разів, вам потрібно переосмислити весь свій підхід. ;)
Рорі

9
@roryap - однак використання декількох повільних методів почне накопичувати секунди. Я б сказав, що це надзвичайно цінна інформація, оскільки "додатки" Excel починають набирати секунди досить легко за допомогою різних методів діапазону тощо.
тиждень

4
@roryap - яка інформація цінна для розмови, яким чином? Я просто констатую, що розсіювання неефективних методів навколо вашого коду зробить додаток повільним у цілому. ти тестуєш це 500 тис. разів дивовижно, і я дякую тобі за це, 22 секунди - це не чудово. (Я згоден з вами)
понеділок

6
Навіть якщо це повільніше, це виглядає набагато чистішим рішенням, ніж прийнята відповідь. +1 від мене.
Саша Л.

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 As Object, strName як String) як булева
    Dim o як об’єкт
    Про помилку Відновіть далі
    set o = objCollection (strName)
    Містить = (Err.Number = 0)
    Err.Clear
 Кінцева функція

Ця функція може бути використана з будь-колекцією як об'єкт ( Shapes, Range, Names, Workbooksі т.д.).

Щоб перевірити наявність аркуша, використовуйте If Contains(Sheets, "SheetName") ...


5
Це не вловлює примітивні типи в колекціях, оскільки помилка буде викликана Setключовим словом. Я виявив, що замість того, щоб використовувати Set, просити TypeNameчлена колекції працює у всіх випадках, тобтоTypeName objCollection(strName)
Citizenkong

2
@Peter: Найкраще додати щось, щоб очистити помилку, яка виникне у випадку відсутності до припинення функціонування - або помилка ядра, або 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

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 і перевірити, чи існує робочий аркуш виключно у формулі комірки, можливо, використовуючи ISREFі INDIRECTфункції:

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

Це повернеться, TRUEякщо робоча книжка містить аркуш, який називається SheetNameта FALSEінше.


12

Я написав це:

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

1
Відмінна функція! Він не тільки швидкий, але й самий стислий.
ChrisB

Я вважаю, що це відповідь, яка найбільше відповідає на питання
Хуан Джоя

Мені це подобається. Зауважте, що він покладається на той факт, що значення за замовчуванням для sheetExist буде помилковим, оскільки це булева функція. Оператор присвоєння насправді не присвоює помилковому значенню sheetExist, якщо аркуша не існує, він просто помиляється і залишає значення за замовчуванням на місці. Якщо ви хочете, ви можете розраховувати на те, що будь-яке ненульове значення, присвоєне булевій змінній, дасть істинний результат і вийде із порівняння> 0, наприклад так: sheetExist = ActiveWorkbook.Sheets(sSheet).Index
oddacorn

5

Моє рішення схоже на Тімс, але також працює у випадку не аркушів аркушів - діаграм

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("IsError(" & vSheetName & "!1:1)")

Повертає ІСТИНА, якщо аркуша НЕ існує; НЕМАЛЬНО, якщо аркуш НЕ існує. Ви можете замінити будь-який діапазон, який вам подобається, на "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

Чому б не просто використати невеликий цикл, щоб визначити, чи існує названий аркуш? Скажіть, якщо ви шукали робочий аркуш під назвою "Аркуш1" у відкритій в даний час робочій книжці.

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.