Icône de la ressource

VBA - Saisie filtrée (alias saisie intelligente) en ComboBox V7

Dudu2

XLDnaute Barbatruc
Modification du post et du fichier ci-dessus pour ajouter le TextColumn en paramètre.
 

crocrocro

XLDnaute Occasionnel
Ce serait intéressant que tu puisses utiliser le nouveau paramètre SearchFunction pour inclure ton code dans le mécanisme. Un exemple est donné dans le fichier pour la ComboBox UserForm.
VB:
'- FilterFunction:  Nom de la fonction personnalisée de filtrage.
'                   Si cet argument est valorisé, il représente le nom de la fonction qui sera appelée pour le filtrage
'                   des valeurs de la ComboBox par rapport aux caractères saisis. L'argument TypeFiltrage sera alors ignoré.
'                   Cette fonction reçoit en arguments:
'                   - Le texte (String) saisi dans la ComboBox
'                   - La table (Variant) à 2 dimensions (1 to n, 1 to p) des items de la ComboBox
'                   - Le TextColumn (Integer) de la ComboBox
'                   Cette fonction doit retouner:
'                   - La table (Long) à 1 dimension (1 to q) des Index [1 - n] des items sélectionnés dans la table des items de la ComboBox
'                   -------
'                   Exemple: Function MaFonctionFiltrage(ComboBoxText As String, TabItems() As Variant, TextColumn As Integer) As Long()
'                   -------

Ton code pourrait alors être proposé comme un "plugin" à la Ressource.
Essaie avec ce fichier et si cela fonctionne je publierai la nouvelle version de la Ressource et ton "plugin".
En pj, mon fichier (nom suffixé) correspondant à ta proposition.
Quelques remarques
- j'ai ajouté dans la feuille "Liste Référence", un tableau de liste de livres, plus adapté pour la ComboBox avec le choix de l'option "Proche". Avec la liste des clients, selon les caractères saisis, la différence n'est pas très sensible avec "Commence par" ou "Contient".
- Dans la feuille principale, j'ai ajouté 3 listes de choix, une pour le tableau de référence (Clients) ou (Livres), pour l'option de filtrage (commence par, contient ...) et la fonction Proche. Pour les personnes qui veulent se faire une première impression, cela me parait plus simple que d'aller bouger le code VBA, même s'il y a peu à faire.
Code:
     Call SaisieFiltréeComboBoxEnter(Me.ComboBoxActiveX, _
                                     ThisWorkbook.Worksheets("Listes Référence").ListObjects(Range("CHOIX_TABLEAU").Value).DataBodyRange, _
                                     TypeFiltrage:=Range("CHOIX_FILTRE").Value, _
                                     FilterFunction:=Range("FONCTION_PROCHE").Value)
- Pour aller plus loin dans les options existantes où tu n'as utilisé, pour ton filtrage que la mise en minuscule (Ucase), il serait facile d'ajouter des options complémentaires dans le Case KeepTypeFiltrage (non prise en compte des accents, des caractères spéciaux ...). Les fonctions de base sont dans mon module (Epure, Sans_Accent, Sans_Special)

Ce ne sont évidemment que de simples suggestions.

J'ai rencontré le petit problème suivant
Lié à ma fonction "FiltrageProche" qui semble être un problème de tempo dans la ComboBox :
Par exemple, si tu saisis "la", le "a" rapidement après le "l" (à la louche moins d'une demie-seconde), "le "a" n'est pas pris en compte dans la liste des Items (c'est comme si on avait saisi uniquement "l").
Dans un fichier où j'utilise une TextBox avec affichage de la Liste résultat au-dessous de la TextBox, le résultat est correct..
 

Pièces jointes

  • Saisie Filtrée ComboBox-crocrocro2.xlsm
    124.1 KB · Affichages: 4

Dudu2

XLDnaute Barbatruc
Bonjour,
T'as bien bossé !
il serait facile d'ajouter des options complémentaires dans le Case KeepTypeFiltrage (non prise en compte des accents, des caractères spéciaux ...)
Oui j'y ai pensé. J'utilise d'ailleurs une fonction très proche de ton Sans_Accent() dans certains cas.
Il faudrait sans doute l'intégrer par défaut pour ne pas alourdir l'appel de la fonction avec des paramètres supplémentaires. Je vais voir mais ça suppose un TabItemsCompare() en majuscules et épuré pour ne pas avoir à le refaire à chaque fois.
Par exemple, si tu saisis "la", le "a" rapidement après le "l" (à la louche moins d'une demie-seconde), "le "a" n'est pas pris en compte dans la liste des Items (c'est comme si on avait saisi uniquement "l").
C'est en effet un problème car à chaque évènement ComboBox_Change() et donc à chaque caractère tapé ou effacé on passe dans la moulinette.
Si elle dure trop longtemps, soit on perd le buffer keyboard des caractères tapés, soit on perd l'évènement ComboBox_Change() ce qui serait étrange. Il faut tracer pour savoir ce qu'il se passe.

Idéalement il faudrait pouvoir attendre 300-500 ms pour savoir s'il y a un autre évènement ComboBox_Change() avant de traiter. Mais cela implique une déclenchement asynchrone qu'on ne peut pas faire avec Application.Ontime dont la résolution n'est pas inférieure à 1 seconde et dont le délai est très aléatoire. Peut-être avec un SetTimer API. Mais ça devient plus complexe à gérer.
 

Dudu2

XLDnaute Barbatruc
Le test montre qu'on ne déclenche pas l'évènement ComboBox_Change().
Donc le 2ème caractère est perdu.

En remplaçant les SendKeys {F4} par des ComboBox.DropDown, ce problème disparait.
Sauf que le DropDown initial qui ne se faisait pas avec {F4} se fait avec le DropDown mais comme si le UserForm était en coordonnées (0, 0).
C'est dû au fait que le UserForm n'est pas encore affiché (UserForm_Test.Visible = False) quand on fait ComboBox_Enter() puisque la ComboBox est en ordre de tablulation le 1er Control activé. Pas facile de trouver une parade. Car il faut trouver le UserForm Parent de la ComboBox en remontant tous les Controls qui peuvent la contenir. Je crois que j'ai du code pour ça.

Alors il y a d'autres SendKeys nécessaires mais je n'ai pas (encore) constaté leur impact sur ce phénomène.
 
Dernière édition:

crocrocro

XLDnaute Occasionnel
çà devient chaud !
Le code va s'en retrouver complexifié et peut-être plus fragile.
Le jeu en vaut-il la chandelle ? Peut-être juste un petit avertissement à la 1ère utilisation ?
Pour ce qui est de ta réflexion,
Il faudrait sans doute l'intégrer par défaut pour ne pas alourdir l'appel de la fonction avec des paramètres supplémentaires. Je vais voir mais ça suppose un TabItemsCompare() en majuscules et épuré pour ne pas avoir à le refaire à chaque fois.
j'ai pu constater que c'était négligeable. Tu peux le vérifier par exemple dans FiltrageProche, dans la boucle
VB:
        For i = LBound(pTabItems, 1) To UBound(pTabItems, 1)
            DicoRef(CStr(i)) = Trim(pTabItems(i, pTextColumn)) ' les blancs en fin de ligne crééent un mot supplémentaire !!! pose pb en cas d'égalité
            For Each Elt In Split(Trim(pTabItems(i, pTextColumn)), " ")
                DicoMotRef(Epure(LCase(Elt))) = DicoMotRef(Epure(LCase(Elt))) & CStr(i) & " "
            Next Elt
        Next i
qui traite plus de 1000 lignes en une fraction de secondes.
C'est toujours quand on travaille sur de l'affichage dans les cellules que çà se corse, un simple mis en gras d'une cellule peut prendre une seconde !!! j'exagère à peine
 

Dudu2

XLDnaute Barbatruc
Non, ce n'est pas si compliqué.
Alors, ce qui a été fait:
- modifié pour intégrer un traitement des accents dans la comparaison.
- supprimé les SendKeys {F4}
- traité le cas où le UserForm n'est pas visible
- changé le paramètre FilterFunction en FonctionFiltrage (tout est en français)
 

Dudu2

XLDnaute Barbatruc
Une petite correction sur un ComboBox.DropDown initial manquant pour une ComboBox Active X.
 

Pièces jointes

  • Saisie Filtrée ComboBox-crocrocro3.xlsm
    132.6 KB · Affichages: 3

cathodique

XLDnaute Barbatruc
Bonjour @Dudu2 :),

Ton fichier m'a beaucoup intéressé. A tel point, que je vais ouvrir une discussion pour pouvoir utiliser ton code pour plusieurs comboboxs. Je sais que pour ceci, il faut utiliser un module de classe que je ne maîtrise pas du tout.
En tout cas bravo!🙌🙌👏👏👏👏👏👏

Bon dimanche.
 

Discussions similaires

Statistiques des forums

Discussions
312 106
Messages
2 085 352
Membres
102 871
dernier inscrit
Maïmanko