Userform changements dans bdd
Bonsoir,
Je reviens une fois de plus sur ce forum à la recherche d'aide sur un sujet qui me préoccupe.
J'ai une BDD que je renseigne via un userform, j'ai par ailleurs construis un second userform pour apporter des modification à cette BDD.
Le problème c'est que en remplissant les trois ComboBox pour me situer sur une ligne, cela reste sur la première ligne. Je n'arrive pas à trouver le bon code.
Pour plus de visibilité, mon fichier en pièce jointe.
J’espère trouver les bonnes réponses comme d'habitude sur ce forum.
Merci.
Bonsoir,
Juste une réflexion méthodologique.
Tu dis que tu as un Userform "pour renseigner ta BDD". C'est à dire qui te permet d'ajouter un nouvel enregistrement dans ta base ?
Si c'est le cas, Je ne vois pas l'utilité d'un Userform destiné aux modification !
On utilise de façon générale le même dispositif pour ajouter ou modifier, la procédure est la même, elle ne diffère que par la ligne d'affectation : nouvelle ligne pour un ajout, ligne déjà existante pour une modif.
Cordialement.
Bonsoir,
Merci pour l'attention que vous avez accordé à mon sujet .
C'est vrai que j'utilise un userform pour alimenter la BDD mais pour la modifier je trouve des difficultés car, d'abord je ne veux modifier qu'une partie des données, et pour me positionner sur une ligne je passe par le remplissage en cascade de trois ComboBox: classe, Nom et Prénom, chose qui ne se fait pas lors du remplissage de la BDD. Ce sont des événements qui m'ont rendu la tâche difficile.
J'espère que je trouverai une aide ou une orientation pour l'aboutissement de cette requête.
Merci
Je ne te suis pas, mais c'est ton appli... !
La recherche justifie une Combo avec une liste issue de la concaténation des noms et prénoms, et la ligne sera fournie par le ListIndex +1, pour peu qu'on utilise une plage nommée. En cas d'ajout on ne fait pas de recherche, ce qui distingue les 2 cas, et la ligne est fournie par le nb de lignes de la plage nommée +1. Economie de contrôles et de code (évidemment avec une organisation cohérente de la base pour simplifier...)
Userform simple, sans élément inutile, code réduit à ce qui est nécessaire et optimisé, dispositif qui fonctionne de façon fiable et rapide, c'est toujours ce qui me paraît le mieux.
Bonsoir,
J'ai essayé de comprendre vos directives, j'ai creusé au niveau des codes des deux userform, mais étant débutant je n'y arrive pas.
J'ai mis en pièce jointe le fichier avec l'userform que j'utilise pour alimenter la BDD les codes peuvent vous sembler très basiques mais ça marche bien. Mon problème est avec le second userform car la sélection de la ligne se fait par trois combobox.
Si vous pouvez intervenir directement sur le fichier pour une correction, je vous serais très reconnaissant.
Merci
Bonjour,
Voilà une illustration... Tu ne retrouveras quasiment rien (en dehors des Msg que j'ai conservé et d'un Unload Me) de ton code antérieur.
J'espère que cela pourra t'ouvrir des horizons...
Sur la forme (car travailler sur du code implique de pouvoir le lire et s'y retrouver à tous moments) et partiellement sur le fond, quelque remarques générales :
- Indentation : elle était en partie respectée dans ton code, en tout cas ce n'était catastophique comme ce qu'on voit trop souvent, mais étant plutôt maniaque en la matière, cela ne pouvait me satisfaire pleinement...
(- Commentaires : je n'en mets pas car ça me gêne et ne m'apprend rien, mais si tu en as besoin je pourrais t'en mettre pour te repérer (du moment que je n'ai plus à travailler sur le code ils ne me gênent plus... !
- Le placement des procédures évènementielles : dans un module de Userform (comme dans un module de feuille) la quasi totalité des procédures sont des proc. d'évènements, il est préférable de laisser VBA les positionner, on les retrouvera plus rapidement...
Quant aux proc. ajoutées (hors évènements), les placer dans la zone (General) du module, soit en tête après les déclarations s'il y en a.
- Les déclarations de variables dans les procédures : toujours en tête, avant tout code exécutable, on sera toujours en mesure de les contrôler...
- Renommage des contrôles : on gagne toujours à renommer les contrôles, notamment de façon à pouvoir les utiliser dans des boucles...
- Je ne connais pas de bon code VBA sans utilisation de boucles, de tableaux et de blocs With... End With, entre autres mais ces éléments sont prioritaires pour à la fois alléger l'écriture et renforcer l'efficacité et la rapidité.
On évite notamment des énumérations interminables et fastidieuses...
A l'inverse, jamais de Select (je n'en ai vu qu'un mais c'est toujours un de trop) sauf pour affichage à l'écran d'un élément qui ne s'y trouve pas (et s'arrêter là !), et qualification des expressions (ça c'était plutôt bien respecté).
Venons-en à l'illustration : Je n'ai pas touché à l'organisation de ta base (ce qui constitue une contrainte du fait que tu sers une ligne aux deux extrémités lors d'un ajout ou d'une modif.).
Par contre, suppression des noms (de colonnes de la BDD), au profit d'un seul (ajouté) : Base (sur la colonne A). Ce nom est suffisant pour les besoins de prélèvement et d'affectation. Son utilisation a pour effet que l'on n'a plus besoin de se référer à la feuille, la référence à cette plage pourvoit aux besoins.
Suppression du Userform Modification (ça je n'ai pas besoin de le dire, c'était l'objet du débat !
Ces éléments ne modifient guère l'allure du Userform, tu n'auras donc pas de difficulté à t'y retrouver de ce point de vue. Mais tous les contrôles utilisés sont renommés (on renomme les contrôles qu'on utilise pour les identifier et les manipuler plus facilement dans le code [NB- en ce qui me concerne je renomme aussi pour raccourcir les noms, pas pour les allonger...]).
Compromis lié à l'organisation de la base, les TextBox (et la Combo Classe) sont renommés en 2 séries : une préfixée ctlInf suivi d'un numéro d'ordre 1 à 9, accueillant les valeurs des colonnes 2 à 10 ; l'autre préfixée tbInf suivi d'un numéro d'ordre 1 à 11, accueillant les valeurs des colonnes 83 à 93. Pour les autres voir les noms dans le fichier.
En ce qui concerne la Combo Classe (ctlInf3), la plage CHOIX_CLASSE est affectée à sa propriété RowSource (par défaut, ce qui supprime l'opération faite en Initialize).
La proc. Initialize disparaît donc. Toutefois, il y a lieu d'initialiser la Combo de Recherche (cbxRech). Au lieu de placer cette initialisation en Initialize, on la place en Activate (contrairement à Initialize qui ne s'exécute qu'une fois au chargement du Userform, Activate s'exécute à chaque affichage). Ce qui permet d'éviter l'inélégant Unload suivi de Show après chaque opération, qui n'avait pour but que de relancer Initialize. Hide donnera le même résultat...
La mise en place de la liste de la Combo s'opère par constitution d'un tableau concaténant les noms et prénoms, affecté à la propriété List.
Outre la constitution de la liste, Activate fait appel à deux procédures auxiliaires emboîtées : InitUsf et InitCtl (la seconde étant lancée par la première. InitCtl efface les TextBox et réinitialise la variable module lgn à 0 (et peut intervenir indépendamment lors d'un effacement de valeur dans la Combo recherche) ; InitUsf effectue en plus le passage en mode ajout (Caption du Userform, masquage de la Combo et de la TextBox date départ...), et peut être lancée indépendamment par le bouton Annuler ou par le décachage de la CheckBox recherche.
A l'ouverture, le Userform est en mode Ajout. Si on coche la CheckBox, cela modifie l'intitulé du Userform et fait apparaître les éléments masqués. A la sélection d'un nom dans la Combo, la valeur du ListIndex augmentée de 1 (ce qui correspond au numéro de ligne dans la plage Base) est affectée à une variable module lgn (qui le conserve), et les données sont prélevées sur la ligne pour alimenter les différents contrôles.
La validation est commune au mode Ajout ou Modification. Si lgn est à 0, on est en mode Ajout, et on lui affecte le nb de lignes de Base +1 (ligne affectation). Si lgn est >0 , c'est la ligne prélevée, sur laquelle on va réaffecter...
Pour ce qui est du déroulement de la procédure, je te laisse étudier les diverses façons de réaliser des boucles, notamment lors de vérifications, et le procédé d'affectation passant par la constitution de tableaux. Tout cela aboutit et réduire de façon conséquente le volume de code...
J'ai intégré le numéro (qui ne figurait nulle part dans ton code) en affectant le numéro de ligne (auquel il correspond), mais cela laisse une lacune sur le statut de ce numéro. S'il s'agit d'un simple numéro d'ordre, il devrait être mis automatiquement par formule...
Ma proc. est probablement inadaptée sur ce point, ou incomplète. En l'absence de procédure de suppression, rien ne pouvait clarifier ce point... A toi de t'y pencher.
Cordialement.
Bonjour MFerrand,
Désolé pour le retard de ma réponse, j'ai eu une forte grippe.
Merci pour vos explications qui sont très bien structurées même si j'ai eu du mal à comprendre certaines d'entre elles à cause de mon niveau débutant en vba.
Par ailleurs j'ai eu le plaisir de tester les solutions sur le fichier directement:
L'idée d'un seul userform est très pratique surtout pour une recherche par nom et prénom en même temps c'est même excellent.
Néanmoins lorsque je valide sans renseigner certains champs obligatoires la couleur des labels change vers le rouge mais ne revient pas au noir après correction ce qui peut induire l'utilisateur en erreur surtout quand il s'agit de plusieurs corrections.
j'ai eu des bugs avec les codes de ce fichier lorsque je rentre des valeurs incorrectes notamment lorsqu'il s'agit des dates cela bloque sur certaines lignes:
Me.Controls(ct).ForeColor = vbRed
ou bien:
Me.Controls(ct(i + 2)).ForeColor = vbRed
il en de même lors de la recherche quand je donne un format de date erroné cela bloque.
A première vue ce la format date des trois textbox qui font bloquer les codes.
J’espère qu'il y a une solution.
Merci
Bonsoir,
Tu n'es pas obligé de citer à chaque fois ! Tu peux répondre sans citer le post auquel tu réponds ! Je sais ce que j'ai écrit et cela figure pas loin...
L'erreur intervenant sur la date d'inscription (en cas de date erronée) provient d'une erreur dans le nom de l'étiquette (lnC9 au lieu de lbC9). Faute de frappe, désolé.
Quant à la couleur restant au rouge, c'est que j'avais omis l'astérisque pour les identifier à partir de la partie générique du nom (lbC* et lbT*). Désolé encore.
C'est rectifié. J'en ai profité pour introduire le repassage en noir de la police des étiquettes sur la commande Annuler, au cas où tu annulerais alors que l'une ou l'autre serait en rouge.
Cordialement.
Bonjour MFerrand,
Merci beaucoup pour le temps et les efforts que vous avez déployé pour la réalisation de ma demande.
J'ai pu tester le formulaire avec pratiquement toutes les possibilités. cela marche bien excepté une seule situation où je bascule sur le mode recherche et je remplie la textbox date de départ de maniéré erronée, le programme se bloque sur la ligne:
ct = CDate(tbDp.Value) Else
Quelle est la solution?
J’espère que ce n'est pas compliqué.
Bonjour MFerrand,
Cela fait deux jour que j'essaie de trouver la cause du blocage des code lorsque je bascule sur le mode recherche et je donne une date de départ erronés (Ci-joint capture écran de l'exemple de remplissage)
La ligne où cela bloque:
J’espère que vous pouvez faire quelque chose( vraiment je suis si près de la finalisation du projet)
Merci d'avance
Bonsoir,
C'était ta question précédente... Je n'ai effectivement pas inclus la Date de départ dans les tests de vérification que tu avais mis en place (j'ai maintenu ceux que tu avais mis, je n'en ai pas enlevé, je n'en ai pas ajouté non plus).
Rien ne t'oblige à saisir une date erronée !
Ceci étant, CDate provoquera une erreur si tu veux convertir en date une expression non reconnaissable comme telle... Tu peux donc l'inclure dans les vérifications ou simplement éliminer l'erreur d'exécution... C'est un aspect tout à fait mineur de la question : laquelle portait sur l'utilisation d'un même dispositif pour Ajout et Modification.
Il y a d'autres questions qui devraient mériter une priorité par rapport à cela : les questions que j'ai soulevées du rôle du numéro et de l'absence de procédure de suppression (dont les incidences pourraient être plus importantes).
Et en matière de vérification, il y a peut-être aussi d'autres éléments susceptibles d'être vérifiés et éventuellement donner lieu à des rectifications automatiques.
Cordialement.
Bonjour MFerrand,
Merci pour vos explications qui me sont toujours utiles.
Concernant la procédure de suppression elle ne fait pas partie de mes projets et je ne compte pas avoir recours à la suppression( ni ligne ni colonne)
Par ailleurs le problème de la tbDp reste préoccupant (surtout face à un utilisateur non averti) car lorsque je l'inclus dans les vérification (quand tbDp visible) elle devient obligatoire au remplissage.
Ce que je cherche c'est: que la vérification de la date ne se fasses que lorsque la tbDp soit visible et remplie, sinon si elle est vide il faut la laisser vide sans aucune vérification
Vraiment je galère sur ce point et j'y arrive pas.
car lorsque je l'inclus dans les vérification (quand tbDp visible) elle devient obligatoire au remplissage.
Je regarde durant le weekend... elle ne doit pas être obligatoire, ce pourquoi la vérification de la date ne doit intervenir que si une valeur est saisie...
Cordialement.
Merci beaucoup MFerrand,
En attente de votre solution
Bon weekend
ReBonjour MFerrand,
Que pensez-vous de
Private Sub tbDp_AfterUpdate()
If Not IsDate(tbDp) Then
lbDp.ForeColor = RGB(255, 0, 0)
MsgBox "Il faut saisir une date valide:(jj/mm/aaaa)"
tbDp = ""
tbDp.SetFocus
Exit Sub
End If
End Sub
J'ai fais quelques tests ça marche bien mais j'ai peut que cela interfère avec d'autres codes.
Déjà sur le mode recherche quand je change la comboBox nom-prénom la tbDp ne se met pas à jour.
Peut-être une piste à améliorer.
En attente de vos réponses.
Bonsoir,
On peut effectivement traiter cette date à part, mais peut-être plus sûr ainsi:
Private Sub tbDp_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
lbDp.ForeColor = vbBlack
If tbDp.Value <> "" Then
If Not IsDate(tbDp.Value) Then
MsgBox "Il faut saisir une date valide : (jj/mm/aaaa)"
lbDp.ForeColor = vbRed
tbDp.Value = ""
Cancel = True
End If
End If
End SubCordialement.
Bonsoir MFerrand,
Je viens de tester les nouvelles modifications, ça marche bien plus de bug.( Pour le moment)
Par ailleurs pour que la tbDp soit mise à jour lors du changement de la cbxRech j'ai fais un petit changement dans le code
tbDp.Value = .Cells(lgn, 66).Text
au lieu de
If .Cells(lgn, 66) <> "" Then tbDp.Value = .Cells(lgn, 66).Text
J’espère que cela va mieux marcher cette fois.
Je vous tiens au courant.
Merci pour le temps et les efforts que vous avez consacré à mes demandes.
bonsoir Youness1972, MFerrand et le forum
j'ai juste apporter une modification au textbox des numéros de téléphone pour les forcer à 10 chiffres avec les écarts
tu rajoutes ces lignes de code et ca devrai fonctionner
Private Sub tbInf11_Exit(ByVal Cancel As MSForms.ReturnBoolean)
tbInf11.Value = Format(tbInf11.Value, "00 00 00 00 00")
End Sub
Private Sub tbInf11_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
tbInf11.MaxLength = 10
End Sub
Private Sub tbInf7_Exit(ByVal Cancel As MSForms.ReturnBoolean)
tbInf7.Value = Format(tbInf7.Value, "00 00 00 00 00")
End Sub
Private Sub tbInf7_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
tbInf7.MaxLength = 10
End SubBonjour Mferand, le forum,
Je reviens sur le forum pour donner des nouvelles de l'avancement du projet.
J'ai finalement pu tester a plusieurs reprise le formulaire, ça marche très bien que ce soit sur le coté Remplissage de la BDD ou recherche et modification. Pour finaliser mon projet j'ai vidé la BDD des données tests pour commencer à exploiter le formulaire avec des données réelles. Malheureusement il y a eu un bug sur Usrform activate sur la ligne ReDim npR(1 To .Rows.Count)
J'ai essayer de comprendre d'ou venait le problème; c'est la première ligne de la BDD qui devrait être non vide pour contourner ce bug.
Je l'ai remplie directement sur le tableau BDD avec des 0 et tout est rentré dans l'ordre même si c'est un peu gênant de retrouver cette ligne de 0 dans les comboBox.
Je me demande si on pourrait contourner ce problème en agissant directement sur le code.
Merci
Une fois qu'elle a joué son rôle de démarrage, tu supprimes cette ligne qui n'a plus d'utilité...