Tester ou vérifier si la feuille existe

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

Fondamentalement, je boucle sur toutes les feuilles du classeur d'origine puis définissez destsheet dans le classeur de destination la feuille portant le même nom que celui actuellement itéré dans le classeur d'origine.

Comment puis-je tester si cette feuille existe? Quelque chose comme:

If wkbkdestination.Worksheets(ThisWorkSheet.Name) Then 
oui
la source
2
duplication possible d' Excel VBA si la feuille de travail ("wsName") existe
sancho.s ReinstateMonicaCellio

Réponses:

173

Certaines personnes n'aiment pas cette approche en raison d'une utilisation "inappropriée" de la gestion des erreurs, mais je pense qu'elle est considérée comme acceptable dans VBA ... Une autre approche consiste à parcourir toutes les feuilles jusqu'à ce que vous trouviez une correspondance.

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
la source
5
Utilisation tout à fait appropriée IMO. C'est un piège pour une chose qui est postulée comme existante et qui n'a pas et qui a une longue histoire - cf perl strict, STAE etc. Vote positif
Wudang
13
On devrait probablement utiliser à la ActiveWorkbookplace de ThisWorkbook. Ce dernier fait référence au classeur qui contient le code de macro, qui peut être différent du classeur que l'on souhaite tester. Je suppose que ce ActiveWorkbookserait utile dans la plupart des cas (les situations artificielles sont toujours disponibles, cependant).
sancho.s ReinstateMonicaCellio
3
sht Is Nothingsera Trues'il n'y a pas de feuille avec ce nom, mais nous voulons revenir Trues'il est une feuille avec ce nom, d' où le non. C'est un peu plus facile (mais pas valide) si vous réorganisez un peu pourSheetExists = sht Is Not Nothing
Tim Williams
3
Il est bon de noter que si vous exécutez ce code dans votre classeur de macros personnelles, passez de If wb Is Nothing Then Set wb = ThisWorkbookàIf wb Is Nothing Then Set wb = ActiveWorkbook
Henrik K
2
C'est une approche très efficace (voir mes commentaires sur les points de repère sous la réponse de Rory ci-dessous), alors qui se soucie de ce que pensent les détracteurs. Notez (pour l'instant) que vous n'avez aucun vote contre.
rory.ap
107

Si vous êtes spécifiquement intéressé par les feuilles de calcul uniquement, vous pouvez utiliser un simple appel Evaluate:

Function WorksheetExists(sName As String) As Boolean
    WorksheetExists = Evaluate("ISREF('" & sName & "'!A1)")
End Function
Rory
la source
14
@Rory J'ai effectué des tests de référence sur cette réponse par rapport à la réponse de Tim Williams. Plus de 500 000 boucles, la vôtre a pris 22 secondes et celle de Tim a pris <1.
rory.ap
17
@roryap - si vous devez l'exécuter 500 000 fois, vous devez repenser l'ensemble de votre approche. ;)
Rory
9
@roryap - cependant, l'utilisation de plusieurs méthodes lentes commencera à accumuler des secondes. Je dirais que ce sont des informations extrêmement précieuses, car les "applications" Excel commencent à accumuler des secondes assez facilement avec diverses méthodes de plage, etc.
tedcurrent
4
@roryap - cette information est-elle précieuse pour la conversation de quelle manière? Je dis simplement que la dispersion de méthodes inefficaces autour de votre code rendra l'application lente dans son ensemble. Tester ces 500 000 fois est génial et je vous remercie de l'avoir fait, 22 secondes, ce n'est pas génial. (Je suis d'accord avec vous)
tedcurrent
6
Même si c'est plus lent, cela ressemble à une solution beaucoup plus propre que la réponse acceptée. +1 de moi.
Sascha L.
49

Vous n'avez pas besoin de gestion des erreurs pour ce faire. Tout ce que vous avez à faire est de parcourir toutes les feuilles de calcul et de vérifier si le nom spécifié existe:

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
la source
21

La vérification des membres d'une collection étant un problème général, voici une version abstraite de la réponse de Tim:

Function Contains (objCollection As Object, strName as String) As Boolean
    Dim o comme objet
    En cas d'erreur Reprendre suivant
    set o = objCollection (strName)
    Contient = (Err.Number = 0)
    Err.Clear
 Fonction de fin

Cette fonction peut être utilisée avec toute collection comme objet ( Shapes, Range, Names, Workbooks, etc.).

Pour vérifier l'existence d'une feuille, utilisez If Contains(Sheets, "SheetName") ...

Peter Albert
la source
5
Cela n'attrape pas les types primitifs dans les collections car une erreur sera déclenchée par le Setmot clé. J'ai trouvé que plutôt que d'utiliser Set, demander TypeNamele membre de la collection fonctionne pour tous les cas, c'estTypeName objCollection(strName)
citizenkong
2
@Peter: Il est préférable d'ajouter quelque chose pour effacer l'erreur qui se produira en cas de non-existence avant la fin de la fonction - soit un err.clear ou On Error Resume Next. Sinon, la gestion des erreurs dans la procédure d'appel pourrait être déclenchée par inadvertance dans les cas suivants. Sub Test() On Error GoTo errhandler Debug.Print Contains(Workbooks, "SomeBookThatIsNotOpen") errhandler: If Err.Number <> 0 Then Stop End Sub
jeffreyweir
16

Corrigé: sans gestion des erreurs:

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
la source
14

Au cas où quelqu'un voudrait éviter VBA et tester si une feuille de calcul existe uniquement dans une formule de cellule, il est possible d'utiliser les fonctions ISREFet INDIRECT:

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

Cela reviendra TRUEsi le classeur contient une feuille appelée SheetNameet FALSEautrement.

VirtualMichael
la source
12

J'ai écrit celui-ci:

Function sheetExist(sSheet As String) As Boolean
On Error Resume Next
sheetExist = (ActiveWorkbook.Sheets(sSheet).Index > 0)
End Function
AOBR
la source
1
Excellente fonction! Non seulement c'est rapide, mais c'est aussi le plus concis.
ChrisB
Je crois que c'est la réponse qui correspond le plus à la question
Juan Joya
J'aime celui la. Notez qu'il repose sur le fait que la valeur par défaut de sheetExist sera False car il s'agit d'une fonction booléenne. L'instruction d'affectation n'affecte pas réellement une valeur False à sheetExist si la feuille n'existe pas, elle se contente d'erreurs et laisse la valeur par défaut en place. Si vous le souhaitez, vous pouvez vous fier au fait que toute valeur non nulle affectée à une variable booléenne donnera un résultat True et sheetExist = ActiveWorkbook.Sheets(sSheet).Index
omettra la
5

Ma solution ressemble beaucoup à Tims mais fonctionne également en cas de feuilles sans feuille de calcul - graphiques

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
la source
3

Mettez le test dans une fonction et vous pourrez le réutiliser et vous aurez une meilleure lisibilité du code.

N'utilisez PAS le "On Error Resume Next" car il peut entrer en conflit avec une autre partie de votre code.

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
la source
3

Plusieurs années de retard, mais j'avais juste besoin de le faire et je n'ai aimé aucune des solutions affichées ... Alors j'en ai inventé une, tout cela grâce à la magie du (geste des mains arc-en-ciel de SpongeBob) "Evaluate ()"!

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

Renvoie TRUE si la feuille n'existe PAS; FALSE si la feuille existe. Vous pouvez remplacer la plage de votre choix pour "1: 1", mais je déconseille d'utiliser une seule cellule, car si elle contient une erreur (par exemple, # N / A), elle retournera True.

X37V
la source
3

wsExistsFonction compacte ( sans dépendre de la gestion des erreurs!)

Voici une fonction courte et simple qui ne repose pas sur la gestion des erreurs pour déterminer si une feuille de calcul existe ( et est correctement déclarée pour fonctionner dans n'importe quelle situation!)

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

Exemple d'utilisation:

L'exemple suivant ajoute une nouvelle feuille de calcul nommée myNewSheet, si elle n'existe pas déjà:

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

Plus d'information:

ashleedawg
la source
2

Pourquoi ne pas simplement utiliser une petite boucle pour déterminer si la feuille de calcul nommée existe? Dites si vous recherchez une feuille de calcul nommée «Sheet1» dans le classeur actuellement ouvert.

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
la source
2

Si vous êtes fan de WorksheetFunction.ou que vous travaillez dans un pays non anglais avec un Excel non anglais, c'est une bonne solution, qui fonctionne:

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

Ou dans une fonction comme celle-ci:

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

Remplacez "Données" par le nom de la feuille que vous testez ...

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
la source
1

Sans aucun doute que la fonction ci-dessus peut fonctionner, je viens de me retrouver avec le code suivant qui fonctionne plutôt bien:

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

Remarque: Sheets_Namec'est là que je demande à l'utilisateur de saisir le nom, donc ce n'est peut-être pas la même chose pour vous.

MAx Segura
la source
0

J'ai fait autre chose: supprimer une feuille uniquement si elle existe - ne pas avoir d'erreur si ce n'est pas le cas:

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
la source
0

J'ai trouvé un moyen simple de le faire, mais je n'ai pas créé de nouveau sous-marin pour cela. Au lieu de cela, j'ai juste "fait une vérification" dans le sous-marin sur lequel je travaillais. En supposant que le nom de la feuille que nous recherchons est "Sheet_Exist" et que nous voulons simplement l'activer s'il est trouvé:

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

J'ai également ajouté une fenêtre contextuelle lorsque la feuille n'existe pas.

imjordy23
la source
0

Je sais que c'est un ancien post, mais voici une autre solution simple et rapide.

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
Client
la source
0

Court et propre:

Function IsSheet(n$) As Boolean
    IsSheet = Not IsError(Evaluate(n & "!a1"))
End Function
Héros d'Excel
la source
-4

En fait, j'avais un moyen simple de vérifier si la feuille existe, puis d'exécuter une instruction:

Dans mon cas, je voulais supprimer la feuille puis recréer la même feuille avec le même nom mais le code a été interrompu si le programme n'était pas en mesure de supprimer la feuille car elle était déjà supprimée

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
la source
Le problème avec cette réponse est que lors de la détermination que la feuille existait effectivement, elle est supprimée et donc n'existe plus. Si cela était écrit en tant que fonction, il pourrait avoir un nom comme SheetExistsAfterDeletion et retournerait toujours FALSE.
ChrisB