Pour le tableau de bord indépendant de ton classeur de données, tu peux sans souci utiliser power query qui, depuis XL2010, permet de récupérer les données de différents classeurs pour les intégrer dans un classeur d'analyse ou de tableau de bord.
Tu comprends mieux maintenait pourquoi j'insiste tant sur l'utilisation d'un tableau structuré puisque PowerPoint Quercy s'appuie préférentiellement sur ce type de tableaux.
"Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
---------------
Mes billets de blog sur DVP
Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
Pensez à utiliser les tableaux structurés. Ils vous simplifieront la vie, tant en Excel qu'en VBA ==> mon tuto
Le VBA ne palliera jamais une mauvaise conception de classeur ou un manque de connaissances des outils natifs d'Excel...
Ce ne sont pas des bonnes pratiques parce que ce sont les miennes, ce sont les miennes parce que ce sont des bonnes pratiques
VBA pour Excel? Pensez D'ABORD en EXCEL avant de penser en VBA...
---------------
J'ai regardé ton fichier.
Dans tes tableaux, il n'est pas nécessaire d'avoir des lignes vides dans le bas du tableau. Ces lignes vont perturber le code et t'obliger à des acrobaties pour savoir sur quelle ligne placer une nouvelle donnée. Le ListObject (tableau structuré en VBA) permet d'ajouter une ligne au tableau avec ListObject.ListRows.Add() qui renvoie le ListRow de la nouvelle ligne créée (par défaut en bas de tableau, mais on peut définir l'endroit de l'insertion). Cette méthode est intéressante car elle fonctionne que ton tableau possède une ligne de total ou pas. Ca t'évite de devoir gérer tout cela toi-même.
La procédure Private Sub btnAjout_Click() est ingérable.
D'abord, une procédure évènementielle ne devrait rien faire d'autre que d'appeler des procédures. Autrement dit, on ne met jamais du code applicatif (du code qui "fait quelque chose") dans un évènement, quel qu'il soit. On délègue le traitement à une procédure qui reçoit les arguments nécessaires et qui travaille avec.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
39
40
41
42
43
44 Private Sub btnAjout_Click() Sheets("BDD en cours").Activate Range("A1").Select Selection.End(xlDown).Select 'On se positionne sur la ligne nom vide Selection.Offset(1, 0).Select ' on se decale d'une ligne vers le bas ActiveCell = txtID.Value ActiveCell.Offset(0, 1).Value = txtID ActiveCell.Offset(0, 2).Value = cboAnnee ActiveCell.Offset(0, 3).Value = cboFonction ActiveCell.Offset(0, 4).Value = cboStatut ActiveCell.Offset(0, 5).Value = txtDenomination ActiveCell.Offset(0, 6).Value = cboCivilite ActiveCell.Offset(0, 7).Value = cboSuivi ActiveCell.Offset(0, 8).Value = txtNom ActiveCell.Offset(0, 9).Value = txtPrenom ActiveCell.Offset(0, 10).Value = TxtCode ActiveCell.Offset(0, 11).Value = txtDoublons ActiveCell.Offset(0, 12).Value = txtNum_voie ActiveCell.Offset(0, 13).Value = txtAdresse ActiveCell.Offset(0, 14).Value = txtLocalisation ActiveCell.Offset(0, 15).Value = txtCode_postal ActiveCell.Offset(0, 16).Value = txtVille ActiveCell.Offset(0, 17).Value = txtDepartement ActiveCell.Offset(0, 18).Value = txtINSEE ActiveCell.Offset(0, 19).Value = txtSurf_foret ActiveCell.Offset(0, 20).Value = txtClasse_tarif ActiveCell.Offset(0, 21).Value = txtCot_soutien ActiveCell.Offset(0, 22).Value = txtCot_GSB ActiveCell.Offset(0, 23).Value = txtCot_UFP38 ActiveCell.Offset(0, 24).Value = txtCot_Revue ActiveCell.Offset(0, 25).Value = txtCot_RC ActiveCell.Offset(0, 26).Value = txtTot_cot ActiveCell.Offset(0, 27).Value = txtRegle ActiveCell.Offset(0, 28).Value = txtEcart ActiveCell.Offset(0, 29).Value = txtDate_regle ActiveCell.Offset(0, 30).Value = txtFixe ActiveCell.Offset(0, 31).Value = txtMobile ActiveCell.Offset(0, 32).Value = txtMail ActiveCell.Offset(0, 33).Value = txtMail2 ActiveCell.Offset(0, 34).Value = txtRef_PEFC ActiveCell.Offset(0, 35).Value = txtNum_prece ActiveCell.Offset(0, 36).Value = txtComment MsgBox " Enregistrement effectué", vbOKOnly + vbInformation + vbInformation End Sub
Il n'est nullement nécessaire d'activer une cellule pour travailler avec. Ca ralentit le processus et ça oblige la proc à se positionner physiquement sur cette cellule, modifiant l'environnement Excel. Le Selection.End(xlDown) est piégeant et, comme déjà dit, c'est du code obsolète qui est ingérable et dangereux, car il considère que tu dois toujours avoir des données en A. De plus, tout ton code est verrouillé sur le fait que ta table commence en A1. Un seul décalage en ligne ou en colonne plantera complètement ton code. Utiliser les tableaux structurés en VBA va faire sauter toutes ces restrictions et limiter considérablement le risque d'erreur.
Idéalement, une procédure qui envoie des données dans une table structurée ne devrait pas se trouver dans un userform, mais dans un module standard. De plus, outre le fait qu'il faut utiliser le code manipulant le tableau structuré, lorsqu'il y a 36 champs à transférer et dans la mesure où tu ne transfères que du texte, il est de loin préférable de prévoir un tableau Excel comprenant deux colonnes (trois si différents types de données sont transférés), et de travailler en boucle sur le tableau. Ici, ta procédure est beaucoup trop liée à l'organisation et à l'ordre des colonnes de la feuille BDD. D'ailleurs, si on regarde la BDD et le code fourni plus haut, on voit que tu transfères deux fois l'ID, une fois dans la colonne 1, une fois dans la colonne 2 du UFP38. Pas simple de s'y retrouver, et je n'ai pas vu de txtUFP38. Tu n'as pas de colonne Mail2 dans la BDD mais tu transfère txtMail22 en colonne 33... Aie aie aie. Evidemment, quand on te conseille de programmer ainsi, ça ne peut que planter, à un moment donné.
On pourrait déjà rendre le code un peu plus lisible et plus sûr en utilisant les références structurées et les noms des colonnes de la table comme je l'ai montré dans un code que je t'ai déjà donné, mais perso, je préfère travailler en boucle. Voilà comment je coderais le transfert des données du usf vers le tableau structuré, en m'appuyant sur la table de mappage dont j'ai parlé. Cette fonction est placée dans un module standard et renvoie 0 (tout est ok) ou le numéro de l'erreur rencontrée. Tu remarques qu'elle n'affiche aucun message à l'utilisateur, ce n'est pas son rôle.
Cette procédure est appelée par le userform lors du clic sur le bouton Ajout, et c'est l'évènement Ajout qui a la charge de renseigner l'utilisateur sur le résultat de l'ajout.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 Function UsfToTable() Dim Target As Range Dim Map As Range Dim i As Long Dim Index On Error GoTo Catch ' Recherche de la ligne dans la BD Index = Application.Match(frmsaisie.txtID.Value * 1, Range("t_BddEnCours[ID]"), 0) If IsError(Index) Then Set Target = Range("t_BddEnCours").ListObject.ListRows.Add().Range Else Set Target = Range("t_BddEnCours").ListObject.ListRows(Index).Range End If For i = 1 To Range("t_MapBdd").Rows.Count Set Map = Range("t_MapBdd")(i, 1).Resize(1, 2) Target(Target.ListObject.ListColumns(Map(1).Value).Index).Value = frmsaisie.Controls(Map(2).Value).Value Next i Catch: UsfToTable = Err.Number End Function
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 Private Sub btnAjout_Click() Dim Result As Long Result = UsfToTable() If Result = 0 Then MsgBox "Tout est ok" Else MsgBox "L'erreur suivante est survenue:" & vbLf & Result & vbLf & Error(Result) End If End Sub
Plus loin, on tombe sur cette procédure, toujours dans le userform
On y constate du hard coding (valeurs "métier" codées en dur en VBA). Là aussi, il faudrait corriger la table dans la feuille "listes déroulantes", la transformer en tableau structuré et y rechercher la ligne sur base de surface_foret_num, plutôt que la mettre en dur dans le code. Imagine un seul instant que tu tries les données de cette "table"... Ca va être rock 'n roll dans ton code, plus rien ne sera correct.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
39
40
41
42
43
44 Sub maj_classe_tarif_txt_et_cotisations() Dim surface_foret_num As Long Dim num_ligne_tablo_cotisation As Long 'RAZ champs formulaire impactés frmsaisie.txtClasse_tarif = "" frmsaisie.txtCot_soutien = "" frmsaisie.txtCot_GSB = "" frmsaisie.txtCot_UFP38 = "" frmsaisie.txtCot_Revue = "" frmsaisie.txtCot_RC = "" frmsaisie.txtTot_cot = "" 'tester le cas sout If LCase(frmsaisie.cboFonction) = "sout" Then frmsaisie.txtClasse_tarif = "Sout" 'maj la classe tarif num_ligne_tablo_cotisation = 17 'retenir le numéro de ligne Excel de la classe tarif dans la feuille "listes déroulantes" ElseIf IsNumeric(frmsaisie.txtSurf_foret) Then 'vérifier que la surface forêt est bien un nombre surface_foret_num = frmsaisie.txtSurf_foret * 1 'passer en numérique la valeur de frmsaisie.txtSurf_foret (par défaut c'est du texte) sinon tu ne peux pas comparer avec un chiffre 'tester les limites de surface If surface_foret_num > 5000000 Then frmsaisie.txtClasse_tarif = "+500" 'maj la classe tarif num_ligne_tablo_cotisation = 16 'retenir le numéro de ligne Excel de la classe tarif dans la feuille "listes déroulantes" ElseIf surface_foret_num > 4000000 Then frmsaisie.txtClasse_tarif = 500 num_ligne_tablo_cotisation = 15 ElseIf surface_foret_num > 3000000 Then frmsaisie.txtClasse_tarif = 400 num_ligne_tablo_cotisation = 14 ElseIf surface_foret_num > 2000000 Then frmsaisie.txtClasse_tarif = 300 num_ligne_tablo_cotisation = 13
Evidemment, les changements que je propose vont maintenant sembler disproportionnés et la tâche te paraître titanesque!. Si, dès le départ, on t'avait renseigné les bonnes pratiques, tu aurais de suite bien codé sur base d'une conception de classeur solide et les adaptations à y apporter seraient mineures.
Au vu de l'organisation de tes données (parfois en tableaux structurés, parfois en plages classiques) et surtout du code généré, je ne peux que te conseiller de faire table rase, au moins du code VBA qui accumule les mauvaises pratiques, et de recoder tout cela sur base des bonnes pratiques. C'est une petite journée de travail mais qui va simplifier la maintenance et l'évolution de ton code. Mais perso, je ne me vois pas venir mettre l'emplâtre sur la jambe de bois. Moi, en tout cas, en l'état, je ne peux pas mettre les mains là-dedans. Ca ne rendrait pas service et je donnerais une image de moi bien peu professionnelle.
"Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
---------------
Mes billets de blog sur DVP
Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
Pensez à utiliser les tableaux structurés. Ils vous simplifieront la vie, tant en Excel qu'en VBA ==> mon tuto
Le VBA ne palliera jamais une mauvaise conception de classeur ou un manque de connaissances des outils natifs d'Excel...
Ce ne sont pas des bonnes pratiques parce que ce sont les miennes, ce sont les miennes parce que ce sont des bonnes pratiques
VBA pour Excel? Pensez D'ABORD en EXCEL avant de penser en VBA...
---------------
Bonsoir
J'ai appliqué tes modifications sur la fonction Ajout et ça marche merci
Ajout j'ai réalisé d'après un tuto de Learnacces je l'es ai écrites.
Quand aux autres fonctions j'ai transposé des fonctions d'Alex, alors ces choix me dépasse et je ne voudrais pas qu'elles viennent en contradiction avec celles d'Alex.
Et je vous laisse débattre ensemble
Merci pour ta participation.
Bonjour,
Je l'ai dit dès le début dans l'une de mes premières réponses; "c'est une des méthodes. Chaque développeur a ses habitudes" et je comprends tout à fait que des tableaux structurés peuvent être préférables avec le code qui va avec.
Le fichier reçu de Fergut a déjà du code, les colonnes des feuilles, certaines feuilles sans tableau et d'autres avec, les formulaires enregistrés. J'ai complété quelques petites parties. Le restant c'est lui seul avec ses recherches Internet et je préfère qu'il ait un code qu'il a créé et qu'il comprenne plutôt que de lui dire de tout recommencer et de lui demander d'utiliser du code tableau.
Je suis d'accord que le code qui était présent est facilement corrigible car pas optimisé (activate, activecell, offset, ...) mais Fergut arrivait quand même a ce qu'il voulait donc même si c'est pas le top et même si ce n'est pas du code utilisant les fonctionnalités tableaux je ne vais pas lui dire de tout recommencer pour utiliser les fonctionnalités tableaux.
De mon côté je n'ai pas non plus utilisé les fonctionnalités tableaux dans le code ajouté, et même si vous pour vous j'ai utilisé des "techniques obsolètes" car j'ai préféré pointer directement des références cellules et pas des noms de colonnes de tableaux. Je sais bien que cette méthode n'est pas l'extase des grands développeurs mais elle permet au moins de savoir cibler précisément une cellule ou une plage pour travailler dessus. Ce qui est plus "comestible" pour un débutant pour comprendre que de directement taper dans les évolutions de code optimisées de type tableau. Je sais bien aussi que j'ai mis un code avec une boucle qui parcoure les cellules de haut en bas pour rechercher le codeadherent alors que j'aurai pu utiliser match (ou encore les tableaux). Cela permet à Firgus de commencer à voir les boucles. Je sais bien que...
Je sais aussi que si l'utilisateur renomme une feuille le code plantera ..... tout comme il plantera en utilisant la méthode magique des tableaux si l'utilisateur change ou supprime un nom donné au tableau ou tout comme il plantera si l'utilisateur supprime une colonne du tableau. Donc quoi qu'il en soit avec ou sans tableau il y a risque de plantage suite manipulation utilisateur. Tout comme un renommage de feuille il faudra également modifier le code en cas de modification de noms ou de suppression de colonne. Je ne suis pas certain que l'utilisation de tableau "sécurisent le code". Modifier le nom d'un tableau ou d'une de ces colonnes et c'est pareil; il y aura plantage.
Je sais aussi que sheets représente une feuille de manière générale et que worksheet représente une feuille contenant des données à la différence d'une feuille contenant un graphique. Là pour le coup oui il aurait été plus propre d'utiliser worksheet. Mais cela permet de ne pas m'obliger à faire moi-même cette différenciation. Avec sheets Excel atteindra la feuille en question que ce soit une feuille de données ou non. Je n'ai par la suite pas forcément accès à ctrl+espace.
Je sais aussi que End(xlDown) ou Up n'est pas l'extase; il faut par exemple commencer par défiltrer la feuille et démasquer les lignes éventuellement masquer sinon seule sont prises en considération les lignes (ou colonnes) affichées. Il ne doit pas non plus y avoir de cellules vides.
Bref, je sais que chaque proposition de code aura ses faiblesses... tout comme l'utilisation de tableaux.
Par contre je ne suis pas d'accord quand vous dites "la première chose à faire est de remettre les données en tableau". On a tout à fait le droit de ne pas utiliser les tableaux. On peut tout à fait décider de ne pas utiliser l'utilisation de cette fonctionnalité qui oblige également à utiliser les plages nommées. Si je ne veux pas ou même ne peux pas par-ce que la feuille est protégée et que je ne peux pas la déprotéger. Je reste libre de ne pas transformer les plages en tableaux. C'est une préférence (ou une incapacité dans le cas d'une feuille protégée). Quitte à utiliser du code qui, pour vous, est obsolète.
Le code utilisant les fonctionnalités tableau ne fonctionnera que si l'utilisateur a créé des tableaux et s'il n'en a pas modifié les noms, ni les noms des plages nommées. Le code sans VBA tableau fonctionnera que l'utilisateur aie ou non créé des tableaux même si cela oblige à d'autres contraintes (renommage feuille par exemple).
Je ne dis pas que la méthode avec plages de cellules est meilleure et sans inconvénients mais je dis que les tableaux ne sont pas non plus une méthode magique absente de contraintes qui rend toutes autres méthodes "obsolète". Il y a des avantages et inconvénients dans les 2 cas. Plus ou moins peut-être mais "la première chose à faire est de remettre les données en tableau" non.
Concernant PQ je ne sais pas. Je n'utilise pas. Je connais le principe et j'ai déjà vu mais sans plus.
Ce que je sais aussi c'est que j'ai déjà eu un fichier de gestion de budget avec pleins d'onglets, de PQ, de tableaux de plusieurs dizaines de Mo (20 de mémoire) qui mettait un temps fou à s'ouvrir et à mettre à jour les requêtes PQ. La responsable budget à été bien contente de récupérer un fichier sans tableaux ni PQ de 1Mo avec formules qui s'ouvrait rapidement et dont les formules que j'avais implantées répondaient immédiatement.
Fergut, dans le cas présent, ou n'importe quel utilisateur utilisera du code qu'il comprend et évoluera ses compétences par la suite. Quitte à, au début et quelle que soit la durée de ce "début", commencer par du code que vous jugez "obsolète".
Maintenant je comprends aussi l'agacement que cela peut engendrer quand ensuite une personne plus expérimentée reprend le projet. Paris ne s'est pas fait en un jour même si on aurait pu mieux faire et plus vite dès le début.
Je pense qu'on doit apporter de l'aide en donnant du code compréhensible facilement par le demandeur selon ce qu'on pense de son niveau initial et pas forcément directement lui fournir un code plus poussé.
Mais oui tu as le droit de ne pas utiliser les tableaux. Ai-je obligé à utiliser des tableaux structurés sous peine de mort? On n'a plus que ce mot-là à la bouche maintenant "avoir le droit". Tu as le droit de préférer des mauvaises techniques, j'ai le droit de dire qu'elles sont mauvaises (à mon estime), d'expliquer pourquoi elles le sont et d'en conseiller des meilleures à la place. "Avoir le droit"... ^^.
Utilise des plages classiques si tu veux, personne ne te l'interdit. On a le droit d'utiliser les pratiques obsolètes si l'on veut. Je dis simplement que travailler avec les outils actuels et donc les tableaux structurés est une meilleure pratique dans la toute grande majorité des cas, et que "on a le droit" (le devoir, en tant que professionnel?) de se former aux nouvelles techniques. Tu as même le droit de dire qu'il vaut mieux utiliser des plages classiques plutôt que les tableaux structurés, mais viens défendre ta cause avec des arguments en béton dans ce cas, que je démolirai un par un (avoir connu UN classeur qui était lourd ou avoir une vague idée de ce qu'est la pédagogie ne sont pas des arguments en béton). J'ai pour ma part bien précisé que "certains cas très spécifiques et très rares justifient de se passer des tableaux structurés ..." et tu viens me sortir UN fichier très lourd (probablement mal conçu) que tu as pu alléger avec de belles formules sans que l'on ait pu analyser exactement à quoi étaient dus les problèmes de lenteur, et Patrice vient avec un cas qui de toutes façons plantera pour d'autres raisons et fera que, tel quel, on ne pourra pas utiliser toute la puissance des outils Excel. Ca ne tient pas la route, vos exemples. Je viens de voir passer sur le forum un beau tableau structuré avec un SOMME.SI.ENS qui reprenait toute la colonne B:B au lieu d'utiliser la référence structurée, alors je peux aussi venir avec des cas, si on veut jouer.
Pour les pseudo-arguments pédagogiques, j'ai plus de mal, par contre, car je pense que "on n'a pas le droit" d'enseigner des techniques obsolètes ou mauvaises (pour moi une technique obsolète est mauvaise) sous prétexte de pédagogie (sauf à des fins de comparaison, pour montrer en quoi elles sont obsolètes ou mauvaises). Je veux bien discuter pédagogie et didactique de l'informatique avec des profs et des formateurs (des vrais hein, qui ont des centaines d'heures de vol, pas des gens qui ont une fois expliqué comment "on fait une somme" en Excel ou des profs de math qu'on a parachuté "prof d'Excel"), mais je n'ai pas envie de perdre mon temps sur ce terrain avec des gens qui n'auront pas apporté la preuve de leur maîtrise en la matière.
"Plus les hommes seront éclairés, plus ils seront libres" (Voltaire)
---------------
Mes billets de blog sur DVP
Mes remarques et critiques sont purement techniques. Ne les prenez jamais pour des attaques personnelles...
Pensez à utiliser les tableaux structurés. Ils vous simplifieront la vie, tant en Excel qu'en VBA ==> mon tuto
Le VBA ne palliera jamais une mauvaise conception de classeur ou un manque de connaissances des outils natifs d'Excel...
Ce ne sont pas des bonnes pratiques parce que ce sont les miennes, ce sont les miennes parce que ce sont des bonnes pratiques
VBA pour Excel? Pensez D'ABORD en EXCEL avant de penser en VBA...
---------------
Bonjour
J’ai complété les codes du bouton « Reprendre la modif dans feuille » ça fonctionne merci
La fonction MAJ est la plus fréquente (95%), Ce que je souhaiterais, si possible :
Utiliser la zone verte du formulaire.
Mettre à jour : Renter un code adhèrent existant à mettre à jour.
Visualiser : Efface les données du formulaire existant, affiche tous les champs correspondant au code demandé, dans le formulaire,
possibilité de modifier tous les champs sauf ceux servant au calcul du code (c’est déjà le cas)
Peut être un bouton efface l'enregistrement sur la BDD en cours
MAJ valide la mise à jour sur BDD en cours.
Dans l'attente de votre réponse
Merci encore
https://fromsmash.com/LnNaIu3AkB-ct
Bonjour,
Le bouton "visualiser" rappelle sur le formulaire les données de ta feuille "BDD en cours" selon le code adhérent "TextCodeMaj". Tu n'as pas besoin de réinitialiser les champs puisque leur valeur sera directement remplacée.
Je n'ai pas compris ce que tu veux avec ton bouton "MAJ".
Tu veux modifier la feuille "BDD en cours" avec les valeurs du formulaire ? Tu as déjà le bouton "Reprendre la modif dans feuille" qui te fait ça.
Attention avec le bouton "supprimer". La ligne est supprimée mais quand tu gèreras les parcelles il faudra réattribuer ses parcelles avant de supprimer l'adhérent.
Partager