De bonnes Habitudes Pour VBA Erreur de Manipulation
Quels sont les bons modèles pour la gestion des erreurs dans VBA?
En particulier, que dois-je faire dans cette situation:
... some code ...
... some code where an error might occur ...
... some code ...
... some other code where a different error might occur ...
... some other code ...
... some code that must always be run (like a finally block) ...
Je veux gérer à la fois les erreurs, et de reprendre l'exécution après le code où l'erreur peut se produire. Aussi, la enfin de code à la fin doit TOUJOURS exécuter de n'importe quelles exceptions sont levées plus tôt. Comment puis-je obtenir ce résultat?
Vous devez vous connecter pour publier un commentaire.
Erreur de Manipulation en VBA
On Error Goto
ErrorHandlerLabelResume
(Next
| ErrorHandlerLabel)On Error Goto 0
(désactive l'actuel gestionnaire d'erreur)Err
objetLa
Err
propriétés de l'objet sont normalement remis à zéro ou une chaîne de longueur nulle dans la routine de gestion des erreurs, mais il peut également être fait explicitement avecErr.Clear
.Des erreurs dans la routine de gestion des erreurs sont appelé à disparaître.
La gamme 513-65535 est disponible pour les erreurs de l'utilisateur.
Pour la classe personnalisée des erreurs, vous ajoutez
vbObjectError
pour le numéro d'erreur.Voir MS documentation sur
Err.Soulever
et la liste des numéros d'erreur.Pour ne pas mis en œuvre l'interface de membres dans un dérivés classe, vous devez utiliser la constante
E_NOTIMPL = &H80004001
.Je voudrais aussi ajouter:
Err
objet est le plus proche que vous avez pour un objet d'exceptionErr.Raise
Et juste pour le fun:
On Error Resume Next
est le diable incarné et à éviter, comme il en silence cache les erreursCall mdl_val.usr_sub_handle_error(Err.Source, Err.Description)
On Error Resume Next
. Le principe commun de ces cas est lorsque certains résultats sont retournés par la levée d'une exception. Le plus souvent de cas est l'accès à unCollection
objet par la chaîne de clé: dans ce cas, l'appelant ne peut pas savoir si il y a un article avec cette clé dans laCollection
objet.De sorte que vous pourriez faire quelque chose comme ce
Si vous voulez faire cuire dans la coutume des exceptions. (par exemple, ceux qui violent les règles de gestion) l'exemple ci-dessus, mais utiliser la fonction goto pour modifier le débit de la méthode que nécessaire.
Resume ExitHere
qui fait beaucoup de la différence entre les deux paradigmes.Voici mon standard de mise en œuvre. J'aime les étiquettes pour être auto-descriptif.
Ou, avec un
Finally
bloc:Finally:
? DoncOn Error GoTo 0
immédiatement aprèsFinally:
peut-être nécessaires pour fixer les indésirables de la récursivité.Finally
bloc, il suffit de lancer l'erreur. Il ne sera pas re-boucle de retour vers leFinally
bloc. (Essayez, vous verrez.) Si vous souhaitez gérer une erreur après le bloc finally, vous aurez besoin d'ajouter un autreOn Error GoTo
, mais probablement avec un autre label, commeCatch2
. Mais ici, nous avons commencer à faire une digression dans le Code Propre méthodologie --> propre méthode aurez seulement besoin d'un gestionnaire d'erreur (et doit encore avoir son propre méthode dédiée à l'erreur de capture.)Finally:
dépend si vous entrez après avoir été détournées pourCatch:
(alors oui il vient de jette)... ou pas! Et dans ce dernier cas, c'est à dire avoir traverséGoTo Finally
aura laOn Error GoTo Catch
toujours en vigueur, de sorte que le contrôle est détournée versCatch:
(pourrait être une bonne chose), puisFinally:
est entré de nouveau, probablement pas ce que vous attendiez en premier lieu.On Error GoTo Catch2
dansFinally:
code, il aura été efficace dans ce dernier cas, mais pas si vous êtes allé à traversCatch:
avant, car il n'est pasOn Error GoTo -1
ni aucuneResume
; l'ajout de l'ancien nous amène si loin de réguliertry catch finally
que l'on pourrait envisager d'arrêter analogie douteuse avant ce point.Professionnel Excel De Développement a une assez bonne erreur de manipulation régime. Si vous allez passer du temps en VBA, c'est probablement la peine d'obtenir le livre. Il y a un certain nombre de domaines où VBA est ce qui manque et ce livre a de bonnes suggestions pour la gestion de ces zones.
PED décrit deux méthodes de gestion des erreurs. La principale est un système où tous les point d'entrée des procédures sont des sous-procédures et toutes les autres procédures sont les fonctions qui retournent des valeurs Booléennes.
Le point d'entrée de procédure d'utilisation Sur les déclarations d'Erreurs de capture des erreurs assez bien conçu. Le non-point d'entrée des procédures de retourner Vrai si il n'y avait pas les erreurs et les Faux si il y avait des erreurs. Non, point d'entrée de procédure d'utilisation en cas d'Erreur.
Les deux types de procédures d'utilisation d'une centrale de traitement d'erreur de procédure pour garder de l'erreur dans l'état et à enregistrer l'erreur.
J'utilise un morceau de code que j'ai développé moi-même et c'est assez bon pour mes codes:
Au début de la fonction ou de les sous, je définir:
et puis, je me charge du possible, les erreurs
Voici un bon modèle.
Pour le débogage: Lorsqu'une erreur est déclenchée, appuyez sur Ctrl-Pause (ou Ctrl-Pause), faites glisser le marqueur de pause (ou quelque chose comme ça) jusqu'à la Reprise de la ligne, appuyez sur F8 et vous ferez étape à la ligne que "jeté" de l'erreur.
La ExitHandler est votre "Enfin".
Sablier d'être tué à chaque fois.
Barre d'état du texte sera effacé à chaque fois.
Il a aussi des pièges pour les DAO et VBA erreurs. Vous pouvez mettre un Select case dans l'erreur VBA section si vous souhaitez piège pour certains Err numéros.
Le code ci-dessous montre une alternative qui s'assure qu'il existe un seul point de sortie pour le sub/function.
Également pertinentes pour la discussion est relativement inconnu,
Erl
fonction. Si vous avez numérique étiquettes à l'intérieur de votre code de procédure, par exemple,La
Erl
fonction renvoie le plus récemment rencontré numberic étiquette de ligne. Dans l'exemple ci-dessus, si une erreur d'exécution se produit après l'étiquette1200:
mais avant1300:
, leErl
fonction sera de retour1200
, puisque c'est le plus recenlty avec succès rencontré une étiquette de ligne. Je trouve que c'est une bonne pratique à mettre une étiquette de ligne immédiatement au-dessus de votre erreur du bloc de gestion. Je typcially utilisation9999
pour indiquer que la partie principale de la procuedure courut à sa devrait conculsion.NOTES:
Ligne les étiquettes DOIVENT être des entiers positifs -- une étiquette comme
MadeItHere:
n'est pas recogonized parErl
.Étiquettes de ligne sont totalement sans lien avec le réel numéros de ligne d'un
VBIDE CodeModule
. Vous pouvez utiliser tous les nombres positifs que vous voulez, dans n'importe quel ordre que vous voulez. Dans l'exemple ci-dessus, il y a seulement 25 lignes de code, mais la ligne numéro de l'étiquette commencer à1000
. Il n'y a pas de relation entre l'éditeur numéros de ligne et de la ligne numéro de l'étiquette utilisée avecErl
.Ligne numéro de l'étiquette n'a pas besoin d'être dans un ordre particulier, même si elles ne sont pas dans l'ordre croissant, ordre de haut en bas, de l'efficacité et de prestations de
Erl
est fortement diminuée, maisErl
sera toujours en rapport le nombre correct.Étiquettes de ligne sont spécifiques à la procédure dans laquelle ils apparaissent. Si la procédure
ProcA
appelle la procédureProcB
et une erreur se produit dansProcB
qui repasse le contrôle deProcA
,Erl
(enProcA
) sera de retour plus récemment rencontrée ligne numéro de l'étiquette dansProcA
avant qu'il appelleProcB
. De l'intérieurProcA
, vous ne pouvez pas obtenir le label de la ligne de numéros qui apparaissent dansProcB
.Utilisation des soins lors de la mise en ligne nombre d'étiquettes à l'intérieur d'une boucle. Par exemple,
Si le code à la suite de la ligne étiquette
500
mais avant600
provoque une erreur, et cette erreur survient sur le 20e itération de la boucle,Erl
sera de retour500
, même si600
a été rencontrée avec succès dans le précédent 19 interaction de la boucle.Bon placement des étiquettes de ligne au sein de la procédure est critique à l'aide de la
Erl
fonction pour obtenir réellement de l'information significative.Il ya un certain nombre de gratuit utilitaires sur le net, qui permet d'insérer étiquette de ligne numérique dans une procédure automatiquement, donc vous devez fine des informations d'erreur pendant le développement et le débogage, puis retirez les étiquettes dès que le code va vivre.
Si votre code affiche les informations d'erreur à l'utilisateur si une erreur inattendue se produit, pourvu que la valeur de
Erl
dans cette information peut rendre la recherche et la résolution du problème INFINIMENT plus simple que si la valeur deErl
n'est pas signalé.Méfiez-vous de l'éléphant piège:
Je n'ai vu aucune mention de cela dans cette discussion. [Access 2010]
Comment ACCESS/VBA gère les erreurs dans les objets de la CLASSE est déterminée par une option configurable:
VBA Éditeur de Code > Outils > Options > Général > Erreur de Piégeage:
- Je trouver la suite à mieux travailler, appelé la centrale de traitement d'erreur d'approche.
Avantages
Vous disposez de 2 modes de fonctionnement de votre application: Debug et Production. Dans le Debug mode, le code s'arrête à chaque erreur inattendue et vous permettre de déboguer facilement en sautant à la ligne où elle s'est produite en appuyant sur F8 deux fois. Dans le Production mode, un véritable message d'erreur sera affiché à l'utilisateur.
Vous pouvez jeter intentionnelle des erreurs de ce genre, qui va arrêter l'exécution du code avec un message à l'utilisateur:
Mise en œuvre
Vous avez besoin de "wrap" toutes les sous-routines et fonctions avec un nombre significatif de code suivantes avec les en-têtes et pieds de page, en veillant à spécifier
ehCallTypeEntryPoint
dans tous vos points d'entrée. Remarque lemsModule
constante, ce qui doit être mis dans tous les modules.Le contenu de la centrale module de gestionnaire d'erreur est le suivant:
Pour définir vous-même dans le Debug mode, exécutez la commande suivante dans la fenêtre exécution:
Mon point de vue personnel sur une déclaration faite plus tôt dans ce thread:
Je suis en utilisant le
On Error Resume Next
sur les procédures où je ne veux pas une erreur d'arrêter mon travail et où tout énoncé ne dépend pas de la suite des déclarations antérieures.Quand je fais cela j'ai ajouter une variable globale
debugModeOn
et je l'ai mis àTrue
. Puis-je l'utiliser de cette façon:Quand je livrer mon travail, j'ai mis la variable à false, et donc de cacher les erreurs de l'utilisateur et de leur montrer pendant le test.
Également l'utiliser pour faire quelque chose qui peut échouer comme l'appel de la DataBodyRange d'un ListObject qui peut être vide:
Au lieu de:
Ou la vérification de l'existence d'un élément dans une collection:
If not debugModeOn Then On Error Resume Next
Dans ce cas, il est préférable d'utiliser la compilation conditionnelle comme#If Hide_Errors > 0 Then On Error Resume Next
et définirHide_Errors
dans le projet VBA propriétésConditional Complication Arguments
en conséquence.