J'essaie de parcourir un tableau dans Excel. Les trois premières colonnes de ce tableau ont des en-têtes de texte, les autres ont des dates comme en-têtes. Je veux affecter ces dates, séquentiellement, à une variable de type Date, puis effectuer certaines opérations en fonction de la date
Pour ce faire, j'utilise une boucle foreach sur myTable.ListColumns. Comme les trois premières colonnes n'ont pas d'en-tête de date, j'ai essayé de configurer la boucle afin que, en cas d'erreur d'attribution de la chaîne d'en-tête à la variable de type date, la boucle passe directement à la colonne suivante
Cela semble fonctionner pour la première colonne. Toutefois, lorsque l'en-tête de la deuxième colonne est "affecté" à la variable de type date, la macro rencontre une erreur même si elle se trouve dans un bloc de traitement des erreurs.
Dim myCol As ListColumn
For Each myCol In myTable.ListColumns
On Error GoTo NextCol
Dim myDate As Date
myDate = CDate(myCol.Name)
On Error GoTo 0
'MORE CODE HERE
NextCol:
On Error GoTo 0
Next myCol
Pour réitérer, l'erreur est renvoyée au deuxième tour de la boucle, à la déclaration
myDate = CDate(myCol.Name)
Quelqu'un peut-il expliquer pourquoi l'instruction On Error cesse de fonctionner?
Avec le code indiqué, vous êtes toujours considéré comme étant au sein de la routine de traitement des erreurs lorsque vous supprimez l'instruction next
.
Cela signifie que les gestionnaires d'erreurs ultérieurs ne sont pas autorisés jusqu'à ce que vous repreniez celui en cours.
Une meilleure architecture serait:
Dim myCol As ListColumn
For Each myCol In myTable.ListColumns
On Error GoTo ErrCol
Dim myDate As Date
myDate = CDate(myCol.Name)
On Error GoTo 0
' MORE CODE HERE '
NextCol:
Next myCol
Exit Sub ' or something '
ErrCol:
Resume NextCol
Cela délimite clairement la gestion des erreurs du code normal et garantit que le gestionnaire d'erreurs en cours d'exécution est terminé avant que vous essayiez de configurer un autre gestionnaire.
Ce site a une bonne description du problème:
Error Handling Blocks And On Error Goto
Un bloc de traitement des erreurs, également appelé gestionnaire d'erreurs, est une section de code vers laquelle l'exécution est transférée via une instruction On Error Goto <label>:
. Ce code doit être conçu pour résoudre le problème et reprendre l’exécution dans le bloc de code principal ou pour mettre fin à l’exécution de la procédure. Vous ne pouvez pas utiliser l'instruction On Error Goto <label>:
simplement sauter des lignes. Par exemple, le code suivant ne fonctionnera pas correctement:
On Error GoTo Err1:
Debug.Print 1 / 0
' more code
Err1:
On Error GoTo Err2:
Debug.Print 1 / 0
' more code
Err2:
Lorsque la première erreur est générée, l'exécution est transférée à la ligne suivant le code Err1:
. Le gestionnaire d'erreurs est toujours actif lorsque la deuxième erreur se produit et, par conséquent, la deuxième erreur n'est pas interceptée par l'instruction On Error
.
Vous devez ajouter resume
de certaines sortes dans votre code de gestion des erreurs pour indiquer que la gestion des erreurs est terminée. Sinon, le premier gestionnaire d'erreurs est toujours actif et vous n'êtes jamais "résolu".
Voir http://www.cpearson.com/Excel/errorhandling.htm (plus précisément dans la rubrique "Traitement des erreurs et suppression d'erreur" et dans la section suivante).
Suivi de la réponse acceptée par paxdiablo. Ceci est possible, en autorisant deux pièges d'erreur dans le même sous, l'un après l'autre:
Public Sub test()
On Error GoTo Err1:
Debug.Print 1 / 0
' more code
Err1:
On Error GoTo -1 ' clears the active error handler
On Error GoTo Err2: ' .. so we can set up another
Debug.Print 1 / 0
' more code
Err2:
MsgBox "Got here safely"
End Sub
Utiliser On Error GoTo -1
annule le gestionnaire d'erreurs actif et en permet la création d'un autre (et err.clear
ne le fait pas!). Que ce soit une bonne idée ou non, reste un exercice pour le lecteur, mais ça marche!
Effacer tous les paramètres de propriété de l'objet Err ne signifie pas réinitialiser le gestionnaire d'erreurs.
Essaye ça:
Sub TestErr()
Dim i As Integer
Dim x As Double
On Error GoTo NextLoop
For i = 1 To 2
10: x = i / 0
NextLoop:
If Err <> 0 Then
Err.Clear
Debug.Print "Cleared i=" & i
End If
Next
End Sub
Vous remarquerez que, tout comme l'OP, l'erreur sera corrigée correctement lorsque i =1
mais échouera à la ligne 10 lorsque i = 2
, même si nous avons utilisé Err.Clear