156 votes

Tester ou vérifier si la feuille existe

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

En gros, je passe en revue toutes les feuilles du classeur d'origine, puis j'active la fonction destsheet dans le classeur de destination vers la feuille portant le même nom que la feuille actuellement itérée dans le classeur d'origine.

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

If wkbkdestination.Worksheets(ThisWorkSheet.Name) Then

2 votes

248voto

Tim Williams Points 31438

Certaines personnes n'aiment pas cette approche en raison d'une utilisation "inappropriée" de la gestion des erreurs, mais je pense que c'est considéré comme acceptable en VBA... Une autre approche consiste à parcourir en boucle 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

7 votes

Utilisation tout à fait appropriée IMO. C'est un piège pour une chose qui est présentée comme existant et qui n'existe pas, et qui a une longue histoire - cf. perl strict, STAE etc. Upvoted

23 votes

On devrait probablement utiliser ActiveWorkbook au lieu de ThisWorkbook . Ce dernier fait référence au classeur qui contient le code de la macro, qui peut être différent du classeur que l'on veut tester. Je suppose que ActiveWorkbook serait utile dans la plupart des cas (des situations artificielles sont toujours possibles, cependant).

0 votes

Noob à vba mais ne peut pas trouver pourquoi cette fonction conduit le code exec à l'erreur 9. J'ai trouvé la réponse ici : stackoverflow.com/a/11459834/461212

132voto

Rory Points 22768

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

2 votes

Une simple évaluation. Elle n'a même pas besoin d'une fonction séparée IMO. Bien joué !

1 votes

Un code vraiment simple et efficace et un grand merci pour m'avoir fait découvrir la commande Evaluate. Respect !

19 votes

@Rory J'ai effectué quelques tests de référence sur cette réponse par rapport à celle de Tim Williams. Sur 500 000 boucles, la vôtre a pris 22 secondes et celle de Tim <1.

73voto

fbonetti Points 1731

Vous n'avez pas besoin de gérer les erreurs pour y parvenir. Tout ce que vous avez à faire est d'itérer sur toutes les feuilles de calcul et de vérifier si le nom spécifié existe :

Dim exists As Boolean

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

34voto

AOBR Points 183

J'ai écrit celui-ci :

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

1 votes

Grande fonction ! Non seulement elle est rapide, mais c'est aussi la plus concise.

0 votes

Je crois que c'est la réponse qui correspond le mieux à la question.

2 votes

J'aime bien celle-là. Notez qu'elle repose sur le fait que la valeur par défaut de sheetExist sera False puisqu'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 de se tromper et de laisser la valeur par défaut en place. Si vous le souhaitez, vous pouvez vous appuyer sur le fait que toute valeur non nulle affectée à une variable booléenne donnera un résultat Vrai et laisser de côté la comparaison > 0, comme suit : sheetExist = ActiveWorkbook.Sheets(sSheet).Index

23voto

Peter Albert Points 8731

Comme la vérification des membres d'une collection est 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 as Object
    On Error Resume Next
    set o = objCollection(strName)
    Contains = (Err.Number = 0)
    Err.Clear
 End Function

Cette fonction peut être utilisée avec n'importe quel objet de type collection ( Shapes , Range , Names , Workbooks etc.).

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

5 votes

Cela ne permet pas de prendre en compte les types primitifs dans les collections, car une erreur sera générée par la fonction Set mot-clé. J'ai découvert que, plutôt que d'utiliser Set en demandant le TypeName du membre de la collection fonctionne pour tous les cas, c'est à dire TypeName objCollection(strName)

2 votes

@Peter : Le mieux est d'ajouter quelque chose pour effacer l'erreur qui sera soulevée dans le cas de la non existence avant que la fonction ne se termine - 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 des cas comme celui-ci. Sub Test() On Error GoTo errhandler Debug.Print Contains(Workbooks, "SomeBookThatIsNotOpen") errhandler: If Err.Number <> 0 Then Stop End Sub

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X