Précédent   Forum des professionnels en informatique > Logiciels > Microsoft Office > Access > Sondages et Débats
Sondages et Débats Forum destiné à recevoir les échanges, avis et sondages autour de la technologie Access.
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 22/08/2006, 18h41   #1
Membre Expert
 
Avatar de Papy Turbo
 
Homme Etienne Pailleret
Développeur VBA
Inscription : mars 2004
Messages : 748
Détails du profil
Informations personnelles :
Nom : Homme Etienne Pailleret
Localisation : France, Hauts de Seine (Île de France)

Informations professionnelles :
Activité : Développeur VBA

Informations forums :
Inscription : mars 2004
Messages : 748
Points : 1 114
Points : 1 114
Par défaut [Cours pt-04]les bases du débogage

>>>> Merci de noter toutes remarques concernant ce cours dans le sujet parallèle : [Cours papyturbo]Commentaires, remarques et suggestions
-------------------------------------------------------------------------
Ce cours est la suite
- du [Cours pt-01][Débutants]Analyse structure base de données simple et
- du [Cours pt-02][Débutants]Requête avec plusieurs sommes
- et représente une "pause" dans le déroulement du [Cours pt-03]turbo-formulaire (les bases), pause destinée à défricher les bases du débogage avant de retourner finir notre formulaire.
Il commence donc par une réponse aux questions posées par Serge57, dans la réponse #10 du cours précédent (le 03),
et nous travaillons à partir du dernier .mdb :
SuiviAffaire 2006-08-17.zip (89,0 ko) -------------------------------------------------------------------------

Zzzzzzap!, zoooing ! tiou tiou tiou tiou, sortez vos lasers quantiques et vos tromblons zappeurs, enfilez le costard de Blade Runner, on part à la chasse aux bugs , en espérant que ce ne soient pas eux qui nous flinguent les premiers.

D'abord, se référer au débat [Conseils] Comment retrouver un problème , qui traite de ce sujet assez à fond. Il contient tous les principaux aspects du débogage et mérite d'être relu par tous.
Ici, nous détaillerons surtout les étapes de base pour débutants.

----------------
Je reprends le bug déjà signalé et apparemment corrigé dans la réponse #9.

La 1ère étape consiste à identifier le bug. Si un message d'erreur s'affiche, facile. Là, ce n'était le cas qu'à condition de faire des tests. En l'occurence, réduire le formulaire à sa taille la plus petite, à partir du coin inférieur droit (mais également : le passer en plein écran, puis en réduction, etc.)

La 2ème étape, c'est le travail du beta testeur qui doit décrire aux développeurs "Comment reproduire le bug". En tant que développeurs, on doit au moins savoir faire cela, et ça a consisté en (dans la réponse #9 du cours 03) :
Citation:
Je n'ai peut être pas été assez clair, donc, pour reproduire le bug, avec ta dernière version du .mdb :
1- démarrer l'application 'Affaires'
2- agrandir Access en plein écran,
3- réduire le formulaire Affaires, pour pouvoir le redimensionner à la souris,
4- saisir le bord inférieur, et remonter jusqu'à ce que la section détail, qui contient le sous-formulaire ssfAffaires, disparaisse.
Dès qu'il disparaît complètement, on a une erreur 2100 'Contrôle ou sous-formulaire trop grand.'


La 3ème étape consiste à comprendre ce qu'il se passe et, lors de l'affichage du message, j'ai une boîte de dialogue avec le message et 2 boutons actifs : Fin (on arrête tout, sans commentaire) ou Débogage (clic)
Le bouton Débogage m'amène sur une ligne de code jaune, la ligne qui provoque l'erreur :
Code :
            Me.Section(acDetail).Height = NewHeight
Là, je regarde les 2 valeurs qui pourraient être concernées.
Pour ça, les techniques de base sont :
- laisser la souris au dessus du nom d'une variable, comme 'NewHeight' : sa valeur s'affiche dans une bulle.

Ça ne marche pas toujours pour une expression plus complexe, comme 'Me.Section(acDetail).Height (si la souris est au dessus de 'acDetail', la bulle affiche 'acDetail = 0', ce qui ne nous intéresse pas). Donc :
- sélectionner l'expression et appuyer sur Maj+F9 : la valeur s'affiche dans une boîte de dialogue.

Troisième méthode :
- ouvrir la fenêtre de débogage avec Ctrl+G, et, dans la fenêtre d'exécution qui s'ouvre sous le code, taper un '?' suivi d'un espace et de la valeur, le nom de la variable ou l'expression à évaluer :
Code :
1
2
? Me.Section(acDetail).Height
 105
Maintenant, je sais que
- ma section détail, avant le Form_resize, mesurait 105 twips en hauteur,
- la variable NewHeight est négative (-5).
D'où vient cette NewHeight négative ?
Elle est calculée au dessus, en gros :
Code :
NewHeight = Me.InsideHeight - Me.Section(acHeader).Height
On peut ignorer la section acFooter, dont la hauteur est 0.
Ce qui veut juste dire que je suis remonté tellement vite que InsideHeight (la fenêtre) est plus petit que la section acHeader (l'en-tête du formulaire).
4ème étape : trouver la solution.
Il paraît ici évident qu'on ne peut pas demander à Access de dessiner une section Détails dont la hauteur serait négative !
D'où, solution :
Code :
1
2
3
4
        If NewHeight > 0 Then
            Me.Section(acDetail).Height = NewHeight
            .Height = NewHeight - (.Top * 2)
        End If
On ne va ajuster la hauteur de la section détails que si elle est positive.

5ème étape : documenter le probème.
Et ça devient :
Code :
1
2
3
4
5
        'Pour empêcher l'erreur de dimensionnement du formulaire (erreur 2100)
        If NewHeight > 0 Then
            Me.Section(acDetail).Height = NewHeight
            .Height = NewHeight - (.Top * 2)
        End If
Étape qu'on oublie trop souvent, indispensable pour permettre de se relire quelques mois plus tard.
Trop de commentaires tueraient les commentaires ?
Peut être, mais il en faut beaucoup pour que ce soit trop et au minimum, il faut signaler toute correction de bug ou de message d'erreur, comme ici.
---------------------
Voilà, en 5 étapes, comment le premier message d'erreur a été "corrigé".

Et tu me signales qu'il est encore là ?
Citation:
Envoyé par Serge57
En reproduisant la manip sur la base corrigée , l’erreur 2100 existe toujours ???.
Mais c'est pas croyable, ça.

Donc, même méthode -> reste plus qu'à trouver la solution appropriée ?
Papy Turbo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/08/2006, 22h40   #2
Membre du Club
 
Inscription : mai 2006
Messages : 79
Détails du profil
Informations forums :
Inscription : mai 2006
Messages : 79
Points : 57
Points : 57
Citation:
Envoyé par Papy Turbo
Mais c'est pas croyable, ça.

Donc, même méthode -> reste plus qu'à trouver la solution appropriée ?
Et voici le nouveau code
Code :
1
2
3
4
5
6
        If NewHeight > (.Top * 2) Then
        'If NewHeight > 0 Then
            Me.Section(acDetail).Height = NewHeight
            'ssfAffaires.Top = 0 : juste au cas où ou mettrait une bordure autour du sous-form, ou...
            .Height = NewHeight - (.Top * 2)
        End If
On m’a soufflé le code (merci pour le souffleur, il se reconnaîtra, je ne balance pas ). En suivant ta méthode, je pense que j'y serai arrivé tout seul.

Citation:
La 1ère étape consiste à identifier le bug. Si un message d'erreur s'affiche, facile. Là, ce n'était le cas qu'à condition de faire des tests. En l'occurence, réduire le formulaire à sa taille la plus petite, à partir du coin inférieur droit (mais également : le passer en plein écran, puis en réduction, etc.)
Et oui, voilà l’expérience (ou le retour d’expérience) qui parle. Ce que je veux dire : Au début je n’avais même pas détecté le bug (l'erreur 2100), pas assez d ‘essai … Du coup, j’ai fait tout plein essais sur le formulaire et, je n’ai plus vu apparaître d’erreur. C’est BIEN ??
Serge57 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/08/2006, 17h53   #3
Membre Expert
 
Avatar de Papy Turbo
 
Homme Etienne Pailleret
Développeur VBA
Inscription : mars 2004
Messages : 748
Détails du profil
Informations personnelles :
Nom : Homme Etienne Pailleret
Localisation : France, Hauts de Seine (Île de France)

Informations professionnelles :
Activité : Développeur VBA

Informations forums :
Inscription : mars 2004
Messages : 748
Points : 1 114
Points : 1 114
Citation:
Envoyé par Serge57
Du coup, j’ai fait tout plein essais sur le formulaire et, je n’ai plus vu apparaître d’erreur. C'est bien ?
Que demande le peuple ?
C'est top cool, et c'est ce qu'il faut maintenant, à chaque routine, quelle qu'elle soit.
Stop : pas vrai. Pas top cool. Et l'étape 5 ?
In-dis-pen-sa-ble : noter un commentaire aussi concis que possible, mais clair !

Puisque tu commences à être rôdé, continuons avec un bug un poil plus difficile.
Dans la réponse #8 du cours pt03, tu as écrit :
Citation:
Envoyé par Serge57
J’ai remarqué que si access à plus de 2 de 2 lignes de menu, une barre d’ascenseur vertical se crée dans le conteneur.
Il semble bien que tu aies détecté quelque chose (1ère étape), mais...
- il faut peut être compléter cette première étape, en identifiant clairement le problème ("qu'est-ce qu'il fait ?" et "qu'est-ce qu'il devrait faire" ? ou bien "qu'est-ce qu'il fait qui ne va pas ?"
- étape 2 : comment reproduire le bug ?
et puis : 3, 4 et 5, bien sûr, mais il risque d'y avoir des pièges.
Comme quoi, si quelque chose semble bizarre, faut fouiner ou, au minimum, le noter pour plus tard, mais jamais laisser passer, sinon, ça ne peut qu'empirer après...

Coups de pouce (je conseille à chacun, dont Serge, de ne pas trop se faire aider, ça pert tout son fun) :
1- pour arrêter le code qui pose problème, pouvoir inspecter les valeurs des variables et autres paramètres, et détecter la ou les instructions qui font que ça déc..., il va falloir, soit
- appuyer sur F9 (ou menu Débogage > Basculer le point d'arrêt, dans l'IDE (espace de travail en VBA : I pour quèque chose genre "Interactive" ? + "Development Environment")
- écrire un Stop dans le code, éventuellement suivi de ":", si tu le mets devant une instruction existante.
Chacun son usage :
Le F9 (point d'arrêt) est temporaire.
Le Stop peut être enregistré avec le code (jusqu'à ce que le bug soit résolu, par exemple).

2- s'il se passe des choses bizarres, ça vaudra le coup d'appuyer sur Ctrl+L (ou menu Affichage > Pile des appels). On en reparlera, mais j'attends tes questions / observations...

Bien entendu, les points d'arrêt et la pile des appels sont documentés dans l'aide d'access.
Papy Turbo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/08/2006, 19h14   #4
Membre du Club
 
Inscription : mai 2006
Messages : 79
Détails du profil
Informations forums :
Inscription : mai 2006
Messages : 79
Points : 57
Points : 57
Citation:
Envoyé par Papy Turbo
Il Il semble bien que tu aies détecté quelque chose (1ère étape), mais...
- il faut peut être compléter cette première étape, en identifiant clairement le problème ("qu'est-ce qu'il fait ?" et "qu'est-ce qu'il devrait faire" ? ou bien "qu'est-ce qu'il fait qui ne va pas ?"
Ok , j’ai joint un fichier .doc ou j’ai insérer deux images pour montrer le bug.


1ère étape - Identification du bug -– un ascenseur apparaît verticalement quand je rajoute une ligne de menu access supplémentaire.


2éme étape reproduction du bug – dans application « SuiviAffaire » ouvrir le formulaire 10-100 Affaires, si dans la barre de menu il y a plus de deux lignes « de boites outils » un ascenseur vertical apparaît.


3éme étape comprendre ce qui se passe – Il n’y a pas de message d’erreur. Je suppose qu’il y a un petit hic sur la valeur de la variable « InsideHeight » retournée par access. J’ai remarqué qu’a chaque affichage d'un nouveau menu, la variable prend une autre valeur. Mais je n’ai pas trouvé de relation cohérante pour faire un "IF" ….
Suis-je sur la bonne piste ?

-------
Fichiers attachés : reponse-4.doc (158,0 ko)
-------
Serge57 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/08/2006, 17h58   #5
Membre Expert
 
Avatar de Papy Turbo
 
Homme Etienne Pailleret
Développeur VBA
Inscription : mars 2004
Messages : 748
Détails du profil
Informations personnelles :
Nom : Homme Etienne Pailleret
Localisation : France, Hauts de Seine (Île de France)

Informations professionnelles :
Activité : Développeur VBA

Informations forums :
Inscription : mars 2004
Messages : 748
Points : 1 114
Points : 1 114
Bon pour l'identification du bug, et on peut le reproduire sans problème (étape 2). Sauf que j'aurais précisé : il faut que le formulaire Affaires soit en 'plein écran' pour que l'ascenseur apparaisse à droite (ça tombe bien, il se met en plein écran au démarrage ).

Par contre, attention : la phrase
Citation:
Envoyé par Serge57
1ère étape - Identification du bug -– un ascenseur apparaît verticalement quand je rajoute une ligne de menu access supplémentaire.
est plus précise que la suivante
Citation:
Envoyé par Serge57
2éme étape reproduction du bug – dans application « SuiviAffaire » ouvrir le formulaire 10-100 Affaires, si dans la barre de menu il y a plus de deux lignes « de boites outils » un ascenseur vertical apparaît.
En faisant le test que tu prescris, je constate que :
- quel que soit le nombre de barres d'outils,
- si j'en supprime une (menu Affichage > Barres d'outils, ou clic droit dans l'espace des barres d'outils) : aucun problème, pas d'ascenseur,
- si j'en ajoute une : apparition de l'ascenseur, ce qui permet, en le faisant glisser vers le bas, de voir une bande orange en dessous du sous-formulaire ssfAffaires. De plus, à l'oeil nu, cette bande semble avoir à peu près la hauteur d'une barre d'outils.
Citation:
Envoyé par Serge57
3éme étape comprendre ce qui se passe – Il n’y a pas de message d’erreur.
Et voilà le hic ! Ce bug fait partie des pires qui soient . Donc, ça vaut le coup d'y passer un moment, en détail.
Donc tu as dû
- ouvrir le code (Alt+F11) de l'évènement Form_Resize()
- cliquer sur la 1ère ligne (ou autre ?) et appuyer sur F9 pour insérer un 'point d'arrêt'
ou bien
- taper l'instruction Stop
- revenir vers le formulaire,
- faire le test (afficher une nouvelle barre d'outils),
- chercher la valeur de InsideHeight et autres variables, lorsque l'exécution du code s'arrête sur le point d'arrêt ou sur le Stop.
Citation:
Envoyé par Serge57
Je suppose qu’il y a un petit hic sur la valeur de la variable « InsideHeight » retournée par access. J’ai remarqué qu’a chaque affichage d'un nouveau menu, la variable prend une autre valeur. Mais je n’ai pas trouvé de relation cohérante pour faire un "IF" ….
A priori, je ne pense pas qu'il "y ait un hic" sur la propriété « InsideHeight » de notre formulaire.
Je pense qu'elle change, en fonction de la taille allouée au formulaire.
Le bon sens nous dit :
- la fenêtre d'Access contient tout : barre de titre + menu (1 bande) + toutes les barres d'outils (1 bande chacune) + le formulaire, qui occupe "le reste".
- quand on ajoute une barre d'outils ou de menu, on réduit l'espace vertical alloué au formulaire -> à vérifier de test en test.

Je comprends que tu aies du mal à suivre ce qu'il se passe.
Suite des outils de débogage : -------------
Une fois l'exécution du code arrêtée par un point d'arrêt ou une instruction Stop, on peut :
- (rappel) inspecter chaque valeur avec la souris, ou avec Shift+F9,
- appuyer sur F8 pour exécuter chaque instruction en pas à pas.
Normalement !
Ce que je constate aussi :
- si j'ai mis l'arrêt sur la 1ère ligne :
Code :
1
2
3
4
5
6
7
8
9
Private Sub Form_Resize()
Dim NewHeight As Long
Dim NewWidth As Long
 
    Stop: With ssfAffaires
        '1- redimensionnement VERTICAL .....................................
        'Me.InsideHeight = somme de toutes les sections
        'footer est à 0.  Juste mentionnée à titre de précaution (si on met quelque chose dedans + tard)
        NewHeight = Me.InsideHeight - Me.Section(acHeader).Height - Me.Section(acFooter).Height
et que j'appuies sur F8, l'instruction suivante (en jaune) passe sur 'NewHeight = Me.InsideHeight - Me.Section...'
Ce qui est bien.
Mais, si j'appuie encore sur F8 pour exécuter cette instruction, la ligne jaune (prochaine à exécuter) remonte en arrière !!!
L'exécution repasse sur la 1ère ligne !
Non, il n'y a pas vraiment de bug dans Access. Le problème ici, c'est que, à chaque fois qu'on exécute cette 2ème ligne de code, Access considère qu'on a changé la taille du formulaire et relance l'exécution de l'évènement Form_Resize.
Ce qu'on peut constater en appuyant sur Ctrl+L : affichage de la pile des appels.

Ce qu'on voit c'est que, à chaque fois qu'on exécute une ligne de code, la 'Fenêtre de débogage' relance l'exécution de l'évènement !
Résultat : les évènement Form_Resize sont parmi les pires à déboguer , et on ne pourra pas utiliser F8 (faire du pas à pas) dans un évènement Form_Resize().

On va devoir utiliser un autre outil : Debug.Print
L'instruction Debug.Print (sur une ligne de code, il suffit de taper 'Debug.?') va afficher ce qu'on veut, dans la fenêtre d'exécution.
Par exemple :
Code :
1
2
3
4
5
6
7
 
Private Sub Form_Resize()
Dim NewHeight As Long
Dim NewWidth As Long
 
    With ssfAffaires
Debug.? "InsideHeight" Me.InsideHeight
va afficher la valeur de 'InsideHeight' à chaque exécution, sans qu'on ait besoin d'arrêter le code pour autant.
Comme l'instruction est tout en haut de la subroutine, elle affiche la valeur avant d'exécuter notre code. Mais on pourrait aussi en mettre d'autres après, plus bas, pour avoir les résultats.
Si je rééxécute le test (ajout / suppression d'une barre d'outils), je vois des valeurs défiler dans la fenêtre d'exécution, comme, par exemple :
Code :
1
2
3
InsideHeight= 6660 
InsideHeight= 6270 
InsideHeight= 6660
On est donc toujours dans l'étape 3, mais on va pouvoir
- sans mettre aucun Stop ni point d'arrêt,
- savoir la hauteur de chaque objet (NewHeight + Section(acDetail) + ssfAffaires),
- aussi bien avant d'exécuter le code de l'évènement Form_Resize qu'après,
- à chaque opération (agandissement, réduction...).

Est-ce que, avec ces outils, le problème commence à être plus précis ? ou bien tu nages encore plus ????
Papy Turbo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/08/2006, 22h11   #6
Membre du Club
 
Inscription : mai 2006
Messages : 79
Détails du profil
Informations forums :
Inscription : mai 2006
Messages : 79
Points : 57
Points : 57
Citation:
Est-ce que, avec ces outils, le problème commence à être plus précis ? ou bien tu nages encore plus ????
Beaucoup plus pratique que les « MsgBox ‘variable’ » que j’utilisais.

Résultat obtenu des variables.
1er lancement
Code :
1
2
3
4
5
6
 
InsideHeight 13185 
acHeader  2040 
acFooter 0 
NewHeight  11145 
Height  11031
Aprés insertion d’une bande de menu supplémentaire
Code :
1
2
3
4
5
6
 
InsideHeight 12795 
acHeader  2040 
acFooter 0 
NewHeight  10755 
Height  10641
Constat : Réduction de 390 twips de la fenêtre contenant le sous formulaire (InsideHeight) 13185-12795, et réduction de la hauteur du sous formulaire (height) 11031-10641.
Donc la fenêtre contenant le sous formulaire « ssfAffaires » se corrige.

Il reste le formulaire contenant, le formulaire « Affaires ».
Il faudrait réajuster la hauteur du formulaire ?
Je penche pour la variable windowheight. Suis je sur le bon chemin ?
Serge57 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/08/2006, 18h05   #7
Membre Expert
 
Avatar de Papy Turbo
 
Homme Etienne Pailleret
Développeur VBA
Inscription : mars 2004
Messages : 748
Détails du profil
Informations personnelles :
Nom : Homme Etienne Pailleret
Localisation : France, Hauts de Seine (Île de France)

Informations professionnelles :
Activité : Développeur VBA

Informations forums :
Inscription : mars 2004
Messages : 748
Points : 1 114
Points : 1 114
On approche, on approche, mais c'est encore froid.
J'aurais mis un peu plus d'indications, dans ces debug.print, concernant tout ce que nous essayons, avec plus ou moins de succès, de modifier.
Les sections Header et Footer ne bougeront jamais, tes tests le confirment.
Mais la section Détail, par contre, devrait être toujours égale à NewHeight, non ? Et le sous-formulaire aussi, à (2*.Top) près.
Et, comme déjà indiqué, je ferais ces tests 2 fois à chaque resize :
- avant nos opérations (au début de la routine), pour vérifier si on a la même valeur qu'au passage précédent,
- après nos opérations, (juste avant le Exit) pour vérifier si les transformations sont bonnes ?
Avec un mot ("avant" ou "après") dans chaque Debug.Print, pour qu'on sache.

Petite astuce qui peut être utile pour mettre des commentaires dans la fenêtre d'exécution(par exemple noter, pour nous, si tu as ajouté ou si tu as masqué une barre d'outil, avant chaque série de mesure) :
- si tu essayes d'aller à la ligne avec Enter, message d'erreur : Access essaye de compiler et exécuter la ligne.
- tu peux aller à la ligne avec Ctrl+Enter sans afficher ce message d'erreur.

Autre (voir la syntaxe de Debug.Print dans l'aide - F1) :
- tu peux mettre autant de noms et de valeurs que tu veux sur la même ligne, en les séparant par des ";"
- une ligne de commande Debug.Print qui se termine par un ";" ne va pas à la ligne. Donc, la prochaine commande continuera sur la même ligne.
Papy Turbo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/09/2006, 15h35   #8
Membre du Club
 
Inscription : mai 2006
Messages : 79
Détails du profil
Informations forums :
Inscription : mai 2006
Messages : 79
Points : 57
Points : 57
Citation:
Envoyé par Papy Turbo
J'aurais mis un peu plus d'indications, dans ces debug.print, concernant tout ce que nous essayons, avec plus ou moins de succès, de modifier.
Voici le nouveau code .

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 
Private Sub Form_Resize()
Dim NewHeight As Long
Dim NewWidth As Long
 
    With ssfAffaires
        '1- redimensionnement VERTICAL .....................................
        'Me.InsideHeight = somme de toutes les sections
        'footer est à 0.  Juste mentionnée à titre de précaution (si on met quelque chose dedans + tard)
        NewHeight = Me.InsideHeight - Me.Section(acHeader).Height - Me.Section(acFooter).Height
        Debug.Print "—Avant le IF --";
        Debug.Print "InsideHeight="; Me.InsideHeight; " - "; "NewHeight="; NewHeight; " - "; "Height="; .Height; " - "; "acDetail="; Me.Section(acDetail).Height
        If NewHeight > 0 Then
            Debug.Print "Rentre dans le IF"
            Me.Section(acDetail).Height = NewHeight
            'ssfAffaires.Top = 0 : juste au cas où ou mettrait une bordure autour du sous-form, ou...
            .Height = NewHeight - (.Top * 2)
        End If
            '2- redimensionnement HORIZONTAL ...................................
            'NewWidth = Me.InsideWidth
            '.Width = NewWidth - (.Left * 2)
        'astuce, pour réduire la largeur du formulaire à
        '   la largeur du contrôle le plus à droite :
        Me.Width = 0
        Debug.Print "—Aprés le IF --";
        Debug.Print "InsideHeight="; Me.InsideHeight; " - "; "NewHeight="; NewHeight; " - "; "Height="; .Height; " - "; "acDetail="; Me.Section(acDetail).Height
    End With
    Debug.Print " --------------------------------"
End Sub
- Lors du premier lancement le résultat dans la fenêtre exécution est:
Code :
1
2
3
4
5
 --------------------------------
-- Avant le IF --InsideHeight= 13185  - NewHeight= 11145  - Height= 10641  - acDetail= 10755 
Rentre dans le IF
-- Aprés le IF --InsideHeight= 13185  - NewHeight= 11145  - Height= 11031  - acDetail= 11145 
 --------------------------------
Je constate que la section Détail (acdétail) est bien égale à la variable NewHeight et que la hauteur du sous formulaire (height) aussi à (2*Top) près. Donc BON.

Insertion d’une nouvelle barre de menu, résultat dans la fenêtre exécution est :
Code :
1
2
3
4
5
 --------------------------------
-- Avant le IF --InsideHeight= 12795  - NewHeight= 10755  - Height= 11031  - acDetail= 11145 
Rentre dans le IF
-- Aprés le IF --InsideHeight= 12795  - NewHeight= 10755  - Height= 10641  - acDetail= 11088 
 --------------------------------
Le constat n’est plus le même. La section Détail n’a rein à voir avec la variable NewHeight par la la Hauteur du formulaire (Height) elle oui à (2*Top) prés.

Après plusieurs essais et lecture des variables,
- dés que la hauteur du sous formulaire est modifiée, Access recalcule la hauteur du de la section détail.
D’où le nouveau code :
Code :
1
2
3
4
5
6
        If NewHeight > 0 Then
            Debug.Print "Rentre dans le IF"
            .Height = NewHeight - (.Top * 2)
            Me.Section(acDetail).Height = NewHeight
            'ssfAffaires.Top = 0 : juste au cas où ou mettrait une bordure autour du sous-form, ou...
        End If
la différence : D’abord j’impose la hauteur du sous formulaire, puis celle de la section détail du formulaire.

Revenons à nos étapes.

1 - Identification du bug réponse # 4
2 - reproduction du bug réponse #4 corrigé par Papy Turbo dans réponse #5
3 - Comprendre ce qui se passe Si l'on modifie la hauteur d'un sous formulaire (ou sous état), Access recalcul la hauteur de la section ou se trouve "ce sous formulaire."
4 - Trouver la solution Une fois la hauteur du sous formulaire imposer, il faut impose la hauteur de la section contenant le sous formulaire. (Tout en restant logique avec la variable "InsideHeight"
5 - documenter le problème
d'où le nouveau code:
Code :
1
2
3
4
5
6
        If NewHeight > 0 Then
            ' Toujours imposer la hauteur du Sous Formulaire avant la redéfinition de la section le contenant.
            .Height = NewHeight - (.Top * 2) ' hauteur du sous formulaire
            Me.Section(acDetail).Height = NewHeight 'hauteur de la section le contenant
            'ssfAffaires.Top = 0 : juste au cas où ou mettrait une bordure autour du sous-form, ou...
        End If

Citation:
On approche, on approche, mais c'est encore froid.
c'est chaud ??
Serge57 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/09/2006, 15h44   #9
Membre Expert
 
Avatar de Papy Turbo
 
Homme Etienne Pailleret
Développeur VBA
Inscription : mars 2004
Messages : 748
Détails du profil
Informations personnelles :
Nom : Homme Etienne Pailleret
Localisation : France, Hauts de Seine (Île de France)

Informations professionnelles :
Activité : Développeur VBA

Informations forums :
Inscription : mars 2004
Messages : 748
Points : 1 114
Points : 1 114

Ben voilà.
Dans ce sens là, ça marche.

Comme je suis vicieux et à l'intention de tous ceux qui meurent d'envie de se plonger dans le monde fascinant du Form_Resize(), je vais juste montrer ce que j'ai fait (c'est quasi identique à ce que tu as fait, juste une ligne de plus) , et les conclusions.
L'ancien code, au complet, avec les Debug.Print :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Private Sub Form_Resize()
Dim NewHeight                           As Long
Dim NewWidth                            As Long
 
    With ssfAffaires
        '1- redimensionnement VERTICAL .....................................
        'Me.InsideHeight = somme de toutes les sections
        'footer est à 0.  Juste mentionnée à titre de précaution
        '   (si on met quelque chose dedans + tard)
        NewHeight = Me.InsideHeight - Me.Section(acHeader).Height - _
                    Me.Section(acFooter).Height
        If NewHeight > (.Top * 2) Then
Debug.Print "1 | InsideHeight="; Me.InsideHeight; "| NewHeight="; NewHeight; _
            "| Section(acDetail)="; Section(acDetail).Height; _
            "| hauteur ssf avec bordure="; .Height + (.Top * 2); _
            "| ssfAffaires"; .Height; "| (.Top * 2)="; (.Top * 2)
            Me.Section(acDetail).Height = NewHeight
Debug.Print "2 | InsideHeight="; Me.InsideHeight; "| NewHeight="; NewHeight; _
            "| Section(acDetail)="; Section(acDetail).Height; _
            "| hauteur ssf avec bordure="; .Height + (.Top * 2); _
            "| ssfAffaires"; .Height; "| (.Top * 2)="; (.Top * 2)
            .Height = NewHeight - (.Top * 2)
Debug.Print "3 | InsideHeight="; Me.InsideHeight; "| NewHeight="; NewHeight; _
            "| Section(acDetail)="; Section(acDetail).Height; _
            "| hauteur ssf avec bordure="; .Height + (.Top * 2); _
            "| ssfAffaires"; .Height; "| (.Top * 2)="; (.Top * 2)
Debug.Print "----------------------------------"
        End If
        '2- redimensionnement HORIZONTAL ...................................
        NewWidth = Me.InsideWidth
        .Width = NewWidth - (.Left * 2)
        ''End If
        'astuce, pour réduire la largeur du formulaire à
        '   la largeur du contrôle le plus à droite :
        Me.Width = 0
    End With
 
End Sub
Note : j'utilise l'autre outil de base, indispensable sous Access pour y voir clair : SmartIndenter de Stephen Bullen (OA Ltd), disponible gratuitement depuis la page Outils
Il a la particularité se mettre (en option seulement, mais ça me plaît) tous les Debug.? dans la marge, à gauche, et plein d'autres options...
Et le résultat, copié de la fenêtre d'exécution ou j'ai rajouté le type d'action (ajout ou suppression barre d'outils) :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Suppression d'une barre d'outils (formulaire s'aggrandit)
1 | InsideHeight= 9705 | NewHeight= 7665 | Section(acDetail)= 7275 | hauteur ssf avec bordure= 7275 | ssfAffaires 7161 | (.Top * 2)= 114 
2 | InsideHeight= 9705 | NewHeight= 7665 | Section(acDetail)= 7665 | hauteur ssf avec bordure= 7275 | ssfAffaires 7161 | (.Top * 2)= 114 
3 | InsideHeight= 9705 | NewHeight= 7665 | Section(acDetail)= 7665 | hauteur ssf avec bordure= 7665 | ssfAffaires 7551 | (.Top * 2)= 114 
----------------------------------
Ajout d'une barre d'outils (formulaire est réduit)
1 | InsideHeight= 9315 | NewHeight= 7275 | Section(acDetail)= 7665 | hauteur ssf avec bordure= 7665 | ssfAffaires 7551 | (.Top * 2)= 114 
2 | InsideHeight= 9315 | NewHeight= 7275 | Section(acDetail)= 7608 | hauteur ssf avec bordure= 7665 | ssfAffaires 7551 | (.Top * 2)= 114 
3 | InsideHeight= 9315 | NewHeight= 7275 | Section(acDetail)= 7608 | hauteur ssf avec bordure= 7275 | ssfAffaires 7161 | (.Top * 2)= 114 
---------------------------------- apparition de l'ascenseur (acDetail trop petite)
? 114/2
 57 
? 7551 + 57
 7608
Comme tu le constates, je me suis demandé pourquoi, en réduction, la section détail ne faisait que 7608 twips, et pas 7275 "comme tout le monde" ?
Lorsqu'on essaye de réduire la section acDetail,
- elle contient un sous formulaire qui mesure encore 7551 twips (il n'a pas encore été réduit),
- le ssf démarre à 57 twips (=.Top) du haut de la section.
Access essaie en fait de le réduire, mais (bon sens ?), il ne peut pas le réduire plus que ce qu'il contient !!!

Dans l'autre sens, en inversant les 2 lignes comme toi, on constate des choses intéressantes :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
        If NewHeight > (.Top * 2) Then
Debug.Print "1 | InsideHeight="; Me.InsideHeight; "| NewHeight="; NewHeight; _
            "| Section(acDetail)="; Section(acDetail).Height; _
            "| hauteur ssf avec bordure="; .Height + (.Top * 2); _
            "| ssfAffaires"; .Height; "| (.Top * 2)="; (.Top * 2)
            'Toujours imposer la hauteur du Sous Formulaire (contenu)
            '            AVANT la redéfinition de la section le contenant.
            .Height = NewHeight - (.Top * 2)
Debug.Print "2 | InsideHeight="; Me.InsideHeight; "| NewHeight="; NewHeight; _
            "| Section(acDetail)="; Section(acDetail).Height; _
            "| hauteur ssf avec bordure="; .Height + (.Top * 2); _
            "| ssfAffaires"; .Height; "| (.Top * 2)="; (.Top * 2)
            Me.Section(acDetail).Height = NewHeight
Debug.Print "3 | InsideHeight="; Me.InsideHeight; "| NewHeight="; NewHeight; _
            "| Section(acDetail)="; Section(acDetail).Height; _
            "| hauteur ssf avec bordure="; .Height + (.Top * 2); _
            "| ssfAffaires"; .Height; "| (.Top * 2)="; (.Top * 2)
Debug.Print "----------------------------------"
        End If
Résultat :
Note : ne pas oublier la gomme, sur la barre d'outils de mzTools, pour nettoyer la fenêtre d'exécution
Code :
1
2
3
4
5
6
7
8
9
10
Ajout d'une barre d'outils
1 | InsideHeight= 9315 | NewHeight= 7275 | Section(acDetail)= 7608 | hauteur ssf avec bordure= 7665 | ssfAffaires 7551 | (.Top * 2)= 114 
2 | InsideHeight= 9315 | NewHeight= 7275 | Section(acDetail)= 7608 | hauteur ssf avec bordure= 7275 | ssfAffaires 7161 | (.Top * 2)= 114 
3 | InsideHeight= 9315 | NewHeight= 7275 | Section(acDetail)= 7275 | hauteur ssf avec bordure= 7275 | ssfAffaires 7161 | (.Top * 2)= 114 
----------------------------------
Suppression barre
1 | InsideHeight= 9705 | NewHeight= 7665 | Section(acDetail)= 7275 | hauteur ssf avec bordure= 7275 | ssfAffaires 7161 | (.Top * 2)= 114 
2 | InsideHeight= 9705 | NewHeight= 7665 | Section(acDetail)= 7608 | hauteur ssf avec bordure= 7665 | ssfAffaires 7551 | (.Top * 2)= 114 
3 | InsideHeight= 9705 | NewHeight= 7665 | Section(acDetail)= 7665 | hauteur ssf avec bordure= 7665 | ssfAffaires 7551 | (.Top * 2)= 114 
----------------------------------
Cette fois-ci (je suis d'accord, faut être grave pour pinailler comme ça), c'est quand on supprime une barre qu'on constate un hic.
Sur la ligne 2,
- On n'a pas encore touché à la section acDetail,
- on a agrandi le ssf de 7161 à 7551,
- la section détail a été agrandie (par access) de 7275 à 7608 (soit toujours de quoi contenir le ssf et son .Top, 7608 = 7551 + 57)
En conclusion,
- quand on agrandit un contrôle à l'intérieur d'une section, Access agrandit la section pour contenir le tout,
- quand on essaye de réduire la section, il limite la réduction à la taille des contrôles contenus.


Maintenant, faut pas rêver en pensant que c'est fini !
C'est bien fini dans notre cas, mais, si j'ai insisté pour bien comprendre le mécanisme, c'est qu'un jour ou l'autre, tu vas tomber sur d'autres conteneurs de contrôles, qui ne se comporteront peut être pas comme la section acDetail !!!
Et là, suffira de faire les mêmes tests, comprendre, solution, commentaire.

Bon, ben on retourne à notre formulaire, dans le cours #03, nouvelle réponse #12.
Papy Turbo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/03/2007, 13h21   #10
Membre Expert
 
Avatar de Papy Turbo
 
Homme Etienne Pailleret
Développeur VBA
Inscription : mars 2004
Messages : 748
Détails du profil
Informations personnelles :
Nom : Homme Etienne Pailleret
Localisation : France, Hauts de Seine (Île de France)

Informations professionnelles :
Activité : Développeur VBA

Informations forums :
Inscription : mars 2004
Messages : 748
Points : 1 114
Points : 1 114
Par défaut Bug dans CheckTablesConnection()

Reprenons à partir de l'application 'mise à jour de données', jointe à ta réponse #22 du cours 05.

Le 1er problème vient du fait qu'on a une monstruosité dans le code de gestion d'erreur :
Code :
1
2
3
4
5
Catch:
Debug.Print Err, Err.Description
    If Debugging Then
        Resume
    End If
Déjà, est-ce que tu vois bien ce qui cloche ? Qu'est-ce qu'il va se passer si jamais Debugging est vrai ? Tu peux faire le test
Ensuite, oublions comment cette énormité est arrivée là, un copier/glisser quelconque ? et reprenons la notion de base avec une La Palissade : les seules erreurs à trouver sont les erreurs non prévues.
La bonne routine de gestion d'erreurs non prévues, dans notre cas, redevient donc :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Finally:
    Set db = Nothing
    Exit Sub    '=================================
Catch:
    Debug.Print Err, Err.Description
    Select Case MsgBox(Err.Description, vbAbortRetryIgnore + vbCritical, Title)
    Case vbAbort
        Resume Finally
    Case vbRetry
        If Debugging Then Stop
        Resume
    Case vbIgnore
        Resume Next
    End Select
End Sub
- J'inclus le Finally: dedans, parce qu'il est utile à de très nombreuses routines, comme on l'a déjà vu. Ici, pour fermer l'objet db proprement. Mais, tant qu'à faire, il manque aussi 'td' et 'ConnectTest'...
Je répète lourdement le but : on ne peut pas quitter cette routine sans passer par le Finally:, même (et surtout) s'il y a une erreur non prévue.
- le Debug.? sera utile pour nous, pour retrouver le n° et description d'erreur pendant et surtout après le débogage, quand on en sera à la gestion d'erreur connue (identifiée, déboguée, à traiter).

- les 3 choix sont utiles pour un utilisateur en face d'une erreur non prévue. Il peut :
1- parfois, corriger l'erreur : il faut introduire une disquette ou clé USB, ou se reconnecter au réseau... Ensuite, il clique sur Réessayer et ça devrait marcher.
2- sinon, il clique sur Ignorer. Ça peut surprendre, mais dans bon nombre de cas, ça marche quand même.
3- si la 1ère erreur en déclenche d'autres, comme une 'variable objet non définie'..., il clique sur Annuler. Puis il recommence le tout.

- Enfin, le Stop va nous permettre, si Debugging est vrai (à faire dans appInit() et dans la fenêtre d'exécution : ThisApp.debugging = True) de cliquer sur Réessayer > l'exécution s'arrête au Stop > on reprend avec F8 qui va faire un Resume > on continue en pas à pas, toujours avec F8...
À partir de là, faut se creuser le ciboulot pour bien comprendre
- comment marche ce code ?
- qu'est-ce qui cloche ?
Déjà, tu as vu qu'il faut être très rigoureux avec tes tests et les méthodes de débogage d'une routine écrite par toi.
Mais c'est beaucoup plus drôle de déboguer quelque chose qui a été écrit par quelqu'un d'autre
Et si j'en juge par la constante mauvaise humeur des développeurs qui reprennent un code "bidouillé par je ne sais quel tocard-nulard", ça arrive tout le temps.
Donc, c'est ton tour de me déboguer, pendant que je vais boire l'apéro.

Je ne m'attends pas à ce que tu cherches des jours et des jours, pour apporter la solution toute crue. N'hésite pas à expliquer ce que tu as fait, les difficultés, ce que tu ne comprends pas... On va chercher ensemble (après l'apéro).
Papy Turbo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/03/2007, 22h18   #11
Membre du Club
 
Inscription : mai 2006
Messages : 79
Détails du profil
Informations forums :
Inscription : mai 2006
Messages : 79
Points : 57
Points : 57
Citation:
Envoyé par Papy Turbo
Je ne m'attends pas à ce que tu cherches des jours et des jours, pour apporter la solution toute crue. N'hésite pas à expliquer ce que tu as fait, les difficultés, ce que tu ne comprends pas... On va chercher ensemble (après l'apéro).
Donc j’explique MA démarche.
La ‘reconnections’ des tables utilisent les variables « OldBase » et « NewBase »
Dans la ‘sub Reconnect’ la variable « OldPathName » me semble bien formaté (chemin + nom) alors que la variable « NewPathName » il manque le nom du fichier. Bonne approche ???

Citation:
On va chercher ensemble (après l'apéro).
l’apéro est fini (4 jours d’apéro c’est pas mal !!!). Mille escuses pour les retards, mais beaucoup de charge et voyage ….
Serge57 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/03/2007, 10h35   #12
Membre Expert
 
Avatar de Papy Turbo
 
Homme Etienne Pailleret
Développeur VBA
Inscription : mars 2004
Messages : 748
Détails du profil
Informations personnelles :
Nom : Homme Etienne Pailleret
Localisation : France, Hauts de Seine (Île de France)

Informations professionnelles :
Activité : Développeur VBA

Informations forums :
Inscription : mars 2004
Messages : 748
Points : 1 114
Points : 1 114
Bonne approche ?
- Tu n'es peut être pas loin, mais je ne sais pas si tu as la bonne méthode.
En tout cas, tu n'es pas sûr de toi, donc il manque quelque chose.
Sur la méthode :
- tu examines ta routine, si les variables font bien leur boulot...
Tu risques d'y passer des heures et des jours, à revérifier chaque variable, chaque algorythme, chaque calcul...

Pour l'instant, ce que je cherche en premier, c'est : "quelle est la ligne qui provoque une erreur # ???, message "le nom de fichier est incorrect".
Le n° d'erreur est généralement important. C'est par là qu'on l'identifie et qu'on va la traiter, si besoin.

Donc,
- si tu as bien suivi les corrections indiquées plus haut,
tu dois pouvoir
- relancer le programme,
- obtenir l'erreur,
- noter son n° et son message (merci, Debug.?)
- t'arrêter sur la ligne : - Resume te ramène effectivement sur
Code :
Reconnect OldBase, NewBase
À partir de là, faut trouver la ligne "qui plante", seul moyen d'être sûr que le problème est bien là.
Papy Turbo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/04/2007, 23h13   #13
Membre du Club
 
Inscription : mai 2006
Messages : 79
Détails du profil
Informations forums :
Inscription : mai 2006
Messages : 79
Points : 57
Points : 57
Citation:
Envoyé par Papy Turbo
Donc,
- si tu as bien suivi les corrections indiquées plus haut,
tu dois pouvoir
- relancer le programme,
- obtenir l'erreur,
- noter son n° et son message (merci, Debug.?)
- t'arrêter sur la ligne :
Numéro de l’erreur est 3055 ‘ Nom de Fichier incorrect’

La ligne qui pose problème se trouve dans la ‘Sub Reconnect ….’
Code :
1
2
3
4
5
 
If InStr(.Connect, OldPathName) > 0 Then
   .Connect = JET_PREFIX & NewPathName
   .RefreshLink
End If
La variable 'NewParhName' a bien le nouveau répertoire mais pas le nom du fichier .

Donc pour corriger: ancien code
Code :
 Reconnect OldBase, NewBase
Nouveau code
Code :
 Reconnect OldBase, NewBase & FileName
Des tests …. Et ça marche !!!!
Serge57 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/04/2007, 19h15   #14
Membre Expert
 
Avatar de Papy Turbo
 
Homme Etienne Pailleret
Développeur VBA
Inscription : mars 2004
Messages : 748
Détails du profil
Informations personnelles :
Nom : Homme Etienne Pailleret
Localisation : France, Hauts de Seine (Île de France)

Informations professionnelles :
Activité : Développeur VBA

Informations forums :
Inscription : mars 2004
Messages : 748
Points : 1 114
Points : 1 114
Ben, bravo !
Tu as
- trouvé la ligne qui plante,
- du coup, tu es sûr du problème à résoudre,
et tu as la solution sans trop de difficulté.

Mais, ce qui m'intéresse, plus encore que la solution, c'est la méthode.
Autrement dit, comment tu as fait pour t'arrêter sur la ligne qui plante, bien qu'elle soit dans une routine qui n'a aucun contrôle d'erreur (pas de On Error Goto ...), laquelle est appelée par une routine qui en a... ?

On est là pour connaître à fond tous les outils de débogage.
Autrement dit, savoir où se trouvent les interrupteurs qui permettent d'allumer et de ne pas rater une marche quand on descend à la cave fouiller dans le charbon..., si tu vois ce que je veux dire.

Donc, n'hésite pas à raconter les marches ratées, les outils, les options, les paramètres que tu as changés pour y arriver.
Papy Turbo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/04/2007, 14h15   #15
Membre du Club
 
Inscription : mai 2006
Messages : 79
Détails du profil
Informations forums :
Inscription : mai 2006
Messages : 79
Points : 57
Points : 57
Citation:
Envoyé par Papy Turbo
Mais, ce qui m'intéresse, plus encore que la solution, c'est la méthode
Pour trouver le numéro et le type d’erreur:

1- dans l’éditeur VBA, menu ‘Options’ - ‘Général’ – ‘Récupération de erreurs’ – coché la case ‘Arrêt sur toutes les erreurs’
2- Relancer l’application.
3- Retourne l’erreur 3044 (chemin non valide pour le fichier) sur la ligne ‘Set ConnectTest = db.OpenRecordset(td.Name)’
4- Remettre dans l’éditeur VBA ‘Arrêt sur les erreures non gérées’
5- Relancer l’application‘
6- Dérouler la routine pas à pas « touche F8 », lors du choix du fichier et de l’essai de reconnections (Reconnect OldBase, NewBase), dans la variable ‘NewBase’, le chemin est bien formaté, mais il manque le nom du fichier.
7- Conclusion ‘Reconnect OldBase, NewBase & Filename’


Dure d’expliquer la démarche !!
Serge57 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/04/2007, 17h34   #16
Membre Expert
 
Avatar de Papy Turbo
 
Homme Etienne Pailleret
Développeur VBA
Inscription : mars 2004
Messages : 748
Détails du profil
Informations personnelles :
Nom : Homme Etienne Pailleret
Localisation : France, Hauts de Seine (Île de France)

Informations professionnelles :
Activité : Développeur VBA

Informations forums :
Inscription : mars 2004
Messages : 748
Points : 1 114
Points : 1 114
Par défaut [Travaux pratiques] et notions de base sur la gestion d'erreurs

Citation:
Envoyé par Serge57
Dure d’expliquer la démarche !!
Je veux bien te croire
Ta démarche est bonne, puisque tu as trouvé. Mais j'ai insisté parce que mon petit doigt me disait que tu avais eu du mal à trouver ça, et donc, que quelques concepts de base n'étaient pas encore tout à fait clairs.
Voici ma démarche, quasi identique, pour trouver la ligne qui donne l'erreur :
1- déjà exposé en détail, arrêt, dans notre code de gestion d'erreur, sur le Stop,
2- F8 sur le Resume, ce qui me ramène sur la ligne Reconnect OldBase, NewBase
3- toujours F8 pour entrer dans la Sub Reconnect(...)
4- Pause : dès que je constate que cette Sub n'a aucun contrôle d'erreur (pas de 'On Error Goto ...'), c'est que j'ouvre le menu Outils > Options > Général pour choisir Arrêt sur toutes les erreurs,
5- puis, pour gagner du temps, F5 (exécution complète)
6- l'exécution s'arrête sur .RefreshLink, avec le message d'erreur 'Nom de fichier incorrect' > clic sur débogage.
À partir de là, le problème est quasiment résolu : je suis sur l'erreur proprement dite, RefreshLink plante, donc le nouveau chemin + nom de fichier ne doit pas être correct...

Maintenant, tâchons de clarifier tout cela :
- quand utilise t'on Arrêt sur erreurs non gérées ou bien Arrêt sur toutes les erreurs ?
- À quoi peut bien servir l'option Arrêt dans le module de classe ?

Il y a quelques notions de base que les 2 exercices ci-dessous, et les centaines de variations que je te conseille de pousser plus loin (ajouter plusieurs routines qui s'appellent l'une l'autre, sur plus de niveaux ; mettre du contrôle d'erreur à des niveaux variables ; etc.) doivent rendre absolument évidentes pour tout développeur :
L'ensemble de notre code se divise en 2 catégories : erreurs gérées ou erreurs non gérées.
Le code avec erreurs gérées
- commence avec un 'On Error Goto ...' ou bien 'On Error Resume Next'
- se termine avec un 'On Error Goto 0', ou bien avec la fin de la routine (End/Exit Sub/Function...)
- inclut tout le code contenu dans les subroutines appelées, à condition qu'il n'y ait pas d'autre gestion d'erreur dans la routine appelée. Sinon, c'est cette gestion d'erreur locale qui prend le pas, jusqu'à ce qu'on remonte à l'appelant ou qu'on rencotre un 'On Error Goto 0'.

Tant qu'aucune erreur n'est gérée, c'est facile pour nous : l'exécution s'arrête en affichant la boîte avec les options 'fin / débogage', ce qui nous permet de corriger (ou gérer) l'erreur.
Si une erreur se produit
- dans un bloc avec gestion d'erreur : l'exécution continue là où nous l'avons spécifié avec le On Error...,
- dans un bloc sans gestion d'erreur,
--- soit la routine où se produit l'erreur est appelée depuis une autre -> VBA va 'remonter' jusqu'à la gestion d'erreur spécifiée dans l'appelant.
--- soit la routine n'est appelée par aucune autre : l'exécution s'arrête en affichant la boîte avec les options 'fin / débogage'.
--- soit il n'y a aucune gestion d'erreur à aucun niveau : l'exécution s'arrête également, au niveau d'appel le plus bas, sur la ligne qui a provoqué l'erreur, en affichant la boîte avec les options 'fin / débogage'.


Exercices : lancer chaque exercice en cliquant dans le code + F5.
Routine simple, pas de contrôle d'erreur
Code :
1
2
3
4
5
 Public Sub TestLevel0()
    Debug.Print "Level 0 - Instruction 1"
    Error 16
    Debug.Print "Level 0 - Instruction 2"
End Sub
Tester avec les 3 options :
Arrêt sur :
- toutes les erreurs
- dans module de classe
- erreurs non gérées
Ici, quelle que soit l'option, l'exécution s'arrête sur la ligne d'erreur et affiche la boîte avec les options 'fin / débogage'.

Routine simple, avec contrôle d'erreur
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 Public Sub TestLevel0()
    On Error GoTo Catch
    Debug.Print "Level 0 - Instruction 1"
    Error 16
    Debug.Print "Level 0 - Instruction 2"
Finally:
    Exit Sub    '======================
Catch:
    Debug.Print Err; Err.Description
    Select Case MsgBox(Err.Number & " - " & Err.Description, vbAbortRetryIgnore, "Tests contrôle d'erreur")
    Case vbAbort
        Resume Finally
    Case vbRetry
        Resume
    Case Else   ' = vbIgnore
        Resume Next
    End Select
End Function
TEST. Arrêt sur :
- toutes les erreurs : boîte de débogage (Fin/débogage), impossible de continuer avec F8
- dans module de classe : pas d'arrêt, contrôle d'erreur actif -> notre MsgBox s'affiche
- erreurs non gérées : idem module de classe.

2 niveaux de routines, contrôle d'erreur au niveau appelant (niveau 0) :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 Public Sub TestLevel0()
    On Error GoTo Catch
    Debug.Print "Level 0 - Instruction 1"
    Testlevel1
    Debug.Print "Level 0 - Instruction 2"
Finally:
    Exit Sub    '======================
Catch:
    Debug.Print Err; Err.Description
    Select Case MsgBox(Err.Number & " - " & Err.Description, vbAbortRetryIgnore, "Tests contrôle d'erreur")
    Case vbAbort
         Resume Finally
    Case vbRetry
         Resume
    Case Else   ' = vbIgnore
         Resume Next
    End Select
End Function
'---------------------------
Sub Testlevel1()
    Debug.Print "Level 1 - Instruction 1"
    Error 16
    Debug.Print "Level 1 - Instruction 2"
End Sub
TEST. Arrêt sur :
- toutes les erreurs : arrêt dans TestLevel1, sur l'erreur
impossible d'aller + loin avec F8
- dans module de classe : pas d'arrêt, contrôle d'erreur actif au niveau 0 -> notre MsgBox s'affiche
L'instruction : Debug.Print "Level 1 - Instruction 2" ne sera jamais exécutée.
- erreurs non gérées : idem module de classe.
Refaire le même, sans aucune gestion d'erreur, seulement au niveau bas...

Appel d'une méthode, dans un module de classe
Toujours dans Module1, l'appelant devient :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 Public Function TestLevel0()
Dim Object1 As Classe1
 
    On Error GoTo Catch
    Debug.Print "Level 0 - Instruction 1"
    Set Object1 = New Classe1
    Object1.Method1
    Debug.Print "Level 0 - Instruction 2"
Finally:
    Exit Function    '======================
Catch:
    Debug.Print Err; Err.Description
    Select Case MsgBox(Err.Number & " - " & Err.Description, vbAbortRetryIgnore, "Tests contrôle d'erreur")
    Case vbAbort
         Resume Finally
    Case vbRetry
         Resume
    Case Else   ' = vbIgnore
         Resume Next
    End Select
End Function
Dans le module de classe Classe1 :
Code :
1
2
3
4
5
 Public Sub Method1()
    Debug.Print "Class module - Instruction 1"
    Error 16
    Debug.Print "Class module - Instruction 2"
End Sub
TEST. Arrêt sur :
- toutes les erreurs :
arrêt dans Method1, sur l'erreur
impossible d'aller + loin avec F8
- dans module de classe :
idem toutes les erreurs : l'exécution s'arrête directement sur l'erreur.
- erreurs non gérées :
pas d'arrêt, contrôle d'erreur actif -> notre MsgBox s'affiche
L'instruction : Debug.Print "Class module - Instruction 2" ne sera jamais exécutée.

Quel est l'intérêt de cette distinction ? Pourquoi s'arrêter spécifiquement dans les modules de classe et non pas dans les modules standards ???
Il m'a fallu quelques années pour y comprendre quelque chose.
Pour cela, il faut penser à la réutilisation du code.
Je vais simplifier bien sûr, en répondant à la question : Quand utilise t'on des modules de classe ? et en ne donnant que 2 réponses :
1- pour créer des objets métier : ces objets peuvent être réutilisés dans plusieurs applications complémentaires les unes des autres.
2- pour se constituer une bibliothèque (Library) de code réutilisable dans toutes (ou au moins dans plusieurs) de nos applications.
Le 2ème cas est plus subtil, parce qu'il n'y aura pas QUE des modules de classe dans une librairie complète. Il y aura des modules de classe et des routines simples, dans des modules standards.

Exemple :
Nous avons déjà 2 applications en chantier : SuiviAffaires (l'application principale) + SuiviAffaire_MàJ (mise à jour de la BDD).
Admettons que nous voulions réutiliser, dans SuiviAffaires, le mécanisme qui permet à SuiviAffaire_MàJ
- de vérifier si les tables sont bien attachées
et, en cas d'erreur,
- d'ouvrir la boîte de dialogue pour que l'utilisateur puisse indiquer l'emplacement de la base,
puis,
- reconnecter automatiquement toutes nos tables.
nous allons avoir besoin de :
- 2 classes : clApplication + clLog
- au moins notre module 'APIsWindows', qui contient OuvrirFichierSpécifique()...
- peut être d'autres Subs et Fonctions utilisées 2 fois ?

Plutôt que de copier ces modules d'une application à l'autre, je conseillerais fortement de:
- créer une base de données indépendante, par exemple Librairie.mdb
- d'y copier (ou importer) les modules concernés.
Puis, dans chacune des 2 applications (et au delà, dans toutes tes futures applications),
- ajouter une simple référence à Librairie.mdb (dans VBA, menu Outils > Références)

À moyen et long terme, les avantages sont considérables : un seul code à corriger et/où compléter, réutilisable partout.
+ le fait que la librairie peut être compilée en une Librairie.mde, donc code sécurisé
L'inconvénient par contre : il n'est pas très pratique de déboguer un code dans une librairie partagée, même si c'est possible (pas dans un .mde).
Notre cas est typique : nous avons trouvé une erreur dans une méthode (CheckConnections) appartenant à un des objets qu'on souhaiterait réutiliser ailleurs.
Il faut donc impérativement
1- utiliser et déboguer complètement cette partie du code, tant qu'elle est incluse directement dans la 1ère application. C'est + facile, c'est ce que nous sommes en train de faire avec la classe clApplication, et c'est pour cette raison que nous avons du code de gestion d'erreur. Ça nous permet de nous arrêter et de corriger ou compléter cette méthode, ainsi que les routines comme Reconnect, qu'elle appelle.
2- une fois qu'elle aura été correctement déboguée, nous allons la déplacer dans la librairie partagée, pour pouvoir la réutiliser.

Et c'est là, ou peut être déjà depuis un bon 1/4 d'heure ? que tu vas me dire : quel rapport avec notre contrôle d'erreur et les options d'arrêt ???
J'y arrive : tout cet exposé pour bien comprendre le principe suivant :
Tout le code de notre application est contenu dans des routines qui s'appellent les unes les autres.
Tout déclenchement de code part toujours
- soit de la fonction de démarrage App_Init(),
- soit d'un évènement de l'interface utilisateur : clic sur un bouton, lancement d'une commande dans un menu spécifique, saisie d'une valeur dans un contrôle...
Les propriétés et les méthodes de nos objets (modules de classe), de même que tout ce que nous mettrons dans une librairie réutilisable, ne seront jamais appelés en direct, mais toujours à partir d'une des routines ci-dessus, déclenchée depuis l'interface.
Par rapport aux tests ci dessus, elles ne seront jamais au niveau 0.

Lorsque nous allons terminer notre application pour la distribuer à d'autres utilisateurs, nous allons
1- mettre du code de contrôle d'erreur à toutes les routines au niveau de l'interface utilisateur (dans tous les évènement de tous les formulaires et/ou de tous les états et de leurs contrôles) + dans la fonction de démarrage App_Init().
Grâce à ce contrôle d'erreur, nous sommes assurés que les utilisateurs de notre application :
- ne verront jamais la boîte de dialogue avec options Débogage/Fin (ils ne sont pas censés rentrer dans le code pour déboguer)
- que notre contrôle d'erreurs non prévues sera toujours actif, avec ses 3 options : Annuler/Réessayer/Ignorer
- de +, si nous avons prévu d'enregistrer l'erreur dans un journal, toute erreur non prévue y sera bien enregistrée (ce qui nous sera beaucoup plus utile que les indications usuelles des utilisateurs qui ne retiennent jamais les messages d'erreur... )
Même si l'erreur se produit dans une sub-sub-sub...routine, à n'importe quel niveau, elle sera contrôlée, affichée, enregistrée.

2- à l'inverse, nous n'allons mettre aucun code de contrôle d'erreur dans notre librairie. Ou disons, le strict minimum.
Et pareil dans nos objets métier.
Ceci est volontaire.
Lorsqu'on appelle une commande de VBA, par exemple FileCopy et qu'une erreur se produit ("File not found", par exemple), l'erreur n'est pas gérée à l'intérieur de la commande FileCopy. Elle nous est renvoyée au niveau de notre application, pour que nous puisssions la traiter sur place et afficher les messages clairs à notre utilisateur ("Impossible de trouver le fichier Clients", par exemple).
Nous devons, après les avoir correctement déboguées, considérer nos routines, encapsulées dans notre librairie, comme un complément de VBA, une surcouche du langage.
Nos commandes de librairie (par exemple ThisApp.CheckTablesConnection) doivent être utilisées comme si elles faisaient partie d'une version étendue d'Access ou de VBA. Nous n'avons fait qu'ajouter une méthode personalisée à l'objet Application d'Access.
Elles ne devraient pas afficher un message à l'utilisateur : c'est le programmeur de chaque application qui va
- capturer l'erreur au niveau de l'appel,
- personaliser chaque message dans la langue de l'utilisateur, et en fonction du contexte de chaque application.
Elles vont donc se contenter de renvoyer les erreurs au niveau appelant : à l'application qui utilise la librairie.

Et voilà la seule explication que je puisse trouver pour justifier la présence de l'option "Arrêt dans les modules de classe" qui sont, par définition, réutilisables et ne gèrent normalement pas les erreurs non prévues.
Bien entendu, il y a des exceptions
Regardons en une, que nous utilisons déjà, la fonction CopyFile().
Comme par hasard, l'original provient de ma librairie usuelle : je l'utilise partout, à la place de la commande VBA FileCopy()
Lorsqu'elle aura été incluse dans une librairie, CopyFile() permettra, comme ici,
- de contrôler que la source est bien différente de la destination. Note qu'elle n'affiche pas de message d'erreur : elle le renvoit avec un Err.Raise. Le programmeur de l'application principale pourra afficher ou non le message, ou gérer l'erreur dans son On Error Goto...
- de gérer le fait que le fichier de destination peut déjà exister : faut-il le supprimer ou l'écraser, avec message ou sans rien dire...
Là, je suppose que tu as remarqué un petit hic : la routine affiche éventuellement un message. Idéalement, il faudrait que le programmeur de chaque application puisse modifier ce message grâce à un des arguments d'appel de CopyFile().
Si d'autres erreurs non prévues se produisent, elles déclencheront le contrôle d'erreur de l'application principale qui pourra les gérer comme s'il s'agissait d'une erreur dans une commande VBA.

Voili voilou. Si ces notions sont parfaitement claires :
- distinction entre code avec ou sans gestion d'erreur,
- niveaux d'appels de code entre les diverses routines,
- comment VBA 'remonte' en cas d'erreur 'en bas', jusqu'à ce qu'il trouve une gestion d'erreur,
- faut-il gérer les erreurs non prévues et est-il préférable de ne pas gérer les erreurs non prévues ?
tu es à 2 doigts de créer des applications solides, que tu pourras déboguer rapidement, au fur et à mesure que les tests (préliminaires, beta tests ou déploiement réel) révèlent des erreurs non prévues.
Papy Turbo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/05/2007, 21h15   #17
Membre du Club
 
Inscription : mai 2006
Messages : 79
Détails du profil
Informations forums :
Inscription : mai 2006
Messages : 79
Points : 57
Points : 57
Citation:
Envoyé par Papy Turbo
Voili voilou. Si ces notions sont parfaitement claires : …. tu es à 2 doigts de créer des applications solides, que tu pourras déboguer rapidement, au fur et à mesure que les tests (préliminaires, beta tests ou déploiement réel) révèlent des erreurs non prévues.
J’ai fait beaucoup d’essais, et je pense avoir compris le principe, mais pour le mettre en pratique on va voir !!

Deux petites remarques (ou éclaircissement)
Pas compris la différence entre un module de classe et un module ‘normal’ !!!

Citation:
Envoyé par Papy Turbo
- créer une base de données indépendante, par exemple Librairie.mdb
Lors de la distribution de l’application, il faudra joindre la librairie ???
Serge57 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/05/2007, 12h01   #18
Membre Expert
 
Avatar de Papy Turbo
 
Homme Etienne Pailleret
Développeur VBA
Inscription : mars 2004
Messages : 748
Détails du profil
Informations personnelles :
Nom : Homme Etienne Pailleret
Localisation : France, Hauts de Seine (Île de France)

Informations professionnelles :
Activité : Développeur VBA

Informations forums :
Inscription : mars 2004
Messages : 748
Points : 1 114
Points : 1 114
Citation:
Envoyé par Serge57
Pas compris la différence entre un module de classe et un module ‘normal’ !!!
Réponse tellement évidente (dès que tu auras utilisé quelques modules de classe), que ça va pas être facile
Essayons un petit résumé :

Module standard :
- contient des variables Public ou Privées (avec Dim...)
- contient des procédures Sub et Function, qui peuvent être Public, donc appelées depuis n'importe quel autre module, ou Private, donc utilisables seulement à partir d'une autre procédure du même module.

Module de classe :
(voir cours 05-Mise à jour BDD, les classes clApplication et clLog)
- permet de créer un 'objet', doté de propriétés (=variables qui appartiennent à l'objet) et de méthodes (procédures qui appartiennent à l'objet).
- les propriétés utilisent des Property Get et Property Let, (Voir Get/Let Name dans clLog) pour lire ou modifier la propriété.
Raccourci : une variable publique dans le module de classe - voir Public Title as String, dans clApplication - n'a pas besoin des Property Letou Get.

La valeur de la propriété est stockée dans une variable (mName ou Title, dans les exemples), à l'intérieur de l'objet.
- les méthodes sont des Sub (qui ne renvoient rien) et des Function (qui peuvent renvoyer une valeur), comme dans un module standard.
- les propriétés et les méthodes sont Public ou Private, comme dans un module standard.
Note : Les librairies externes utilisent aussi des procédures Friend. Celles-ci sont 'publiques' dans toute la librairie elle-même, mais sont invisibles à l'application qui fait référence à cette librairie. On en reparlera peut être...

L'utilisation d'un objet est différente de celle des variables et procédures standard :
- tu dois d'abord créer une variable objet, du type de ta classe.
1- Déclaration de la variable :
Code :
Public ThisApp As clApplication
suivi de 2- Création de l'objet, qui est une instance (=une copie en mémoire) de la classe :
Code :
Set ThisApp = New clApplication
L'utilisation, la modification d'une propriété ou d'une méthode se fait toujours en passant par le nom de la variable objet, suivi d'un point et de la propriété ou de la méthode.
Code :
1
2
MsgBox ThisApp.Title
ThisApp.Debugging = True
Les utilisations multiples peuvent être imbriqués dans un With... End With
Code :
1
2
3
4
With ThisApp
    MsgBox .Title
    .Debugging = True
End With
- les classes ont en plus 2 "évènements" : Initialize et Terminate, qui permettent de donner des valeurs initiales aux propriétés (Voir clApplication > Class_Initialize qui crée le titre de l'application), ou de les fermer proprement lors de la destruction de l'objet.
- Attention : un objet peut en cacher un autre, ce qui fait toute la puissance des objets. Voir notre clApplication qui contient un objet Log As clLog.
Code :
ThisApp.Log.Name = "SuiviAffaires_MiseAJourBDD"
Voir surtout, dans l'aide d'Access > Microsoft DAO 3.60 > Références des objets DAO > Modèle d'objet DAO pour espace de travail Microsoft Jet. Tu y trouveras un exemple complexe qui contient des objets et collections très familiers : Databases > recordsets > fields...

Enfin, les objets peuvent être contenus dans des collections (voir exemple DAO ci-dessus, ou collection Forms() qui contient des objets Form...).
Si nous avions besoin de plusieurs journaux dans notre moteur de mise à jour, nous aurions pu doter notre classe clApplication d'une collection de journaux, utilisables comme :
Code :
1
2
ThisApp.Logs.Item(0).Name = "Journal d'erreurs - SuiviAffaires"
ThisApp.Logs.Item(1).Name = "Journal de mise à jour de la base V1"
ou bien
Code :
ThisApp.Logs.Item("Journal d'erreurs - SuiviAffaires").Append Err.description
À chaque fois que tu tapes un point dans le code (Docmd.Maximize), tu utilises une propriété ou une méthode d'un objet. La liste des propriétés et méthodes est affichée par la fonction intellisense de l'éditeur de code...

Citation:
Envoyé par Serge57
Lors de la distribution de l’application, il faudra joindre la librairie ???
Oui, et ça ne pose aucun problème si les 2 "bases .mdb" (l'application qui utilise la librairie + la librairie elle-même) sont copiées dans un seul répertoire : dès le premier lancement de l'application, Access rétablit la liaison (référence) avec la librairie
Lors de modifications ultérieures de ton application, tu n'as plus besoin de distribuer la librairie (sauf si elle a été modifée aussi, oeuf corse).

Voilà, si tout ça est bien clair (et y a intérêt ), je te propose de terminer notre application de mise à jour des bases en
1- supprimant d'abord tout code d'erreur, sauf code de traitement d'une erreur spécifique, bien sûr. Ceci afin de repartir sur une base simple et claire.
2- d'extraire vers une librairie ce que nous pourrons réutiliser ailleurs. Par exemple, nos classes clApplication et clLog, pour que l'application principale soit elle aussi dotée d'un journal d'erreurs.
3- de choisir où nous allons mettre du code de contrôle d'erreur, et utiliser le générateur de mzTools pour 'blinder' nos 2 applications contre toute erreur imprévue.

Donc, sauf questions ici que nous continuerons en //, prochain exercice :
- reprendre la suite du cours 05, en supprimant tout code d'erreur non indispensable.
Papy Turbo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/05/2007, 17h50   #19
Membre du Club
 
Inscription : mai 2006
Messages : 79
Détails du profil
Informations forums :
Inscription : mai 2006
Messages : 79
Points : 57
Points : 57
Citation:
Envoyé par Papy Turbo
Voilà, si tout ça est bien clair (et y a intérêt ), je te propose de terminer notre application de mise à jour des bases...
Vache, vache…. Je pensais avoir tout compris mais je rame un peu …


Citation:
1- supprimant d'abord tout code d'erreur, sauf code de traitement d'une erreur spécifique, bien sûr. Ceci afin de repartir sur une base simple et claire.
Dans toutes les subroutines et fonctions du modules ClApplication et SpecificTransferRoutines. (mais il faut les pièger dans les sub appelantes !! )


Citation:
2- d'extraire vers une librairie ce que nous pourrons réutiliser ailleurs. Par exemple, nos classes clApplication et clLog, pour que l'application principale soit elle aussi dotée d'un journal d'erreurs.
J’ai essayé, Mais code erreur dans variable « Public ThisApp As clApplication » variable non référence !! Pas tout compris vu que la librairie est raccrochée à l’application.

Citation:
3- de choisir où nous allons mettre du code de contrôle d'erreur, et utiliser le générateur de mzTools pour 'blinder' nos 2 applications contre toute erreur imprévue.
N’étant pas un VRAI développeur, je ne sais pas l’utiliser.

Nota : beaucoup de retard dans mes réponses,parce que ça ce complique(je m’accroche), que je ne comprend pas tout du premier coups et que j’ai un métier qui me sature en ce moment. (semaine 23 et semaine 24 pas là, en déplacement)
Serge57 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/05/2007, 11h51   #20
Membre Expert
 
Avatar de Papy Turbo
 
Homme Etienne Pailleret
Développeur VBA
Inscription : mars 2004
Messages : 748
Détails du profil
Informations personnelles :
Nom : Homme Etienne Pailleret
Localisation : France, Hauts de Seine (Île de France)

Informations professionnelles :
Activité : Développeur VBA

Informations forums :
Inscription : mars 2004
Messages : 748
Points : 1 114
Points : 1 114
Bonjour, Serge,
je vois que l'enthousiasme et la bonne humeur sont toujours là .
Ça fait bien plaisir.
Et puis, tant qu'il fait beau, on a le moral au top, non ?
Citation:
Envoyé par Serge57
Vache, vache…. Je pensais avoir tout compris mais je rame un peu …
Je ne te cache pas que les exercices que tu t'offres ici (et que j'encourage vivement tous les lecteurs à faire, sauf si leur but est simplement de connaître quelques termes techniques pour briller en comité de coordination ?!? Hint : pour ça, Wikipedia, ça va plus vite) sont nettement d'ordre didactique, sans grand intérêt pratique pour notre application, dans l'immédiat : tu vas enlever tout code de traitement des erreurs non prévues, en conservant juste le traitement des erreurs spécifiques.
Plus tard, (étape 3.), nous remettrons notre traitement d'erreurs non prévues (là où il faut, et pas plus).

Le but est de bien distinguer les deux : dans la pratique, beaucoup mélangent allègrement le traitement des erreurs non prévues et celui des erreurs spécifiques, ce qui amène à des capharnaüms pas faciles à démêler ensuite...

Donc, étape 1 : juste produire une appli qui, en cas d'erreur non prévue, ouvre la boîte de dialogue d'Access : Erreur... choix -> Déboguer ? ou Fin ?
Citation:
Envoyé par Serge57
Dans toutes les subroutines et fonctions du modules ClApplication et SpecificTransferRoutines. (mais il faut les pièger dans les sub appelantes !! )
Chaque chose en son temps : on fera ça à l'étape 3, sur une base "propre".
Citation:
Envoyé par Serge57
J’ai essayé, Mais code erreur dans variable « Public ThisApp As clApplication » variable non référence !! Pas tout compris vu que la librairie est raccrochée à l’application.
Pige pas Tu as déjà démarré l'étape 2 et séparé la librairie du reste ?
C'est un peu prématuré, et je comprends que tu satures.
Encore une fois, Che va piano va sano, étape par étape.
Citation:
Envoyé par Serge57
N’étant pas un VRAI développeur, je ne sais pas l’utiliser.
1- un Pro, par définition, c'est quelqu'un qui gagne principalement sa vie en développant. D'accord, ce n'est pas ton cas, comme tant d'autres sous Access. Mais un VRAI, c'est quoi ?
2- avec les exercices que tu fais depuis quelques mois, j'ai le sentiment que tu vas, d'ici à l'année prochaine, nous pondre des applications qui seront beaucoup beaucoup plus "propres" (structure d'appels, contrôle d'erreur, commentaires...), mieux structurées (portée des variables, modules spécifiques/génériques, classes...), plus efficaces (optimisation, ergonomie, réutilisation de code...) que le plupart de celles, dites "professionnelles", sur lesquelles je tombe ici et là
Citation:
Envoyé par Serge57
Nota : beaucoup de retard dans mes réponses,parce que ça ce complique(je m’accroche), que je ne comprend pas tout du premier coups et que j’ai un métier qui me sature en ce moment. (semaine 23 et semaine 24 pas là, en déplacement)
Ce sont les aléas de ces cours en ligne. J'en suis exactement au même point (je serai à Caen, la semaine 23 - mais rien à voir avec les 60 ans de D-Day), donc, tout va bien.

Je préfère, au contraire, qu'on s'offre le luxe de prendre le temps (revoir la récré sur débogage et méthode de test, plus haut), pour bien éclaircir les quelques principes de base (y en a pas tellement).
Et rien ne vaut la pratique : exercices, exercices, exercices...

Donc, dès que tu as fait ton nettoyage (étape 1), avec quelques tests pour que ça compile et que ça marche quand même, tu le mets en pièce jointe et on revoit ça.
Papy Turbo est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 07h53.


 
 
 
 
Partenaires

Hébergement Web