Ceci est une page optimisée pour les mobiles. Cliquez sur ce texte pour afficher la vraie page.

Microsoft 365 Sélection ligne dans ListBox avec boutons précédent-suivant

meyscal

XLDnaute Occasionnel
Bonjour le forum,

voilà, j'ai bien cherché dans les forums mais je n'ai rien trouvé qui répondait exactement à mon besoin.
J'ai un champ de recherche avec 2 boutons "Précédent" et "Suivant".

Mon besoin serait qu'avec un évènement Textbox1_Change, la 1ère ligne de la ListBox1 contenant le champ soit sélectionnée. Avec les boutons "Suivant" et "Précédent", je souhaiterais accéder à la prochaine ligne contenant l'élément. Là ou éventuellement ça peut se compliquer c'est que le champ recherché peut être une date (toujours format jj/mm/aaaa), un nom (majuscules et minuscules variables) , se trouver au milieu d'une phrase, ...

J'ai déjà essayé plusieurs codes dont certains me renvoient le résultat souhaité ou trient la ListBox mais ce n'est pas ce que je souhaite et je ne vois pas comment faire ça.

Quelqu'un aurait une idée par hasard ?

Voici ci-dessous le code pour ma listbox (initialize userform) + lors de la sélection de la ligne (récupération des champs dans textbox et combobox).7
Par avance merci

PS : je ne pourrais pas mettre de fichier exemple avant ce soir par contre.

VB:
Private Sub UserForm_Initialize()
HideBar Me
Sheets("Année 2023").Activate
With ListBox1
.List = Range("A2:N" & Range("B1000").End(xlUp).Row).Value
.ColumnCount = 14
End With
ListBox1.ColumnWidths = "35;44;65;45;75;18;13;120;140;45;65;140;45;140"
Dim i As Integer
For i = ListBox1.ListCount - 1 To 0 Step -1
If ListBox1.List(i) = "" Then ListBox1.RemoveItem (i)
Next i
End Sub


Private Sub ListBox1_Click() ' au clic dans la ListBox1
Me.TextBox1.Caption = Cells(Me.ListBox1.ListIndex + 2, 1)
Dim X As Integer
For X = 2 To 14 'boucle sur les 13 textboxes sauf n°1
Me.Controls("TextBox" & X).Value = Cells(Me.ListBox1.ListIndex + 2, X)
Next X
End Sub
 

mapomme

XLDnaute Barbatruc
Supporter XLD
Re,

Voici un exemple d'utilisation d'une colonne masquée dans une ListBox pour conserver le numéro de la ligne dans la feuille de calcul.

Voir l'initialisation du Userform1 et la procédure lié au bouton N° ? qui affiche le numéro de ligne sur la feuille de calcul de l'élément sélectionné et sélectionne la ligne concernée sur la feuille de calcul.

Les lignes de code liées à cette méthode sont un peu commentées.
 

Pièces jointes

  • MEYSCAL- Filtrer- v2.xlsm
    31 KB · Affichages: 3
Dernière édition:

meyscal

XLDnaute Occasionnel
Merci @mapomme (... et merci également à @Lolote83 et à @vgendron)
Je vais jeter 1 oeil à ça.
J'aime beaucoup les commentaires dans vos codes qui aident en amenant un côté pédagogique !

Comme je le disais, j'ai du mal à adapter à mon véritable fichier, le seul dispo pour le moment étant un exemple réalisé par @Lolote83.
Je le remets du coup dans ce post l'ayant supprimé précédemment. Celui-ci est cette fois-ci sans mot de passe. et sans sucre ajouté (pour ceux qui craignent de l'ouvrir)

Merci encore !
 

Pièces jointes

  • meyscal.xlsm
    237.7 KB · Affichages: 4

meyscal

XLDnaute Occasionnel
avec la version v1b sans les boutons de déplacement. Pour se déplacer, on utilise simplement les touches haut et bas du clavier.
Alors ça c'est top ! A se demander pourquoi ce n'est pas faisable de base avec n'importe quelle Listbox !

Je vais encore essayer d'adapter. Je suppose qu'une façon de contourner le problème (je préfère par nature généralement les affronter) que je rencontre est de mettre le code dans 1 module et de l'appeler dans un évènement ?
Ou bien je dis des c*****ies ?
 

mapomme

XLDnaute Barbatruc
Supporter XLD
Alors ça c'est top ! A se demander pourquoi ce n'est pas faisable de base avec n'importe quelle Listbox !
En fait une ListBox n'est pas obligatoirement reliée à une feuille de calcul (bien souvent quand même quand on l'utilise dans Excel).

Il est parfois tout aussi rapide de réécrire un code pour une situation particulière que de vouloir utiliser une procédure générique qui marche pour beaucoup de situation mais sans doute pas pour toutes les situations.
Si on a bien assimilé le principe d'une méthode, si on l'a codée deux ou trois fois, alors les prochains codages seront très rapides. Mais ça tu dois certainement déjà le savoir .
 
Dernière édition:

mapomme

XLDnaute Barbatruc
Supporter XLD
Ça m'arrive effectivement de faire une procédure pour garnir une listbox et d'appeler cette procédure dans différents évènements. Quand je fais cela, je place le code dans le module du UserForm.
 

meyscal

XLDnaute Occasionnel
Bonsoir,

bon j'ai à peu près réussi je pense mais j'ai un souci avec ça :




Et si je l'ajoute après Option Explicit ou dans le Sub du bouton filtre, voici ce que j'obtiens :



Je dis donc que j'y suis presque mais pas presque terminé ... presqu'à pouvoir tester si c'est fonctionnel.
Une idée de comment je peux corriger ?

J'ai recopié cela du Sub UF initialize mais sans succès (là rien ne se passe) :



Donc là je sèche et d'ailleurs je ne comprends plus ce que je fais ou ce qu'il faut faire ...

Bon pour le code du UF initialize tout est ok j'ai réussi à l'adapter et les fonctions de modifications sont ok !
C'est déjà ça

Merci par avance
 

mapomme

XLDnaute Barbatruc
Supporter XLD
Bonsoir,

Dans mon code, Ti est une variable définie au niveau du module de Userform1. En général juste après le "Option Explicit".
Ti est donc accessible dans n'importe quelle procédure (évènementielle ou non) situé dans le module de UserForm1.
Ti va contenir les données sources pendant toutes la durée de l'existence de UserForm1.
On va donc définir Ti dès l'initialisation de Userform1 dans la procédure Initialize de UserForm1.

Attention, il est tout à fait légal de pouvoir déclarer une variable Ti dans une autre procédure P . VBA l'autorise.
Mais il faut savoir que si l'on fait cela dans la procédure P, alors cette variable Ti (déclarée au niveau de P) n'a plus rien a voir avec la variable Ti (de niveau module) qu'on a initialisée.

La variable Ti déclarée dans P est une variable locale à la procédure P. Quand VBA rencontre la déclaration "Dim Ti"dans P, VBA crée une nouvelle variable "Ti" le temps de la procédure P. Quand P se termine, Ti est de la procédure P est détruite.

Donc quand vous exécutez P :
  • vous créez une variable Ti (vide) au niveau de la procédure P
  • Il existe déjà une autre variable Ti au niveau module (qui elle a été initialisée) mais qui est déconnectée de Ti variable locale déclarée dans la procédure P.
Dans une procédure P, les variables déclarées localement prennent le pas sur les variables déclarées au niveau module.

Si vous déclarez une variable au niveau module pour l'utiliser dans d'autres procédures, il ne faut surtout pas re-déclarer cette variable dans les autres procédures.

C'est ce qui se passe dans votre procédure en redéfinissant Ti. Ti est vide, VBA ne sait pas attribuer un "vide" à List de la listBox.

Donc, il faut bien déclarer "Dim Ti "après "Option Explicit" et surtout remplir Ti dès que possible avant de vouloir utiliser Ti dans d'autre procédures. Et le plus naturel est de la faire dans la procédure Initialize de l'Userform1.

Il peut y avoir d'autres subtilités mais sans le fichier c'est compliqué à dire.

Les questions à se poser :
Ai-je besoin d'une variable utilisable dans différente procédure ?
Si Oui, je la déclare au niveau du module de UserForm1 (et je fais attention à ne pas la re-déclarer ailleurs)
Et je veille bien à avoir défini une valeur pour Ti avant de l'utiliser une dans une autre procédure.

Bien sûr ce n'est la seule façon de faire, mais c'est une des plus basique.
 

meyscal

XLDnaute Occasionnel
Bonjour @mapomme, @Lolote83, @vgendron, le forum

Donc, il faut bien déclarer "Dim Ti "après "Option Explicit" et surtout remplir Ti dès que possible avant de vouloir utiliser Ti dans d'autre procédures. Et le plus naturel est de la faire dans la procédure Initialize de l'Userform1.

Je ne suis pas sûr d'avoir bien tout compris, désolé ...
Du coup cela signifie que vu que c'est dans le UF Initialize je n'en ai plus besoin après ?
En l'enlevant, j'ai quand-même une autre erreur (incompatibilité de type) :



Mais je pense surtout que je n'ai pas bien compris.

Je mets le fichier en PJ, comme dit précédemment j'ai réussi à adapter pour le reste.

Bonne journée
 

Pièces jointes

  • meyscal.xlsm
    247.2 KB · Affichages: 1

cp4

XLDnaute Barbatruc
Bonjour tout le monde,
 

meyscal

XLDnaute Occasionnel
Bonjour Cp4

c'est ce que j'ai fait + dans le code du bouton. Plus de message d'erreur mais le filtre ne fonctionne pas.
Je ne comprends plus rien là.

Qqun a une idée ? Je pensais avoir réussi à adapter mais peut-être pas finalement ...
 

Pièces jointes

  • meyscal.xlsm
    247.6 KB · Affichages: 6

cp4

XLDnaute Barbatruc
@meyscal : Tu dois avoir une 'condition' mal construite. Tu as plusieurs userforms.
J'ai vu le userform3, le code du bouton 'Cmd_Filtrer' a une condition bizarre à mon sens.
VB:
   If Trim(Txt_Filtre) = "" Then clef = "*" Else clef = "*" & LCase(Txt_Filtre) & "*"
   'ne serait-ce pas <> "" par hasard! au lieu de =""
Ensuite, sur ce formulaire je ne vois pas de bouton 'suivant'/'precedent'
 

meyscal

XLDnaute Occasionnel
Non j'ai enlevé les boutons suivant et précédent car à l'utilisation ce n'était pas très pratique et la solution de @mapomme avec les boutons haut et bas du clavier est top.
Pour le Userform 3 oui c'est bien sur celui-là que se situe le problème.
Le code fournit par @mapomme fonctionnait bien sur le fichier exemple donc j'ai des doutes pour le <>

Bon je commence à me dire que je vais laisser tomber la fonctionnalité de recherche car je vois pas le bout.
Merci quand-même à vous tous
 

vgendron

XLDnaute Barbatruc
Hello

Je crois qu'il s'agit simplement d'un problème de syntaxe pour le nom du control Txt_Filtre

essaie avec ceci
VB:
Private Sub Cmd_Filtrer_Click()
Dim clef, i&, j&, present As Boolean
Dim Txt_Filtre

   If Trim(Me.Txt_Filtre) = "" Then clef = "*" Else clef = "*" & LCase(Me.Txt_Filtre) & "*"
 
   For i = UBound(Ti) To 1 Step -1
      present = False
      For j = 1 To UBound(Ti, 2)
         If LCase(Ti(i, j)) Like clef Then present = True: Exit For
      Next j
      If Not present Then ListBox1.RemoveItem i - 1
   Next i
   If ListBox1.ListCount > 0 Then ListBox1.ListIndex = 0
End Sub

PS: ajouter le préfixe Me. permet justement d'éviter les pb de syntaxe puisque la saisie semi auto ne te propose que les controles connus sur le formulaire

PS2: Bizarrement,
msgbox Txt_Filtre ne renvoie rien
alors que
msgbox me.Txt_Filtre donne bien le contenu de la boite...

PS3: il faudrait ajouter un bouton "quitter" sur ton formulaire..
 
Dernière édition:

meyscal

XLDnaute Occasionnel
Hello @vgendron

nickel ! Merci C'est fou quand-même que c'était juste ça le souci.

Bon si je reclique sur le bouton j'ai cette erreur qui apparaît mais avec un On error resume next c'est réglé



Par contre malheureusement je constate que je n'ai pas dû correctement adapter le code de @mapomme.
Cela vient peut-être du fait que j'ai encore des colonnes après la sélection ?
Une fois la liste filtrée, les éléments reportés dans la "carte rouge" ne sont pas les bons et même en essayant d'ajouter une colonne vide c'est sans effet ...

Pfff c'est sans fin
 

Pièces jointes

  • meyscal.xlsm
    253.4 KB · Affichages: 4

Discussions similaires

Réponses
17
Affichages
1 K
Réponses
4
Affichages
403
Les cookies sont requis pour utiliser ce site. Vous devez les accepter pour continuer à utiliser le site. En savoir plus…