Filtrer les lignes afficher dans un userform

pmfontaine

XLDnaute Occasionnel
Bonjour, Je ne sais pas si mon titre est bien clair car j'ai eu beau chercher sur le Net avec ces mots clés et bien d'autres, mais je n'ai rien trouvé.
1 - J'aurais besoins de votre aide pour filtrer les résultats dans les TextBox en fonction des sélections faites dans des ComboBox ?
2 - Et t'il possible de lire les données de la feuille en restant sur une autre feuille ?

Je pense que la lecture du fichier joint sera beaucoup plus explicite que mon texte.
Merci d'avance pour votre aide
Patrick
 

Pièces jointes

  • FiltrerTextBoxComboBox.xlsm
    30.7 KB · Affichages: 93

Dranreb

XLDnaute Barbatruc
Bonjour.
L'objet ComboBoxLiées permet de faire ça.
(du moment qu'on n'espère pas pouvoir modifier ensuite une ComboBox en allant y chercher dans un autre tableau ce qu'on veut y mettre à la place. Toutefois si le Nom vernaculaire de droite ainsi que la classe étaient des ComboBox ce serait possible)

Mais on aurait une meilleure vision du résultat filtré en envoyant dans une ListBox tout ce qui correspond aux choix effectués dans les ComboBox. On verrait où on en est dans l'exploration de la liste, et on pourrait en selectionner un autre que celui juste avant ou juste après. Mais on pourrait éventuellement mettre un bouton toupie pour passer au suivant ou au précédent de la liste.

La question qui va se poser c'est que devra devenir le résultat du filtre si on modifie le critère.
Je pense qu'on ne peut pas le garder parce qu'il faut obligatoirement actualiser. Je doute qu'on puisse garder la position courante. Mais… il faut voir…)
 
Dernière édition:

pmfontaine

XLDnaute Occasionnel
Bonjour Dranreb,
Merci pour ta réponse.
Je vais faire une synthèse de mon fichier en enlevant les données confidentielles et en simplifiant les BD, pour avoir une vue globale de mon projet, car si on remet des ComboBoxLiées, je ne suis pas sur de pouvoir faire la synthèse de tous.
En attendant, est-ce qu'il y aurait une solution simple me permettant de limiter le nombre de lignes a une date ou a un site (peu importe)
Merci
Patrick
 

Dranreb

XLDnaute Barbatruc
Bonjour.
La programmation la plus simple possible dans l'UserForm sera celle utilisera un objet ComboBoxLiées.
De plus ce serait dommage de ne pas faire comme ça puisque je sais que le classeur que vous auriez dû joindre est déjà équipé des modules de classe qui définissent ce type d'objet. L'évènement Résultat donne directement la liste des numéros de lignes dans la base correspondant aux choix effectués.
Il n'y à qu'a l'affecter à une table Private TLgn As Long (faire TLgn = Lignes) et faire ensuite varier l'indice dans cette table pour prendre chaque enregistrement. La valeur d'un SpinButton SBn serait parfaite comme indice. Les données au numéro de ligne récupéré dans cette table à la position qu'il indique peuvent se récupérer dans la propriété PlgTablo, ou, s'il y a toujours des ListObject, dans la propriété Lignes. Exemple de code :
VB:
LCou = TLgn(SBn.Value)
VLgn = CL.Lignes (LCou).Range.Value
 
Dernière édition:

pmfontaine

XLDnaute Occasionnel
Merci Dranreb pour votre nouvelle intervention.
J'avoue ne pas savoir comment utiliser vos deux lignes de code.
Voila donc mon fichier simplifier, avec tous les éléments qui le compose.
Patrick
 

Pièces jointes

  • Gestion_observation_FichierTestV1.xlsm
    691.7 KB · Affichages: 95

Dranreb

XLDnaute Barbatruc
Un peu déçu que mes couleurs d'UserForm et autres ne vous aient pas plu finalement…
Je reviens sur l'UFmSaisie d'abord.
Je ne veux pas que vous utilisiez la méthode Range de la feuille active dans votre programmation.
Elle est longue à exécuter.
Ce sont des tableaux, alors utilisez les. Plus besoin de faire des End(xlUp) pour trouver la fin puisqu'on a LO.ListRows.Count.
Et renseignez les colonnes d'un coup, sans faire de boucle.
VB:
Dim LO as ListObject, Plage As Range
Set LO = FObserv.ListObjects("TabObs")
Set Plage = LO.ListRows(LO.ListRows.Count).Range.Offset(1).Resize(LBx.ListCount)
Plage.Columns("M").Resize(, 3).Value = LBx.List
Plage.Columns("A").Value = Me.datedesobservations
Plage.Columns("B").Value = Me.CBxSite
Plage.Columns("C").Value = Me.CBxObservateur1
etc.
Mais le mieux ce serait encore de préparer toute l'image des données à enregistrer dans un tableau.
Et ce en repartant des données d'origine, comme dans ma 1ère idée, et non de la LBx, puisqu'on a une colonne CD_NOM (Pourquoi Colonne1 dans TabEspèces ?) qui ne figure pas dans la ListBox. C'est idiot de la rechercher à postériori par une formule compliquée alors qu'on l'a dans la TabEspèces et donc dans CL.PlgTablo.Row(L) et dans CL.Lignes(L) !

Dans la BtValiderNom_Click de UFmNom on pourrait simplement faire :
VB:
With FEspèces.ListObjects("TabObservateurs")
   .ListRows.Add.Range.Value = Me.TextBoxNom.Text & " " & Me.TextBoxPrénom.Text
   .Sort.Apply
   For L = .ListRows.Count To 2 Step -1
      If .ListRows(L).Range.Value = .ListRows(L - 1).Range.Value Then .ListRows(L).Delete
      Next L: End With

Ne pourriez vous empiler les observateurs dans une ListBox ? Je déteste la répétition de contrôles servant tous à la même chose.
 
Dernière édition:

Dranreb

XLDnaute Barbatruc
Pour l'UFmModification il devrait être possible de partir de ça, au début :
VB:
Option Explicit
Private WithEvents Flt As ComboBoxLiées, LObs As Long, TLObs() As Long, _
   WithEvents Esp As ComboBoxLiées, LEsp As Long

Private Sub UserForm_Initialize()
Set Flt = New ComboBoxLiées
Flt.Plage [TabObs]
Flt.Add CBxFiltreValidation, "VALIDE"
Flt.Add CBxFiltreSite, "Site"
Flt.Add CBxFiltreDate, "Date"
Flt.Actualiser
Set Esp = New ComboBoxLiées
Esp.Plage [TabEspèces]
Esp.Add CBxModOrdre, "Classe"
Esp.Add CBxModNomVerna, "Nom vernaculaire"
Esp.Add CBxModNomLatin, "Nom latin"
Esp.Actualiser
End Sub
Avec un bouton toupie ou une barre de défilement pour conserver dans sa Value l'indice du numéro de ligne dans TLObs

Remarque: À partir du moment où on n'a jamais besoin de rechercher une espèce parmi les observations, il me paraît inutile d'avoir les contrôles en double pour la valeur d'origine d'une part et la valeur éventuellement modifiée d'autre part. Mais avant de remarquer ça, j'avais commencé à poursuivre ainsi :
VB:
Private Sub Flt_Change(ByVal Complet As Boolean, ByVal NbrLgn As Long)
Dim N As Long
If NbrLgn > 0 Then Exit Sub
ReDim TLObs(1 To Flt.Lignes.Count)
For N = 1 To UBound(TLObs): TLObs(N) = N: Next N
Position1
End Sub

Private Sub Flt_Résultat(Lignes() As Long)
TLObs = Lignes
Position1
End Sub

Private Sub Esp_Change(ByVal Complet As Boolean, ByVal NbrLgn As Long)
LEsp = 0
End Sub

Private Sub Esp_BingoUn(ByVal Ligne As Long)
LEsp = Ligne
End Sub

Sub Position1()
If SBn.Value = 1 Then SBn_Change Else SBn.Value = 1
SBn.Max = UBound(TLObs)
End Sub

Private Sub SBn_Change()
LabPosit.Caption = "Enregistrement " & SBn.Value & " / " & UBound(TLObs)
LObs = TLObs(SBn.Value)
VLObs = Flt.Lignes(LObs).Range.Value
TBxOrgDateObs.Text = VLObs(1, 1)
TBxOrgSite.Text = VLObs(1, 2)
…
End Sub
SBn est un SpinButton avec Min à 1.
Mais je vais maintenant attendre vos commentaires avant de continuer.
 
Dernière édition:

pmfontaine

XLDnaute Occasionnel
Bonsoir, Une fois de plus merci pour le temps que vous me consacrez.
Pour les couleurs d'UserForm, en fait je n'est pas trop fait attention, dans mes divers modification j'ai mis un peu au hasard pour le moment, je n'est pas regarder l'aspect présentation. Mais j'y viendrais.

Pour votre message de 15 h je pense avoir pratiquement réussi a mettre en place vos propositions. (Fichier jiont) Mais ça reste à vérifier si vous le voulez bien.
J'ai également mis les ComboBoxLiées pour la modification, qui semble marcher, mais, un détail me gène, quand je modifie, la Date et Cd_NOM sont au format texte au lieu de Date et Nombre. Comment mettre le bon format ?

Par contre pour votre message de 16 h 08 avec les filtres, j'ai fais des essais, mais sans résultat car je ne comprend pas du tous le code et je ne sais pas ce qu'est un Bouton Toupie, pour la Barre de défilement j'ai bien vu dans la boite à outil, mais je ne sais pas du tous comment ça s'utilise.
Patrick
 

Pièces jointes

  • Gestion_observation_FichierTestV2.xlsm
    675.5 KB · Affichages: 93

Dranreb

XLDnaute Barbatruc
Oui, j'ai oublié dans des codes que je vous ai montrés de convertir certains Text de contrôle en leur types de donnée corrects lorsqu'il le fallait.
Plage.Columns("A").Value = CDate(Me.datedesobservations)
Plage.Columns("P").Value = CDbl(Me.CBxCD_NOM)
Et l'idée de remplacer toutes les ComboBox observateurs par une seule + une ListBox, vous en pensez quoi ?
Et, dans l'autre UFm, un seul jeu de contrôles à la fois pour afficher les valeurs originales et les modifier ?
Un bouton toupie, simplement indiqué Toupie dans la boite à outils chez moi, est un double bouton avec des flèches pour avancer et reculer. Il peut se disposer verticalement ou horizontalement.
C'est un contrôle de type SpinButton. Ça s'utilise comme une barre de défilement, sa propriété Value est un nombre entier qui représente en général une position dans quelque chose et qui s'incrémente ou se décrémente quand on clique sur les boutons, ce qui déclenche un évènement Change.
Qu'est ce qui vous paraît obscur en dehors de cela ?
 
Dernière édition:

pmfontaine

XLDnaute Occasionnel
Bonjour,

Merci pour vos explications;
Pour Les observateurs dans une ListBox Je n'y vois pas d’inconvénient, au contraire, mais pour le moment je ne sais pas l'utiliser. (Dans tous nos échanges, vous avez peut-être compris que je suis 100% autodidacte en Excel VBA, donc j'avance à petits pas)

Dans les points bloquants, je n'arrive pas a mettre dans TabObs les valeurs De CBxCD_NOM dans UFmSaisie.
J'ai bien essayé de comprendre comment rajouter cette donnée dans LBx, mais je n'ai pas compris comment faire.

Certain point du programme ne sont pas très clairs, mais je comprend la logique.
Par contre ce code
Code:
LBx.ColumnWidths = CBxNomVerna.Left - CBxOrdre.Left & " pt;" _
  & CBxNomLatin.Left - CBxNomVerna.Left & " pt;" _
  & LBx.Width - CBxNomLatin.Left & " pt;0 pt"
est vraiment très obscur.

Que pensez-vous de mon principe de correction, je ne sais pas si c'est conventionnel, mais ça permet de faire les corrections toutes en gardant en visuelle les anciennes valeurs.

Bonne journée

Patrick
 

Dranreb

XLDnaute Barbatruc
Bonjour.

Pour remplir une ListBox avec les observateurs saisis un à un dans une seule ComboBox vous pouvez très bien utiliser le même principe que celui utilisé pour empiler les observations dans l'autre, avec un bouton pour ajouter ou retirer un observateur. C'est plus simple là: il n'y a qu'une seule colonne et vous pouvez simplement spécifier sa valeur à la méthode AddItem. Je vous suggère donc de vous obliger ainsi à comprendre comment ça fonctionne.
Je propose de repaptiser LBx en LBxObtions et la ListBox des observateurs LBxObteurs

Mais je crois qu'il ne faut pas, actuellement saisir CD_NOM. Ne faut-il pas le récupérer de la table des espèces ? À moins qu'il puisse aussi faire l'objet de la recherche d'espèce, auquel cas il n'y a qu'à ajouter la ComboBox à celles prises en charge par CL.

Ce point obscur ne doit pas vous tracasser: il ne touche en rien à la logique de fonctionnement du UserForm. Peut être entreverrez vous le but visé en tapant des nombres séparés de points virgules à la propriété ColumnWidths dans la fenêtre de propriétés de la LBx. Ce serait peut être mieux, d'ailleurs que les boutons soient au dessus et les ComboBox collées verticalement contre la ListBox. Comme ça les Label au dessus de ComboBox compteraient aussi bien comme leur désignation que comme titres des colonnes de la ListBox. C'est le seul cas où je mets aussi les Label au dessus de contrôles. Normalement, pour des contrôles isolés, ils se mettent toujours à leur gauche et non au dessus, ça donne une présentation moins chargée. Vous l'aurez compris, j'espère, le code mystérieux est une question d'alignement exact sur les ComboBox des colonnes de la ListBox.
 
Dernière édition:

pmfontaine

XLDnaute Occasionnel
Bonsoir,
Désolé pour ce silence un peu long, mais je n'ai pas eu beaucoup de disponibilité pour travailler sur mon dossier.
Mais je suis quand même arrivé à faire "presque tout" comme sur le fichier joint "Gestion_observation_FichierTestV4.xlsm"
Par contre sur le fichier Gestion_observation_FichierTestV5 avec filtre.xlsm j'ai mis en place le code que vous (Dranreb) m'avais proposé, mais je ne suis pas arrivé à le faire fonctionner.

Petite question concernant la réinitialisation après suppression d'une ligne, j'ai tenter (
Unload Me avec UserForm.Show) mais pas agréable et il faut trouver un moyen pour revenir au niveau de la ligne qui vient d'être supprimé. J'ai mis une macro correspondant a un changement de ligne pour mettre a jour l'UserForm, mais la macro est longue.
Est-ce qu'il y aurait une astuce plus agréable ?

Merci d'avance pour votre aide
Patrick
 

Pièces jointes

  • Gestion_observation_FichierTestV4.xlsm
    615 KB · Affichages: 79
  • Gestion_observation_FichierTestV5 avec filtre.xlsm
    615.2 KB · Affichages: 102

Dranreb

XLDnaute Barbatruc
Bonsoir.
Manque un Label nommé LabPosit et dans SBn_Change le reste des instructions qui garnissent toutes les TextBox à partir de VLObs
Je ne comprend vraiment pas l'intérêt de continuer d'afficher des informations devenues fausses si on y modifie quelque chose. Mais tant qu'à faire si ce n'est pas modifiable il vaudrait mieux l'afficher dans des Label et non des TextBox.
Non. Il ne faut surtout pas réinitialiser l'UserForm. Par contre il est impératif de faire Flt.Actualiser après toute modification dans les observations pour qu'il se mette en phase avec leur nouvel état.
Mettez bien toujours en tête de tous les noms de contrôles un trigramme reprenant les majuscules et la dernière lettre du nom du type de contrôle suivi d'un mnémonique commençant par une majuscule, et si c'est un nom composé, une majuscule au début de chaque mot qui le compose. Sauf pour les Label: trigramme Lab (seulement ceux qui sont manipulés par le code, pas les intitulés fixes)
Et je ne veux pas voir de Selection ni autre Range ou Cells. Là vous n'avez aucune garantie d'être sur la bonne ligne !
Selection.EntireRow.Delete : FAUX, c'est :
Flt.Lignes(LObs).Delete !
Et une modification devra se terminer par :
Flt.Lignes(LObs).Range.Value = VLObs, avec les VLObs(1, x) préalablement garni des valeurs de contrôles appropriés à chaque colonne x
 
Dernière édition:

pmfontaine

XLDnaute Occasionnel
Bonsoir,
Merci pour la réponse et aussi pour votre réactivité.
Ok j'ai mis un Label "LabPosit"
Mais "VLObs" c'est quoi ?

VLObs.jpg

Bonne soirée
Patrick
 

Dranreb

XLDnaute Barbatruc
VLObs() globale, déclarée à la suite dans l'instruction Private. Valeurs de la ligne d'observation courante.
C'est vrai que j'avais oublié de la signaler au poste #7 quand j'ai indiqué la suite de la programmation.
 
Dernière édition:

Discussions similaires

  • Résolu(e)
Microsoft 365 Code de tri
Réponses
22
Affichages
297
Réponses
2
Affichages
280

Statistiques des forums

Discussions
312 198
Messages
2 086 153
Membres
103 137
dernier inscrit
Billly