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

pmfontaine

XLDnaute Occasionnel
Bonjour,
J'ai pas tous compris ?
Ok VLObs() est bien déclarée
Code:
Option Explicit
Private WithEvents Flt As ComboBoxLiées, LObs As Long, TLObs() As Long, _
   WithEvents Esp As ComboBoxLiées, LEsp As Long
Mais pourquoi VLObs n'est pas défini comme j'ai sur le message d'erreur ?
Et Quelle différence entre VLObs() et VLObs (Une et globale ? et l'autre est simple ?)
Je vais essayer de comprendre sur ces pages https://www.excel-pratique.com/fr/vba/variables.php et https://www.excel-pratique.com/fr/vba/variables_suite.php

Mais en attendant, pour finaliser mon projet, que dois-je mettre pour ne plus avoir cette erreur ?

Merci et bonne journée
Patrick
 

Dranreb

XLDnaute Barbatruc
Bonjour.
Ajoutez ", VLObs()" à la suite dans l'instruction de déclaration globale Private, et ne déclarez cette variable nulle part ailleurs.
Sans les parenthèses ça déclarerait un Variant et non un tableau dynamique d'éléments Variant. Un Variant peut certes ensuite contenir un tableau de Variant mais ça ne sert à rien de faire comme ça si c'est toujours un tableau qu'on veut. On peut dès le départ le déclarer en tant que tableau dynamique si on n'a jamais à l'impliquer dans un contexte où il faut un Variant.
Peut être vous y retrouveriez vous mieux, vous, si vous déclariez chaque variable globale dans une instruction Private séparée, avec un commentaire au bout expliquant ce qu'elle contiendra, ce qui définit du coup son rôle dans l'UserForm.
(Une et globale ? et l'autre est simple ?)
Qu'est ce que vous entendez par simple ? Non globale c'est locale et donc déclarée dans une procédure, non par Private ni Public, ces instructions y étant interdites, mais seulement par Dim. Volatile, son existence ne dure que le temps d'exécution de la procédure et elle n'est partagée, conservée ni connue nulle part en dehors d'elle.
 
Dernière édition:

Dranreb

XLDnaute Barbatruc
Oui. Je pense que vous ne vous en sortirez pas sans cela. Et chaque fois qu'il en faudra une de plus on l'ajoutera sur le même principe.
VB:
Option Explicit
Private WithEvents Flt As ComboBoxLiées ' Gestion des choix des ComboBox CBxFiltre…
Private TLObs() As Long ' Table des numéros dans Flt.Lignes des lignes d'observations filtrées.
Private LObs As Long ' Numéro dans Flt.Lignes de la ligne d'observation courante.
Private VLObs() As Variant ' Valeurs de la ligne d'observation courante.
Private WithEvents Esp As ComboBoxLiées ' Gestion des choix des ComboBox CBxMod…
Private LEsp As Long ' Numéro dans Esp.Lignes de la ligne de l'espèce choisie.
 

pmfontaine

XLDnaute Occasionnel
Bonsoir,
Si je n'avais pas mélangé TLObs() et VLObs() j'aurais plus vite compris.
Mais heureusement maintenant j'ai vu mon erreur et tous fonctionne comme je le souhaitais, mais je dois encore mettre a jour du code qui n'est pas comme vous le préconisez.
Même si ça fonctionne, Il faut que je vérifie qu'il ne reste pas des (Range ou Cells.)
Je vais également mettre en application votre suggestion pour les noms des contrôles.
Merci et Bon W.E.
Patrick
 

pmfontaine

XLDnaute Occasionnel
Bonsoir
Mon fichier fonctionne avec la mise en place du code de Dranreb si-dessous.
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

Mais je bloc sur la modification du code suivant avec les éléments tableau
Code:
Dim Cel As Range
Dim DerLig As Long
Dim DerCol As Long
Dim Dico As Object
Dim LigneActive As Long
Dim Temp
Set Dico = CreateObject("Scripting.Dictionary")
Me.LBobservateurs.Clear 'on efface la LBobservateurs
Me.CBxObservateur.Clear 'on efface le CBxObservateur
LigneActive = LObs + 1
     With Sheets("BD")
If Cells(LigneActive, 2).Value <> "" Then 's'il y a déjà au moins un observateur
           DerCol = WorksheetFunction.CountA(Range(Cells(LigneActive, 3), Cells(LigneActive, 12)))
                For Each Cel In Range(Cells(LigneActive, 3), Cells(LigneActive, DerCol + 2)) 'on balaie la ligne de Col 3 à derniere col avec observateur.
                    Me.LBobservateurs.AddItem Cel.Value 'et on met les Observateurs déjà inscrits dans la listbox
                Next Cel
           End If
    End With
  
       With Sheets("ESPECES")
        DerLig = .Cells(Rows.Count, 12).End(xlUp).Row 'dernière ligne du tableau observateurs
        For Each Cel In .Range("L2:L" & DerLig) 'on balaie la colonne
       If IsError(Application.Match(Cel.Value, Sheets("BD").Rows(LigneActive), 0)) Then Dico(Cel.Value) = Cel.Value
            'ici, on ne va rajouter dans CBxObservateur les observateurs non présents dans la ligne selectionnée
        Next Cel
    If Dico.Count > 0 Then 'si tous les observateurs ne sont déjà pas présents dans la ligne selectionnée
            Temp = Dico.keys
            Me.CBxObservateur.List = Temp
        End If
    End With
Je n'arrive pas a modifier une ligne sans avoir une erreur. Par exemple j'ai voulu remplacer
Code:
  DerLig = .Cells(Rows.Count, 12).End(xlUp).Row 'dernière ligne du tableau observateurs
Par
Code:
DerLig =  UBound(TabObservateurs)
en déclarant TabObservateurs () dans l'instruction de déclaration globale Private. Mais ça marche pas.

J'ai essayé de mettre dans ce code VLObs(1, Col) mais sans succes.

J'arrive a adapté un code mais là il faut pratiquement le créer et je n'y arrive pas.
Merci d'avance pour votre aide
Patrick
 

Dranreb

XLDnaute Barbatruc
Bonsoir.
La table des observateurs est aussi mise sous forme de tableau. Alors utilisez les fonctionnalités du ListObject et travaillez avec un petit tableau local où vous commencez par la charger entièrement.
Joignez votre classeur.

À priori ce serait quelque chose comme ça :
VB:
Private Sub MàJListCBxObsver()
Dim L As Long, D As New Dictionary, T()
For L = 0 To LBxObsver.ListCount - 1: D(LBxObsver.List(L, 0)) = 1: Next L
CBxObsver.Clear
T = [TabObsver].Value
For L = 1 To UBound(T)
   If Not D.Exists(T(L, 1)) Then CBxObsver.AddItem T(L, 1)
   Next L
End Sub

À appeler chaque fois que la ListBox des observateurs est changée.

Remarque: peut être y aurait il intérêt à remplacer partout mon Obsver par une abréviation d'un synonyme plus court de observateur tel que Témoin, Surv, Spect, Invest, Scrut
 
Dernière édition:

pmfontaine

XLDnaute Occasionnel
Bonjour Dranreb et le Forum
Merci Dranreb d'être toujours là pour m'aider.
De mon coté, je vais essayer votre code pour apprendre, mais comme je sais que ça vas être compliqué pour moi voila mon fichier en pièce jointe.

Une question
Code:
 For NbObs = 0 To Me.LBxObservateurs.ListCount - 1 'et on rajoute les observateurs à la suite
            VLObs(1, 3 + NbObs) = Me.LBxObservateurs.List(NbObs)
            Next NbObs
Ça marche, sauf si dans ma correction j’enlève des observateurs (3 ALD 4 par Exemple) Le quatrième reste dans TabObs. J'ai mis :
Code:
            For NbObs = 0 To 9
            VLObs(1, 3 + NbObs) = ""
            Next NbObs

            For NbObs = 0 To Me.LBxObservateurs.ListCount - 1 'et on rajoute les observateurs à la suite
            VLObs(1, 3 + NbObs) = Me.LBxObservateurs.List(NbObs)
            Next NbObs
Qui marche, mais est-ce une programmation correcte ?

PS : J'ai chercher sur le Net une site qui explique le fonctionnement des tableaux, mais rien trouvé de valable, Avez vous un site a me conseiller ?

Bon Dimanche
Patrick
 

Pièces jointes

  • Gestion_observation_FichierTestV12 avec filtre.xlsm
    596.5 KB · Affichages: 56
Dernière édition:

Dranreb

XLDnaute Barbatruc
Bonjour.
Je prendrais une de ces 2 structures :
VB:
For NbObs = 0 To Me.LBxObservateurs.ListCount - 1 'et on rajoute les observateurs à la suite
   VLObs(1, 3 + NbObs) = Me.LBxObservateurs.List(NbObs)
   Next NbObs
While NbObs < 9: VLObs(1, 3 + NbObs) = Empty: NbObs = NbObs + 1: Wend
VB:
For NbObs = 0 To 9
   If NbObs < LBxObservateurs.ListCount Then
         VLObs(1, 3 + NbObs) = Me.LBxObservateurs.List(NbObs)
   Else: VLObs(1, 3 + NbObs) = Empty: End If
   Next NbObs

Que voudriez vous savoir sur les tableaux que vous ne savez déjà ?
LBound(T, n) donne le 1er indice de la nième dimension de T
UBound(T, n) donne le dernier indice de la nième dimension de T
Redim permet de définir les dimensions de T seulement si c'est un tableau dynamique,
Redim Preserve permet de le faire sans perdre le contenu, mais en changeant seulement le UBound de la dernière dimension.
C'est plutôt une règle d'Excel que vous ne saisissez pas, celle ci :
La propriété Value d'un objet Range représentant plusieurs cellules contigües est un tableau d'éléments de type Variant à deux dimensions en base 1, même s'il n'y a qu'une ligne ou une colonne. (s'il y en a à la fois seulement 1 de chaque c'est juste un Variant, non un tableau). Dimensions de Plage.Value : (1 To Plage.Rows.Count, 1 To Plage.Columns.Count)
J'ajouterai que la récupération ou la modification de la propriété Value d'un Range est une opération longue en soit, Excel passant beaucoup plus de temps à retrouver les adresses d'implantation dans l'image mémoire extrêmement complexe du classeur qu'à transférer les valeurs proprement dites. Cette durée est pratiquement indépendante du nombre de cellules. Aussi a-t-on toujours intérêt à en transférer le plus possible le moins souvent possible dans des tableaux. Le cellule par cellule est à bannir absolument.

Je trouve qu'il y a quelque chose qui ne va pas dans votre système.
On a d'un coté des valeurs d'origine au complet mais présumées fausses si on entreprend d'en modifier certaines, ce qui me fait d'ailleurs douter de l'utilité de les afficher,
Et de l'autre quelque contrôles seulement, renseignés de façon exacte. Mais on n'a nulle part une vue d'ensemble de tous les contrôles renseignés conformément à ce qu'on va envoyer dans la fiche.
 
Dernière édition:

pmfontaine

XLDnaute Occasionnel
Merci
Je suppose que vous préconisez ce que j'ai fait sur le fichier joint. (Supprimer TextBox et Pre-remplir les ComboBox) Pour avoir une vue complète de la ligne.
Mais ça bug :
  • Plus de liste de choix dans les ComboBoxLiées
  • plus erreur de type quand on veux appliquer un filtre
  • Et
    VB:
    VLObs(1, 3 + NbObs) = IIf(NbObs < LBxObservateurs.ListCount, LBxObservateurs.List(NbObs), Empty)
    Ne fonctionne plus.
Je supose donc que ce n'est pas la bonne méthode !
Patrick
 

Pièces jointes

  • Gestion_observation_FichierTestV13 avec filtre.xlsm
    590.2 KB · Affichages: 66

Dranreb

XLDnaute Barbatruc
En fait j'ai commis une erreur en vous indiquant cette instruction. IIf évalue la 1ère expression même si la condition est fausse. On ne peut donc l'employer. J'ai corrigé en la solution équivalente du 2ième code dans mon dernier édit du poste précédent.
Je vais regarder votre nouveau fichier.
À +
 

Dranreb

XLDnaute Barbatruc
Manque Esp.Actualiser dans l'UserForm_Initialize pour que les données d'espèces soient prises en compte.
On peut peut être enlever "Mod" dans les noms de contrôles, maintenant qu'ils servent à la fois d'entrée et de sortie.
Si vous décidez un jour de remettre des contrôles pour montrer la situation d'origine, ce seront plutôt des Lab.
 

Dranreb

XLDnaute Barbatruc
Si le trigramme CBn ne vous parle pas assez je veux bien mais alors Btn pas BTn parce qu'il n'y a pas de T majuscule dans CommandButton (Mais il en a 2, c'est peut être ça ?…)

Il faut mettre l'initialisation de Esp avant celle de Flt parce que la Flt.Actualiser entraine de proche en proche une référence à Esp dans la SBn_Change

Ah non ! Une ComboBox sert à quelque chose et alors elle est visible ou vous n'en mettez pas !
Cette information vous l'avez dans Esp.PlgTablo(LEsp, 4).Value
pis comme ça vous n'aurez même pas à faire de CDbl dessus, elle y est déjà du bon type de donnée.
 
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 188
Messages
2 086 028
Membres
103 100
dernier inscrit
erym64300