Prova o controlla se il foglio esiste


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

Fondamentalmente faccio scorrere tutti i fogli nella cartella di lavoro di origine, quindi imposto destsheetnella cartella di lavoro di destinazione al foglio con lo stesso nome di quello attualmente iterato nella cartella di lavoro di origine.

Come posso verificare se quel foglio esiste? Qualcosa di simile a:

If wkbkdestination.Worksheets(ThisWorkSheet.Name) Then 

Risposte:


173

Ad alcune persone questo approccio non piace a causa di un uso "inappropriato" della gestione degli errori, ma penso che sia considerato accettabile in VBA ... Un approccio alternativo consiste nel ripetere tutti i fogli fino a trovare una corrispondenza.

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
Uso completamente appropriato IMO. È una trappola per una cosa che viene postulata come esistente e non ha una lunga storia - cf perl strict, STAE ecc. Upvoted
Wudang

13
Uno dovrebbe probabilmente usare ActiveWorkbookinvece di ThisWorkbook. Quest'ultimo si riferisce alla cartella di lavoro che contiene il codice della macro, che potrebbe essere diversa dalla cartella di lavoro di quanto si voglia testare. Immagino che ActiveWorkbooksarebbe utile per la maggior parte dei casi (le situazioni artificiose sono sempre disponibili, però).
sancho.s ReinstateMonicaCellio

3
sht Is Nothingsarà Truese non c'è nessun foglio con quel nome, ma vogliamo tornare Truese v'è un foglio con quel nome, da cui il Not. È un po 'più facile (ma non valido) se riorganizzi un po' perSheetExists = sht Is Not Nothing
Tim Williams

3
È interessante notare che se esegui questo codice nella tua cartella di lavoro macro personale, cambia da If wb Is Nothing Then Set wb = ThisWorkbookaIf wb Is Nothing Then Set wb = ActiveWorkbook
Henrik K

2
Questo è un approccio altamente efficiente (vedi i miei commenti sui punti di riferimento sotto la risposta di Rory di seguito), quindi chi se ne frega di cosa pensano i detrattori. Nota (al momento) hai zero voti negativi.
rory.ap

107

Se sei specificamente interessato solo ai fogli di lavoro, puoi utilizzare una semplice chiamata di valutazione:

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

14
@Rory Ho eseguito alcuni test di benchmark su questa risposta rispetto a Tim Williams. Oltre 500.000 loop, il tuo ha impiegato 22 secondi e quello di Tim <1.
rory.ap

17
@roryap: se è necessario eseguirlo 500.000 volte, è necessario ripensare l'intero approccio. ;)
Rory

9
@roryap - tuttavia, l'utilizzo di diversi metodi lenti inizierà ad accumulare secondi. Direi che si tratta di informazioni estremamente preziose, poiché le "applicazioni" di Excel iniziano a accumulare secondi abbastanza facilmente con vari metodi di intervallo, ecc.
tedcurrent

4
@roryap: queste informazioni sono preziose per la conversazione in che modo? Sto semplicemente affermando che la diffusione di metodi inefficienti attorno al codice renderà l'applicazione lenta nel suo complesso. provare questo 500k volte è fantastico e ti ringrazio per averlo fatto, 22 secondi non sono eccezionali. (Sono d'accordo con te)
tedcurrent

6
Anche se è più lenta, sembra una soluzione molto più pulita della risposta accettata. +1 da me.
Sascha L.

49

Non è necessaria la gestione degli errori per eseguire questa operazione. Tutto quello che devi fare è iterare su tutti i fogli di lavoro e verificare se il nome specificato esiste:

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

Poiché il controllo dei membri di una raccolta è un problema generale, ecco una versione astratta della risposta di Tim:

La funzione contiene (objCollection As Object, strName as String) As Boolean
    Dim o come oggetto
    In caso di errore, riprendi dopo
    impostare o = objCollection (strName)
    Contiene = (Err.Number = 0)
    Err.Clear
 Fine funzione

Questa funzione può essere utilizzata con qualsiasi raccolta come oggetto ( Shapes, Range, Names, Workbooks, ecc).

Per verificare l'esistenza di un foglio, utilizzare If Contains(Sheets, "SheetName") ...


5
Questo non cattura i tipi primitivi nelle raccolte poiché verrà generato un errore dalla Setparola chiave. Ho scoperto che invece di usare Set, chiedere TypeNameil membro della raccolta funziona per tutti i casi, cioèTypeName objCollection(strName)
citizenkong

2
@Peter: meglio aggiungere qualcosa per cancellare l'errore che verrà sollevato in caso di inesistenza prima che la funzione termini - o un err.clear o On Error Resume Next. In caso contrario, la gestione degli errori nella procedura chiamante potrebbe essere attivata inavvertitamente in casi come i seguenti. Sub Test() On Error GoTo errhandler Debug.Print Contains(Workbooks, "SomeBookThatIsNotOpen") errhandler: If Err.Number <> 0 Then Stop End Sub
jeffreyweir

16

Corretto: senza gestione degli errori:

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

Nel caso in cui qualcuno desideri evitare VBA e verificare se un foglio di lavoro esiste esclusivamente all'interno di una formula di cella, è possibile utilizzare le funzioni ISREFe INDIRECT:

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

Questo tornerà TRUEse la cartella di lavoro contiene un foglio chiamato SheetNamee in caso FALSEcontrario.


12

Ho scritto questo:

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

1
Grande funzione! Non solo è veloce, è anche il più conciso.
ChrisB

Credo che questa sia la risposta che corrisponde di più alla domanda
Juan Joya

Mi piace questa. Si noti che si basa sul fatto che il valore predefinito per sheetExist sarà False poiché è una funzione booleana. L'istruzione di assegnazione in realtà non assegna un valore False a sheetExist se il foglio non esiste, si limita a sbagliare e lascia il valore predefinito al suo posto. Se lo desideri, puoi fare affidamento sul fatto che qualsiasi valore diverso da zero assegnato a una variabile booleana darà un risultato Vero e tralascia il confronto> 0, in questo modo: sheetExist = ActiveWorkbook.Sheets(sSheet).Index
oddacorn

5

La mia soluzione assomiglia molto a Tims ma funziona anche in caso di fogli non di lavoro: i grafici

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

Metti il ​​test in una funzione e sarai in grado di riutilizzarlo e avrai una migliore leggibilità del codice.

NON utilizzare "On Error Resume Next" poiché potrebbe essere in conflitto con altre parti del codice.

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

Molti anni di ritardo, ma avevo solo bisogno di farlo e non mi è piaciuta nessuna delle soluzioni postate ... Così ne ho inventata una, tutto grazie alla magia di (gesto delle mani arcobaleno di SpongeBob) "Evaluate ()"!

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

Restituisce VERO se il foglio NON esiste; FALSO se il foglio ESISTE. Puoi sostituire "1: 1" con qualsiasi intervallo tu voglia, ma sconsiglio di utilizzare una singola cella, perché se contiene un errore (ad esempio, # N / A), restituirà True.


3

wsExistsFunzione compatta ( senza fare affidamento sulla gestione degli errori!)

Ecco una funzione breve e semplice che non si basa sulla gestione degli errori per determinare se esiste un foglio di lavoro ( ed è correttamente dichiarato per funzionare in qualsiasi situazione!)

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

Utilizzo di esempio:

L'esempio seguente aggiunge un nuovo foglio di lavoro denominato myNewSheet, se non esiste già:

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

Maggiori informazioni:


2

Perché non utilizzare solo un piccolo ciclo per determinare se il foglio di lavoro denominato esiste? Di 'se stavi cercando un foglio di lavoro denominato "Foglio1" nella cartella di lavoro attualmente aperta.

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

Se sei un fan di WorksheetFunction.o lavori da un paese non inglese con un Excel non inglese questa è una buona soluzione, che funziona:

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

O in una funzione come questa:

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

Cambia "Dati" con il nome del foglio che stai testando ...

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

Senza alcun dubbio che la funzione di cui sopra può funzionare, ho appena finito con il seguente codice che funziona abbastanza bene:

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

Nota: Sheets_Nameè qui che chiedo all'utente di inserire il nome, quindi potrebbe non essere lo stesso per te.


0

Ho fatto un'altra cosa: eliminare un foglio solo se esiste, per non ottenere un errore in caso contrario:

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

Ho trovato un modo semplice per farlo, ma non ho creato un nuovo sottotitolo per questo. Invece, ho semplicemente "eseguito un controllo" all'interno del sottotitolo su cui stavo lavorando. Supponendo che il nome del foglio che stiamo cercando sia "Sheet_Exist" e vogliamo solo attivarlo se trovato:

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

Ho anche aggiunto un pop-up per quando il foglio non esiste.


0

So che è un vecchio post, ma ecco un'altra semplice soluzione veloce.

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

Breve e pulito:

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

-4

In realtà avevo un modo semplice per verificare se il foglio esiste e quindi eseguire alcune istruzioni:

Nel mio caso volevo cancellare il foglio e poi ricreare lo stesso foglio con lo stesso nome ma il codice veniva interrotto se il programma non era in grado di cancellare il foglio in quanto era già cancellato

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

Il problema con questa risposta è che dopo aver determinato che il foglio esisteva effettivamente, viene eliminato e quindi non esiste più. Se fosse scritto come una funzione, potrebbe avere un nome come SheetExistsAfterDeletion e restituirebbe sempre FALSE.
ChrisB
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.