Testen oder prüfen Sie, ob ein Blatt vorhanden ist

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

Grundsätzlich durchlaufe ich alle Blätter in der Ursprungsarbeitsmappe und setze sie dann destsheetin der Zielarbeitsmappe auf das Blatt mit demselben Namen wie das aktuell iterierte in der Ursprungsarbeitsmappe.

Wie kann ich testen, ob dieses Blatt vorhanden ist? Etwas wie:

If wkbkdestination.Worksheets(ThisWorkSheet.Name) Then 
yse
quelle
2
Mögliches Duplikat von Excel VBA Wenn WorkSheet ("wsName") vorhanden ist
sancho.s ReinstateMonicaCellio

Antworten:

173

Einige Leute mögen diesen Ansatz nicht, weil die Fehlerbehandlung "unangemessen" verwendet wird, aber ich denke, dass er in VBA als akzeptabel angesehen wird ... Ein alternativer Ansatz besteht darin, alle Blätter zu durchlaufen, bis Sie eine Übereinstimmung finden.

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
Tim Williams
quelle
5
Verwenden Sie IMO vollständig. Es ist eine Falle für eine Sache, die als existent gesetzt wird und nicht existiert und eine lange Geschichte hat - siehe Perl Strict, STAE usw. Upvoted
Wudang
13
Man sollte wohl ActiveWorkbookstatt verwenden ThisWorkbook. Letzteres bezieht sich auf die Arbeitsmappe, die den Makrocode enthält, der sich möglicherweise von der Arbeitsmappe unterscheidet, die getestet werden soll. Ich denke, ActiveWorkbookwäre in den meisten Fällen nützlich (erfundene Situationen sind jedoch immer verfügbar).
sancho.s ReinstateMonicaCellio
3
sht Is Nothingwird , Truewenn mit diesem Namen kein Blatt gibt es, aber wir wollen zurückkehren , Truewenn es ist ein Blatt mit diesem Namen, damit die nicht. Es ist ein wenig einfacher (aber nicht gültig), wenn Sie ein wenig neu arrangierenSheetExists = sht Is Not Nothing
Tim Williams
3
Gut zu beachten , dass , wenn Sie diesen Code in Ihrer persönlichen Makro - Arbeitsmappe ausführen, Wechsel von If wb Is Nothing Then Set wb = ThisWorkbookzuIf wb Is Nothing Then Set wb = ActiveWorkbook
Henrik K
2
Dies ist ein hocheffizienter Ansatz (siehe meine Kommentare zu Benchmarks unter Rorys Antwort unten). Wen interessiert es also, was die Kritiker denken? Beachten Sie (ab sofort), dass Sie keine Stimmen mehr haben.
rory.ap
107

Wenn Sie sich speziell nur für Arbeitsblätter interessieren, können Sie einen einfachen Evaluate-Aufruf verwenden:

Function WorksheetExists(sName As String) As Boolean
    WorksheetExists = Evaluate("ISREF('" & sName & "'!A1)")
End Function
Rory
quelle
14
@Rory Ich habe einige Benchmark-Tests zu dieser Antwort gegen Tim Williams durchgeführt. Über 500.000 Loops dauerten 22 Sekunden und Tims <1.
rory.ap
17
@roryap - Wenn Sie dies 500.000 Mal ausführen müssen, müssen Sie Ihren gesamten Ansatz überdenken. ;)
Rory
9
@roryap - Wenn Sie jedoch mehrere langsame Methoden verwenden, häufen sich die Sekunden. Ich würde sagen, dass dies äußerst wertvolle Informationen sind, da Excel- "Anwendungen" mit verschiedenen Range-Methoden usw. ziemlich leicht Sekunden
sammeln können
4
@roryap - auf welche Weise sind diese Informationen für das Gespräch wertvoll? Ich sage nur, dass das Verteilen ineffizienter Methoden um Ihren Code die Anwendung insgesamt verlangsamt. Sie testen diese 500k mal ist großartig und ich danke Ihnen dafür, 22 Sekunden sind nicht großartig. (Ich stimme Ihnen zu)
Tedcurrent
6
Selbst wenn es langsamer ist, sieht es nach einer viel saubereren Lösung aus als die akzeptierte Antwort. +1 von mir.
Sascha L.
49

Sie benötigen keine Fehlerbehandlung, um dies zu erreichen. Sie müssen lediglich alle Arbeitsblätter durchlaufen und prüfen, ob der angegebene Name vorhanden ist:

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
Fbonetti
quelle
21

Da die Suche nach Mitgliedern einer Sammlung ein allgemeines Problem darstellt, finden Sie hier eine abstrahierte Version von Tims Antwort:

Funktion enthält (objCollection As Object, strName as String) als Boolean
    Dim o als Objekt
    On Error Resume Next
    set o = objCollection (strName)
    Enthält = (Err.Number = 0)
    Err.Clear
 Endfunktion

Diese Funktion kann mit jeder Sammlung wie Objekt verwendet werden ( Shapes, Range, Names, Workbooks, etc.).

Verwenden Sie, um das Vorhandensein eines Blattes zu überprüfen If Contains(Sheets, "SheetName") ...

Peter Albert
quelle
5
Dies fängt keine primitiven Typen in Sammlungen ab, da das SetSchlüsselwort einen Fehler auslöst. Ich fand, dass anstatt zu verwenden Set, nach dem TypeNameMitglied der Sammlung Werke für alle Fälle zu TypeName objCollection(strName)
fragen
2
@Peter: Fügen Sie am besten etwas hinzu, um den Fehler zu beheben, der im Falle einer Nichtexistenz auftritt, bevor die Funktion beendet wird - entweder ein err.clear oder On Error Resume Next. Andernfalls könnte die Fehlerbehandlung in der aufrufenden Prozedur in folgenden Fällen versehentlich ausgelöst werden. Sub Test() On Error GoTo errhandler Debug.Print Contains(Workbooks, "SomeBookThatIsNotOpen") errhandler: If Err.Number <> 0 Then Stop End Sub
Jeffreyweir
16

Korrigiert: Ohne Fehlerbehandlung:

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
Shai Alon
quelle
14

Wenn jemand VBA vermeiden und testen möchte, ob ein Arbeitsblatt nur in einer Zellformel vorhanden ist, ist dies mit den Funktionen ISREFund möglich INDIRECT:

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

Dies wird zurückkehren , TRUEwenn die Arbeitsmappe ein Blatt namens enthält SheetNameund aus FALSEanderen Gründen .

VirtualMichael
quelle
12

Ich habe diesen geschrieben:

Function sheetExist(sSheet As String) As Boolean
On Error Resume Next
sheetExist = (ActiveWorkbook.Sheets(sSheet).Index > 0)
End Function
AOBR
quelle
1
Tolle Funktion! Es ist nicht nur schnell, sondern auch am prägnantesten.
ChrisB
Ich glaube, dies ist die Antwort, die der Frage am meisten entspricht
Juan Joya
Ich mag diesen. Beachten Sie, dass dies auf der Tatsache beruht, dass der Standardwert für sheetExist False ist, da es sich um eine boolesche Funktion handelt. Die Zuweisungsanweisung weist sheetExist keinen falschen Wert zu, wenn das Blatt nicht vorhanden ist. Es gibt nur Fehler aus und belässt den Standardwert. Wenn Sie möchten, können Sie sich darauf verlassen, dass jeder Wert ungleich Null, der einer booleschen Variablen zugewiesen wird, ein True-Ergebnis sheetExist = ActiveWorkbook.Sheets(sSheet).Index
liefert
5

Meine Lösung ähnelt Tims, funktioniert aber auch bei Nicht-Arbeitsblatt-Blättern - Diagrammen

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

.

uildriks
quelle
3

Wenn Sie den Test in eine Funktion einfügen, können Sie ihn wiederverwenden und haben eine bessere Lesbarkeit des Codes.

Verwenden Sie NICHT "On Error Resume Next", da dies zu Konflikten mit anderen Teilen Ihres Codes führen kann.

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
Martin Carlsson
quelle
3

Viele Jahre zu spät, aber ich musste das nur tun und mochte keine der veröffentlichten Lösungen ... Also habe ich mir eine ausgedacht, alles dank der Magie von (SpongeBob Regenbogen Hände Geste) "Evaluate ()"!

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

Gibt TRUE zurück, wenn Sheet NICHT vorhanden ist. FALSE wenn Blatt existiert. Sie können "1: 1" durch einen beliebigen Bereich ersetzen. Ich rate jedoch davon ab, eine einzelne Zelle zu verwenden. Wenn sie einen Fehler enthält (z. B. # N / A), wird True zurückgegeben.

X37V
quelle
3

Kompakte wsExistsFunktion ( ohne auf Fehlerbehandlung angewiesen zu sein!)

Hier ist eine kurze und einfache Funktion, die sich nicht auf die Fehlerbehandlung stützt, um festzustellen, ob ein Arbeitsblatt vorhanden ist ( und in jeder Situation ordnungsgemäß als funktionsfähig deklariert ist !).

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

Anwendungsbeispiel:

Im folgenden Beispiel wird ein neues Arbeitsblatt mit dem Namen hinzugefügt myNewSheet, sofern es noch nicht vorhanden ist:

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

Mehr Informationen:

ashleedawg
quelle
2

Warum nicht einfach eine kleine Schleife verwenden, um festzustellen, ob das genannte Arbeitsblatt vorhanden ist? Angenommen, Sie haben in der aktuell geöffneten Arbeitsmappe nach einem Arbeitsblatt mit dem Namen "Sheet1" gesucht.

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
ScottMcC
quelle
2

Wenn Sie ein Fan von WorksheetFunction.oder nicht aus einem nicht englischen Land mit einem nicht englischen Excel arbeiten, ist dies eine gute Lösung, die funktioniert:

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

Oder in einer Funktion wie dieser:

Function WorksheetExists(sName As String) As Boolean
    WorksheetExists = Not WorksheetFunction.IsErr(Evaluate("'" & sName & "'!A1"))
End Function
Vityata
quelle
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
Philipp88
quelle
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
Shrikant
quelle
1

Ändern Sie "Daten" in den Blattnamen, auf den Sie testen ...

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
gth826a
quelle
1

Ohne Zweifel, dass die obige Funktion funktionieren kann, habe ich gerade den folgenden Code erhalten, der ziemlich gut funktioniert:

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

Hinweis: Sheets_NameHier fordere ich den Benutzer auf, den Namen einzugeben, damit dies für Sie möglicherweise nicht identisch ist.

MAx Segura
quelle
0

Ich habe eine andere Sache gemacht: Löschen Sie ein Blatt nur, wenn es existiert - um keinen Fehler zu erhalten, wenn es nicht existiert:

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
Shai Alon
quelle
0

Ich habe mir einen einfachen Weg ausgedacht, aber ich habe kein neues Sub dafür erstellt. Stattdessen habe ich in dem U-Boot, an dem ich gearbeitet habe, nur eine Überprüfung durchgeführt. Angenommen, der gesuchte Blattname ist "Sheet_Exist" und wir möchten ihn nur aktivieren, wenn er gefunden wird:

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

Ich habe auch ein Popup hinzugefügt, wenn das Blatt nicht vorhanden ist.

imjordy23
quelle
0

Ich weiß, dass es ein alter Beitrag ist, aber hier ist eine andere einfache Lösung, die schnell ist.

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
Gast
quelle
0

Kurz und sauber:

Function IsSheet(n$) As Boolean
    IsSheet = Not IsError(Evaluate(n & "!a1"))
End Function
Excel Hero
quelle
-4

Ich hatte tatsächlich eine einfache Möglichkeit, zu überprüfen, ob das Blatt vorhanden ist, und dann eine Anweisung auszuführen:

In meinem Fall wollte ich das Blatt löschen und habe dann dasselbe Blatt mit demselben Namen neu erstellt, aber der Code wurde unterbrochen, wenn das Programm das Blatt nicht löschen konnte, da es bereits gelöscht wurde

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
Chenaou
quelle
Das Problem bei dieser Antwort besteht darin, dass das Blatt nach Feststellung, dass es tatsächlich vorhanden war, gelöscht wird und daher nicht mehr vorhanden ist. Wenn dies als Funktion geschrieben würde, könnte es einen Namen wie SheetExistsAfterDeletion haben und würde immer FALSE zurückgeben.
ChrisB