[RESOLU]Propagation d'erreur en VBA

Allons droit au but : comment simulé le try … catch, throw, throws en VBA. Je recherche tout simplement à propager une erreur d’une procédure à une autre, mais d’après ce que j’ai vu, on est obligé de traiter toutes les erreurs dans la procédure où elles se sont produites sinon elles sont perdues.

Dites moi que c’est possible, sinon je vais démoraliser.

Hummm en VBA je suis pas sur mais en VB tu peux toujours tenter un truc du style : Je mets un On error resume next tout en haut de ma procédure, et là ou tu attends l’erreur, enfin à la ligne en dessous, tu appelles une procédure spéciale de gestion des erreurs à qui tu passes toutes les infos utiles, par exemples les propriétés de err (err.number etc…) Après c’est à peu près tout ce que je vois et qui se rapproche le plus de ce que tu veux…Mais c’est pas la panacée non plus, je ne connais pas de vrai équivalent de try catch en VB…

C’est ce que je disais plus haut, on est obligé de traiter l’erreur dans la procédure, mais moi j’ai pas trop envie niveau conception c’est très très moche.
Dans mon cas, je développe une procédure qui ouvre un classeur, je ne lui demande rien d’autre que de l’ouvrir mais bon, si le classeur n’existe pas ou si un classeur du même nom est déjà ouvert ca plante, j’aimerai gérer les deux cas séparément sans pour autant mettre un gros msgbox bien moche dans cette fonction, ce n’est pas son problème à cette fonction de m’afficher l’erreur, tout ce qu’elle doit faire, c’est prévenir la procédure qu’il l’a appelée que ca n’a pas maché et lui indiquer pourquoi. Quel mécanisme je peux mettre en place pour réaliser ça.

Ok Ok. Bon là je n’ai pas ce qu’il faut pour tester mais je ne me rappelle pas que l’objet err est remis à zéro en sortant de la fonction. Si tu as une erreur alors le numéro et tout le blabla sont stockés dans err et tu peux y accéder en dehors de ta fonction non ? Je dis peut-être une bêtise. Sinon tu peux toujours transformer la procédure qui ouvre ton classeur en fonction et lui faire retourner le numéro de l’erreur, la procédure l’ayant appelé saura alors que ça ne s’est pas bien passé. Pour le moment c’est tout ce que je vois comme solution, la première étant celle qui laisse la procédure d’ouverture du classeur la plus indépendante de toute gestion d’erreur.
Je suis d’accord que la gestion d’erreur c’est pas bien joli en VBA.

Manque de chance, la variable ERR se réinitialise à la sortie de le fonction, je n’ai pas trouvé le moyen de lui mettre un nombre pour le récupérer par la suite si quelqu’un sais comment faire…
Sinon pour ta deuxième solution, ce n’est pas une procédure mais une fonction qui retourne un Worksheet, donc je ne peux pas retourner un nombre, en ce moment, je retourne Nothing quand ca ne fonctionne pas, mais je n’ai aucun moyen de remonter la cause.
Il y avait une fonction dans VB : CVErr qui permet de retourner une erreur, mais je n’ai pas trop bien compris sous fonctionnement et les tests que j’ai effectué non rien donné (ca ne doit fonctionner que pour les types primitifs).

Là, je n’ai plus trop d’idée.

Ah autant pour moi si c’est déjà une fonction ton post précédent m’a enduit d’erreur B)
Bon j’avoue je suis un peu à court d’idée, la seule qui me reste c’est … une variable globale. Oui bon pas tapé hein, c’est pas très beau bon ok c’est laid mais bon tant que les pointeurs n’existent pas … La franchement je ne vois rien d’autre, mais si un demi-dieu du VBA a une idée…

La fonction CVErr, autant que je me souvienne, nécessite aussi de retourner une valeur à la fin de la fonction. En gros tu faisais MaFonction=CVErr(unnombre) et dans la procédure appelante tu faisais un if IsError(lavaleurderetour) then … pour savoir si tout s’était bien passé.

et ça ?
[codebox]Public Function fonction_appelante(div)
On Error GoTo trait_err
Dim a
a = fonction_appelee(div)
fonction_appelante = a
trait_err:
If err.Number = 13 Then
MsgBox “mon erreur '” & err.Description & "’ est bien remontée dans fonction_appelante"
End If
End Function
Public Function fonction_appelee(div)
On Error GoTo trait_err
fonction_appelee = 3 / div

Exit Function
trait_err:
If err.Number = 11 Then
’rollback exemple à la con
err.Raise 13, , "l’erreur s’est produit dans toto"
Else
err.Raise err.Number ’ ajout relatif à l’edit du message du thread
End If
End Function[/codebox]Quand je fais:
?fonction_appelante(0) dans la boite de debug de VBA access, j’obtiens bien l’erreur qui a été traitée avant renvoi:“mon erreur ‘l’erreur s’est produit dans toto’ est bien remontée dans fonction_appelante”

Bon après c’est clair qu’on est loin de try except.
edit: Et on n’est pas obligé de tout traiter:
?fonction_appelante(“a”) me donne bien :“mon erreur ‘Type Incompatible’ est bien remontée dans fonction_appelante”

Ce qui veut dire que err n’est pas réinitialisé à la sortie de la fonction ? C’est le coup du err.Raise qu’il manquait donc ?

[quote=« BioGeek, post:8, topic: 29834 »]Ce qui veut dire que err n’est pas réinitialisé à la sortie de la fonction ? C’est le coup du err.Raise qu’il manquait donc ?[/quote]mais si! B) err est réinitialisé à la sortie de la fonction. Quand tu fais raise, tu la regénère de A à Z à partir des élements de celle en cours (je n’ai pas les bons termes). Tu remarqueras d’ailleurs que tout les élements que je n’ai pas repris dans le raise n’y sont pas à l’arrivée, c’est donc bien une erreur complétement nouvelle qui est générée à partir de l’ancienne.

Quand j’ai vu raise dans la doc je me suis toute de suite dit que ça pourrait convenir: en PL/SQL c’est cette même instruction qui est utilisée mais plus simplement (gestion des exceptions: begin; ma_ligne_generant_une_erreur; exception when dup_val_on_index then…;when others then raise; end;)

Bon attendons de voir si ça convient à Zgoblin. :smiley:

goto? y’a encore des gens qui utilisent ça?

Nickel, je n’utilisais pas bien le Err.Raise. C’est sur qu’on est loin du try catch, mais c’est quand même très intéressant de pouvoir diffuser une erreur de cette manière.

Pour le Goto, NE SURTOUT PAS L’UTILISER sauf dans quelques cas très rares, dans mes codes, il doit en avoir un ou deux, je l’utilise pour exécuter le code en bout de précédure/fonction qui supprime les pointeur vers des objets, genre :

[code]Function F_Test(Tableau[] as String) as String
Dim O_Objet as MonObject
Dim i as long

  Set  O_Objet = new MonObjet

   For i = 1 to 5000
		If O_Objet.Valeur = Tableau[i] Then
			 F_Test = Tableau[i] 
			 goto fin
		 End If
   Next i
   F_Test = ""

fin:
set O_Objet = Nothing
End Function[/code]

C’est un exemple à la con qui comporte peut-être des erreurs de syntaxe mais l’idée est là.

Je me souviens du temps où je programmais pas mal (pour le plaisir, je me faisais des softs à la con pour des besoins particuliers) que déjà j’abhorrais les goto.
Et surtout d’un stage au CEA où je devais bosser sur un logiciel écrit en fortran 77 et le porter en fortran 90, en le rendant plus rapide et en le remettant au propre. Le truc faisait 450000 lignes
J’avais des milliards de goto, et j’en ai chié ma race pour redescendre leur nombre à 2. Les 2 qui restaient, c’est parce que ça faisait un truc du genre:

for
while
endfor
endwhile

Et qu’imbriqué comme ça, je savais pas comment m’en sortir.
(au passage j’avais ramené le code à 150000 lignes, toutes réécrites au propre, et le soft était de 40 à 2000% plus rapide en optimisant les calculs matriciels par rapport à l’archi des CPU) </Ma Life>

Ca compile des boucles imbriquées ? Pour moi, c’était totalement interdit dans tous les langages, pas tous à voir…

[quote=“ColdFire, post:10, topic: 29834”]goto? y’a encore des gens qui utilisent ça?[/quote] En VBA pour traiter les erreurs tu es obligé d’utiliser le goto puisque justement les clauses d’interception à la try catch n’existent pas. Je n’utilises jamais le goto sauf dans ce cas là de On error goto. Mais en fait heureusement je n’ai plus de projets en VB ou VBA depuis des siècles.[quote=“ZGoblin, post:11, topic: 29834”]Nickel, je n’utilisais pas bien le Err.Raise. C’est sur qu’on est loin du try catch, mais c’est quand même très intéressant de pouvoir diffuser une erreur de cette manière.[/quote]cool B)

En VB on est obligé d’utiliser le Goto car certaines instructions manquent comme le try … catch (voir post phili_b ci-dessus) ou le break dans une boucle (vois mon post précédant), dans les autres cas C’EST MAL !!!

Justement, je disais que c’étaient les seuls goto que j’ai du laisser, vu que je ne pouvais pas faire de boucles imbriquées B)

Et tu n’as pas réussi à trouvé un algo avec des vrais boucles ou de la récursivité ? Je suppose aussi qu’ils y a d’autres contraintes comme le temps qui font en sorte que : “y’a surement moyen de faire mieux, mais j’ai déjà bien nettoyé, les perfs sont là, je vais pas me casser le cul juste pour 2 goto à enlever…” Surtout que des fois le code est tellement obscur qu’on préfère ne rien toucher de peur que ca ne fonctionne plus.

Bah en plus le prog avait des bouts de codes faits par des personnes différentes, et avait été commencé en 1977 avec des ajouts jusqu’en 99…
En réécrivant des trucs et optimisant j’avais déjà divisé par 3 la taille du code, je ne pouvais pas faire beaucoup mieux en 3 mois…

Ah, et extrait de ma soutenance de stage:
“Moi: c’est le code le plus sale que j’ai jamais vu”
“Un prof: oui mais bon, tu n’as pas vu non plus des milliers de programmes”
“Mon maître de stage: sisi, ce programme était vraiment extrèmement mal écrit. Ce sont des scientifiques (chimistes, physiciens) qui l’ont écrit, pas des informaticiens”.

Ah bah cool j’aurais appris un truc avec le err.raise, je ne l’utilisais pas correctement en effet. Bon pas sur que ça me servira mais bon, c’toujours ça de pris.

77 jusque 99 !! J’imagine alors la tête du code ! Moi à l’instant, je viens de voir une macro avec une procédure de 400 lignes en VBA écrit gràce à outil, enregistré la macro d’excel (qui donne vraiment un résultat le plus pourrave possible) auquel on a rajouté quelques conditions et boucles ici et là. C’était pas beau non plus, mais j’ai réussi à renvoyé cette macro telquel en disant, “le code est dégeullasse, je ne peux absolument rien faire”, ouf B)

PS: Merci à BioGeek de recentrer le sujet car c’est vrai qu’on s’en éloigne vachement !