Vous êtes sur la page 1sur 44

### Mise sur pied du formulaire pour la recherche

Structure du formulaire de recherche


La recherche doit pouvoir se faire selon plusieurs critères :
par compositeur par appréciation
par type de musique par recherche libre
par instrumentation par période
par interprétation par collection spéciale

De plus, l'utilisateur doit pouvoir choisir l'affichage selon deux critères de tri :
par numéro de CD par compositeur

Nous allons donc créer un formulaire qui sera déclanché par le bouton Recherche de la façon suivante :

o Private Sub cmdRecherche_Click()


o frmRecherche.Show
o End Sub

Vu que l'utilisateur va pouvoir choisir parmi plusieurs critères de recherche, il convient de n'afficher que les listes déroulantes ou les zones
de textes nécessaires. Cela explique pourquoi beaucoup ont été rendues invisibles et ne deviendront visibles que lorsque l'utilisateur va
cliquer sur une case à cocher correspondante.
Par défaut, il faut s'attendre à ce que l'utilisateur fasse une recherche par compositeur. Dans ce cas - et dans ce cas seulement - il serait
souhaitable d'avoir un tri par numéro de CD. Lors de l'affichage du formulaire, le bouton d'option par numéro de CD ainsi que la case à cocher
par compositeur seront activés automatiquement.
Table des propriétés du formulaire et du cadre
Propriété Valeur Valeur
Name frmRecherche fraChoixDeTri
Caption Formulaire de recherche Choisissez un ordre de tri pour vos résultats !
Height 257.25 41.25
Left 0 7.5
Top 0 7.5
Width 240 217.5

Table des propriétés des boutons d'option Table des propriétés des boutons de commande
Propriété Valeur Valeur Propriété Valeur Valeur
Name optCompositeur optParCD Name cmdOK cmdAnnuler
Caption par compositeur par numéro de CD Caption OK Annuler
Default True False Cancel False True
Height 15.75 15.75 Default True False
Left 11.25 120 Height 18.75 18.75
Top 11.25 11.25 Left 176.25 116.25
Value False True Top 213.75 213.75
Width 86.25 86.25 Width 50 50

Table des propriétés des cases à cocher


Propriété Valeur Valeur Valeur Valeur
Name chkCompositeur chkTypeMusique chkInstrumentation chkInterprétation
Caption par compositeur par type de musique par instrumentation par interprétation
Height 15 15 15 15
Left 7.5 7.5 7.5 7.5
TabStop False False False False
Top 60 82.5 105 127.5
Width 96 96 96 96

Table des propriétés des cases à cocher


Propriété Valeur Valeur Valeur Valeur
Name chkAppréciation chkRechercheLibre chkPériode chkCollection
Caption par appréciation par recherche libre par période collection particulière
Height 15 15 15 15
Left 7.5 7.5 7.5 7.5
TabStop False False False False
Top 150 172.5 195 217.5
Width 96 96 96 96

Table des propriétés des listes déroulantes


Propriété Valeur Valeur Valeur Valeur Valeur
Name cboCompositeurs cboTypeMusique cboInstrumentation cboInterprétation cboAppréciation
Height 16 16 16 16 16
Left 7.5 7.5 7.5 7.5 7.5
Top 60 82.5 105 127.5 150
Visible True False False False False
Width 120 120 120 120 120
Table des propriétés des libellés
Propriété Valeur Valeur Valeur
Name lblDe lblA lblEcart
Caption de à écart
Height 11.25 11.25 11.25
Left 93.75 140.75 178.25
Top 197.5 197.5 197.5
Visible False False False
Width 96 10 20

Table des propriétés des zones de texte


Propriété Valeur Valeur Valeur Valeur
Name txtRechercheLibre txtDe txtA txtEcart
Height 15.75 15.75 15.75 15.75
Left 108.75 107.75 148.25 200.75
Top 172.5 195 195 195
Visible False False False False
Width 120 26.25 26.25 26.25

Le code du bouton Annuler est le suivant

o Private Sub cmdAnnuler_Click()


o Unload Me
o End Sub

Affichage du formulaire et remplissage de la liste déroulante automatique pour les compositeurs

Attention : consulter la feuille "Améliorations aux recherches pour y trouver une solution
beaucoup plus simple sous le titre Remplissage d'une liste déroulante simplifiée !
Lorsque le formulaire s'affiche, on voudrait pouvoir avoir immédiatement le listing de tous les compositeurs dans la liste déroulante correspondante. On
ne veut toutefois pas que on ait éternellement le même premier conpositeur qui s'affiche. Par conséquent, on évitera la ligen de code suivante en fin de
sous-procédure :

o frmRecherche.cboCompositeurs.ListIndex = 0

En revanche, on va devoir utiliser la fonction qui nous remplit la liste déroulante plusieurs fois. Il est donc raisonnable de mettre sur pied une sous-
procédure qui accepte des paramètre pour pouvoir remplir n'importe quelle liste déroulante de notre application.

De plus, comme nous allons chercher des listing déjà triés avec des références uniques, il serait intelligent de définir dans quelle feuille de notre classeur
se trouve le listing désiré pour la liste déroulante ainsi que la longueur de chaque listing. C'est la raison pour laquelle nous définissons les constantes
publiques suivantes (ces constantes sont à mettre dans le module principal) :

o Public Const RANGE_COMPOSITEURS = "A2:A300"


o Public Const RANGE_INTERPRETATION = "A2:A300" Ce code statique est en fait une mauvaise solution. Il faudra
o Public Const RANGE_INSTRUMENTATION = "A2:A100" le changer ultérieurement pour le rendre dynamique, bien
o Public Const RANGE_TYPE_MUSIQUE = "A2:A30" entendu avec des variables globales.
o Public Const RANGE_APPRECIATION = "A2:A20"

Le code qui se déclenche lorsque frmRechercher s'affiche est le suivant :

o Private Sub UserForm_Activate()


o Call RemplirListeDéroulante("frmRecherche", "Compositeurs", RANGE_COMPOSITEURS, "cboCompositeurs")
o End Sub

Ici, le code général pour remplir une liste déroulante (ce code est à placer dans le module FormulaireRecherche) :

o Sub RemplirListeDéroulante(ByRef frm As String, sh As String, rge As String, cbo As String)


o Dim AllCells As Range, Cell As Range
o Dim NomElément As New Collection
o 'Comme Item va être utilisé dans For Each, il faut qu'il soit de nature Variant ou Object
o Dim Item As Variant
o
o Set AllCells = Sheets(sh).Range(rge)
o
o For Each Cell In AllCells
o 'Le If sert dans le cas où il n'y a plus de compositeur dans la range pour éviter un message d'erreur.
o If Cell.Value <> "" Then NomElément.Add Cell.Value
o Next Cell
o
o 'Ajouter la liste triée d'objets uniques dans la ListBox
o For Each Item In NomElément
o frmRecherche.cboCompositeurs.AddItem Item
o Next Item
o End Sub

En fait, nous allons "nourrir" toutes les listes déroulantes, que celles-ci soient visibles ou non. Ainsi, le travail sera déjà fait
au départ, et dès l'activation d'une case à cocher, la liste déroulante sera visible avec son contenu tout prêt.

Nous changerons le code du UserFormActivate() comme décrit ci-après :

o Private Sub UserForm_Activate()


o Call RemplirListeDéroulante(Me, "Compositeurs", RANGE_COMPOSITEURS, "cboCompositeurs")
o Call RemplirListeDéroulante(Me, "Appréciation", RANGE_APPRECIATION, "cboAppréciation")
o Call RemplirListeDéroulante(Me, "Instrumentation", RANGE_INSTRUMENTATION, "cboInstrumentation")
o Call RemplirListeDéroulante(Me, "Interprétation", RANGE_INTERPRETATION, "cboInterprétation")
o Call RemplirListeDéroulante(Me, "TypeMusique", RANGE_TYPE_MUSIQUE, "cboTypeMusique")
o End Sub

Notez le changement du première paramètre "frmRecherche" en Me dans les appels ci-dessus et la répercussion sur la sous-routine elle-même !

Cela entraîne la modification du code de la sous-routine RemplirListeDéroulante( … ) :

o 'Sous-routine servant remplir les différentes listes déroulantes


o 'Sous-routine appelée par UserForm_Activate() aussi bien dans le formulaire
o 'frmRecherche que frmNouveauCD
o Sub RemplirListeDéroulante(ByRef frm As UserForm, sh As String, rge As String, cbo As String)
o Dim AllCells As Range, Cell As Range
o Dim NomElément As New Collection
o 'Comme Item va être utilisé dans For Each,
o 'il faut qu'il soit de nature Variant ou Object
o Dim Item As Variant
o
o Set AllCells = Sheets(sh).Range(rge)
o
o For Each Cell In AllCells
o 'Le If sert dans le cas où il n'y a plus de compositeur
o 'dans la range pour éviter un message d'erreur.
o If Cell.Value <> "" Then NomElément.Add Cell.Value
o Next Cell
o
o 'Ajouter la liste triée d'objets uniques dans la ListBox
o Select Case cbo
o Case "cboCompositeurs"
o For Each Item In NomElément
o frm.cboCompositeurs.AddItem Item
o Next Item
o 'Ligne qu'il faudrait rajouter si on veut
o 'l'affichage sur le premier compositeur
o 'frmRecherche.cboCompositeurs.ListIndex = 0
o Case "cboAppréciation"
o For Each Item In NomElément
o frm.cboAppréciation.AddItem Item
o Next Item
o Case "cboInstrumentation"
o For Each Item In NomElément
o frm.cboInstrumentation.AddItem Item
o Next Item
o Case "cboInterprétation"
o For Each Item In NomElément
o frm.cboInterprétation.AddItem Item
o Next Item
o Case "cboTypeMusique"
o For Each Item In NomElément
o frm.cboTypeMusique.AddItem Item
o Next Item
o Case Else
o MsgBox "Problème dans Select Case RemplirListeDéroulante"
o End Select
o
o End Sub
Bouton Recherche 2 Contrôle logique d'affichage des listes déroulantes dans

Click sur le bouton OK du formulaire de recherche


L'utilisateur pourrait très bien par inadvertence désactiver la première case à cocher. Dans ce cas-là, il n'y aurait rien à
s'assurer que ceci ne soit pas le cas. C'est la première chose dont il faut se soucier après que l'utilisateur clique sur le

Le déclenchement du bouton OK est relié à la procédure qui suit, procédure qui va encore s'étoffer :

o Private Sub cmdOK_Click()


o If ContrôleAuMoinsUneCaseACocherValide = True Then
o ….
o End If
o End Sub

Voici la sous-procédure de contrôle qui doit être placée, bien entendu, dans un module ad hoc.

o Public Function ContrôleAuMoinsUneCaseACocherValide()


o If frmRecherche.chkAppréciation = False And _
o frmRecherche.chkCollection = False And _
o frmRecherche.chkCompositeur = False And _
o frmRecherche.chkInstrumentation = False And _
o frmRecherche.chkInterprétation = False And _
o frmRecherche.chkPériode = False And _
o frmRecherche.chkRechercheLibre = False And _
o frmRecherche.chkTypeMusique = False Then
o MsgBox "Vous devez opter pour au moins une possibilité de recherche !", vbExcla
o ContrôleAuMoinsUneCaseACocherValide = False
o Else
o ContrôleAuMoinsUneCaseACocherValide = True
o End If
o End Function

Activation et désactivation d'une liste déroulante en fonction d'une case à cocher


Il se pourrait toutefois que l'utilisateur désactive une case à cocher. Dans ce cas, il faut s'assurer que la liste déroulant
correspondante ne s'affiche pas. En revanche, si une case à cocher est activée, il faut que la zone de texte ou la liste
s'affiche. Et s'il s'agit d'une liste déroulante, nous la voulons bien entendu nourrie de son contenu !…
Il s'agit par conséquent d'événements liés aux différentes cases à cocher.
De plus, on peut regrouper les cases à cocher de cet exemple en 2 catégories :
les cases à cocher avec liste déroulante
les cases à cocher sans liste déroulante
Lorsqu'une case à cocher de la première catégorie est activé, il faut désactiver l'autre catégorie, et vice versa.
De plus, du dernier groupe des trois cases à cocher, seule une case peut-être validée.

Nous proposons donc les codes événementielles et leurs sous-procédures suivantes :

o Private Sub chkAppréciation_Click()


o cboAppréciation.Visible = Not cboAppréciation.Visible
o If cboAppréciation.Visible = True Then Call DésactiverZonesTexte
o End Sub

o Private Sub chkCompositeur_Click()


o cboCompositeurs.Visible = Not cboCompositeurs.Visible
o If cboCompositeurs.Visible Then Call DésactiverZonesTexte
o End Sub

o Private Sub chkInstrumentation_Click()


o cboInstrumentation.Visible = Not cboInstrumentation.Visible
o If cboInstrumentation.Visible Then Call DésactiverZonesTexte
o End Sub

o Private Sub chkInterprétation_Click()


o cboInterprétation.Visible = Not cboInterprétation.Visible
o If cboInterprétation.Visible Then Call DésactiverZonesTexte
o End Sub

o Private Sub chkPériode_Click()


o txtDe.Visible = Not txtDe.Visible
o txtA.Visible = Not txtA.Visible
o txtEcart.Visible = Not txtEcart.Visible
o lblDe.Visible = Not lblDe.Visible
o lblA.Visible = Not lblA.Visible
o lblEcart.Visible = Not lblEcart.Visible
o If txtDe.Visible = True Then
o Call DésactiverListeDéroulantes
o chkCollection = False
o chkRechercheLibre = False
o End If
o End Sub

o Private Sub chkTypeMusique_Click()


o cboTypeMusique.Visible = Not cboTypeMusique.Visible
o If cboTypeMusique.Visible = True Then Call DésactiverZonesTexte
o End Sub

o Private Sub chkRechercheLibre_Click()


o txtRechercheLibre.Visible = Not txtRechercheLibre.Visible
o If txtRechercheLibre.Visible = True Then
o Call DésactiverListeDéroulantes
o chkCollection = False
o chkPériode = False
o End If
o End Sub

o Private Sub chkCollection_Click()


o If chkCollection.Value = True Then
o chkPériode.Value = False
o chkRechercheLibre.Value = False
o Call DésactiverListeDéroulantes
o End If
o End Sub

o Private Sub DésactiverListeDéroulantes()


o chkAppréciation.Value = False
o chkCompositeur.Value = False
o chkInstrumentation.Value = False
o chkTypeMusique.Value = False
o chkInterprétation.Value = False
o End Sub

o Private Sub DésactiverZonesTexte()


o chkPériode.Value = False
o chkRechercheLibre.Value = False
o chkCollection.Value = False
o End Sub
s déroulantes dans formulaire de recherche

ce cas-là, il n'y aurait rien à faire. Il faut donc


que l'utilisateur clique sur le bouton OK.

recherche !", vbExclamation, "Message d'erreur"

ssurer que la liste déroulante ou la zone de texte


la zone de texte ou la liste déroulante correspondante

orie, et vice versa.


### Recherche d'un élément avec filtre

Nous vourdrions commencer par la collection particulière, car c'est la plus simple pour montrer comment nous désirons fair
Nous partons du principe que nous voudrions faire afficher tous les CD dont la remarques dans la feuille "Opera Omnia" co
caractère "Juju".

Par conséquent, nous avons étoffé la sous-routine cmdOK_Click() du formulaire frmRecherche comme suit :

o Private Sub cmdOK_Click()


o If ContrôleAuMoinsUneCaseACocherValide = True Then
o If chkCollection Then Call CollectionParticulière
o End If
o End Sub

La sous-routine CollectionParticulière() se trouve dans le module FormulaireRecherche avec le contenu suivan

o Sub CollectionParticulière()
o Dim Cell As Range
o 'Cette variable sert à placer le bouton de Retour au Menu au bon endroit
o Dim Lin As Long
o 'Cette variable se souvient si l'utilisateur a demandé un tri sur les
o 'compositeur, ceci avant que le formulaire soit refermé.
o Dim TriSurCompositeurs As Boolean
o
o TriSurCompositeurs = frmRecherche.optCompositeur
o
o Unload frmRecherche
o
o Worksheets("Opera Omnia").Activate
o Range("N2:N65536").Clear
o Range("A2").Select
o Do While ActiveCell.Value <> ""
o If ActiveCell.Offset(0, 10).Value <> "" Then
o Set Cell = ActiveCell.Offset(0, 10)
o
o 'Le If suivant génère une erreur si la cellule contient une chaîne mais que "
o 'n'est pas trouvé. En mettant On Error Resume Next, un VRAI est quand-même m
o 'dans la colonne 13 ce que nous voulons éviter. La parade, c'est de dire à l
o 'routine d'aller chercher sous l'étiquette :Erreur ce qu'il faut faire. A ce
o ' on fait sauter une ligne de code afin que le mot VRAI ne soit pas inscrit.
o On Error GoTo Erreur
o If Application.WorksheetFunction.Find("Juju", Cell) > 0 Then
o ActiveCell.Offset(0, 13).Value = 1
o 'On se souvient de combien d'occurences vont être trouvées
o Lin = Lin + 1
o
o Prochain:
L'utilisation de l'erreur géné
o End If
par la fonction Find est
o End If particulièrement intéressan
o dans ce code !
o ActiveCell.Offset(1, 0).Activate
o Loop
o
o Call FiltreAutomatique(14, 1, Lin, TriSurCompositeurs)
o
o Exit Sub
o
o Erreur:
o Resume Prochain
o End Sub

o Sub FiltreAutomatique(ByRef Col As Integer, Valeur As Integer, _


o Lin As Long, TriSurCompositeurs As Boolean)
o Selection.AutoFilter
o Selection.AutoFilter Field:=Col, Criteria1:=Valeur
o
o SendKeys ("^{HOME}")
o
o If TriSurCompositeurs Then
o Selection.Sort Key1:=Range("B2"), Order1:=xlAscending, _
o Key2:=Range("C2"), Order2:=xlAscending, _
o Header:=xlGuess, OrderCustom:=1, MatchCase:=False, _
o Orientation:=xlTopToBottom
o End If
o
o 'Le petit calcul qui suit permet de toujours mettre le bouton au
o 'bon endroit, sachant que la hauteur de ligne fait 12.75
o Sheets("Opera Omnia").cmdRetourMenu.Top = Lin * 12.75 + 20
o End Sub
comment nous désirons faire afficher certains CD.
s la feuille "Opera Omnia" contient la chaîne de

rche comme suit :

che avec le contenu suivant :

une chaîne mais que "Juju"


VRAI est quand-même marqué
de, c'est de dire à la sous-
'il faut faire. A cet endroit
ne soit pas inscrit.
L'utilisation de l'erreur générée
par la fonction Find est
particulièrement intéressante
dans ce code !
### Recherche de plusieurs éléments avec filtre

Nous voudrions à présent pouvoir faire un tri multiple sur plusieurs critères comme
dans l'exemple suivant. Il y a 5 listes déroulantes dans notre menu. Au moins une
doit être remplie pour cet exercice. Mais on peut s'imaginer vouloir faire un filtre sur
toutes les œuvres de J.-B. Bach pour clavecin solo.

Nous allons par conséquent encore étoffer la sous-routine suivante :

o Private Sub cmdOK_Click()


o Dim strBit As String
o
o If ContrôleAuMoinsUneCaseACocherValide = True Then
o If chkCollectionJuju Then Call CollectionParticulière
o
o 'Cette procédure construit une chaîne de caractères faite de 0 et de 1
o Call AnalyseDésires(strBit)
o
o 'Cette procédure exécute le filtre automatique en fonction de la chaîne de 0 e
o Call ExécutionDésires(strBit)
o
o End If
o
o End Sub

La première sous-routine qui suit construit une chaîne de caractères en écrivant de gauche à droite pour permettre une
C'est la raison pour laquelle on contrôle en premier la valeur de la case à cocher d'appréciation et en dernier le compos

o 'Précédure appelée par Private Sub cmdOK_Click()


o 'Cette procédure construit une chaîne de caractères faite de 0 et de 1
o Private Sub AnalyseDésires(ByRef strBit As String)
o If chkAppréciation Then strBit = "1" Else strBit = "0"
o If chkInterprétation Then strBit = strBit & "1" Else strBit = strBit & "0"
o If chkInstrumentation Then strBit = strBit & "1" Else strBit = strBit & "0"
o If chkTypeMusique Then strBit = strBit & "1" Else strBit = strBit & "0"
o If chkCompositeur Then strBit = strBit & "1" Else strBit = strBit & "0"
o End Sub

La deuxième sous-routine n'est qu'un énorme Select Case qui exécute le filtre automatique en fonction de la chaîne
construite dans la procédure précédente. La chaîne de caractères se lit de droite à gauche. Chaque "bit" allumé repré
l'activation de la case à cocher.

o 'Procédure appelée par Private Sub cmdOK_Click()


o 'Cette procédure exécute le filtre automatique en fonction de la chaîne de 0 et de 1
o Private Sub ExécutionDésires(ByRef strBit As String)
o Worksheets("Opera Omnia").Activate
o Range("A2").Select
o Selection.AutoFilter
o
o Select Case strBit
o Case "00001" 'colonne 2 par compositeur
o Call FiltreMultiple(0, "", 0, "", 0, "", 0, "", 2, cboCompositeurs)
o Case "00010" 'colonne 9 par type
o Call FiltreMultiple(0, "", 0, "", 0, "", 9, cboTypeMusique, 0, "")
o Case "00011"
o Call FiltreMultiple(0, "", 0, "", 0, "", 9, cboTypeMusique, 2, cboComposit
o Case "00100" 'colonne 7 par instrumentation
o Call FiltreMultiple(0, "", 0, "", 7, cboInstrumentation, 0, "", 0, "")
o Case "00101"
o Call FiltreMultiple(0, "", 0, "", 7, cboInstrumentation, 0, "", 2, cboComp
o Case "00110"
o Call FiltreMultiple(0, "", 0, "", 7, cboInstrumentation, 9, cboTypeMusique
o Case "00111"
o Call FiltreMultiple(0, "", 0, "", 7, cboInstrumentation, 9, cboTypeMusique
o Case "01000" 'colonne 8 par interprétation
o Call FiltreMultiple(0, "", 8, cboInterprétation, 0, "", 0, "", 0, "")
o Case "01001"
o Call FiltreMultiple(0, "", 8, cboInterprétation, 0, "", 0, "", 2, cboCompo
o Case "01010"
o Call FiltreMultiple(0, "", 8, cboInterprétation, 0, "", 9, cboTypeMusique,
o Case "01011"
o Call FiltreMultiple(0, "", 8, cboInterprétation, 0, "", 9, cboTypeMusique,
o Case "01100"
o Call FiltreMultiple(0, "", 8, cboInterprétation, 7, cboInstrumentation, 0,
o Case "01101"
o Call FiltreMultiple(0, "", 8, cboInterprétation, 7, cboInstrumentation, 0,
o Case "01110"
o Call FiltreMultiple(0, "", 8, cboInterprétation, 7, cboInstrumentation, 9,
o Case "01111"
o Call FiltreMultiple(0, "", 8, cboInterprétation, 7, cboInstrumentation, 9,
o Case "10000" 'colonne 12 par appréciation
o Call FiltreMultiple(12, cboAppréciation, 0, "", 0, "", 0, "", 0, "")
o Case "10001"
o Call FiltreMultiple(12, cboAppréciation, 0, "", 0, "", 0, "", 2, cboCompos
o Case "10010"
o Call FiltreMultiple(12, cboAppréciation, 0, "", 0, "", 9, cboTypeMusique,
o Case "10011"
o Call FiltreMultiple(12, cboAppréciation, 0, "", 0, "", 9, cboTypeMusique,
o Case "10100"
o Call FiltreMultiple(12, cboAppréciation, 0, "", 7, cboInstrumentation, 0,
o Case "10101"
o Call FiltreMultiple(12, cboAppréciation, 0, "", 7, cboInstrumentation, 0,
o Case "10110"
o Call FiltreMultiple(12, cboAppréciation, 0, "", 7, cboInstrumentation, 9,
o Case "10111"
o Call FiltreMultiple(12, cboAppréciation, 0, "", 7, cboInstrumentation, 9,
o Case "11000"
o Call FiltreMultiple(12, cboAppréciation, 8, cboInterprétation, 0, "", 0, "
o Case "11001"
o Call FiltreMultiple(12, cboAppréciation, 8, cboInterprétation, 0, "", 0, "
o Case "11010"
o Call FiltreMultiple(12, cboAppréciation, 8, cboInterprétation, 0, "", 9, c
o Case "11011"
o Call FiltreMultiple(12, cboAppréciation, 8, cboInterprétation, 0, "", 9, c
o Case "11100"
o Call FiltreMultiple(12, cboAppréciation, 8, cboInterprétation, 7, cboInstr
o Case "11101"
o Call FiltreMultiple(12, cboAppréciation, 8, cboInterprétation, 7, cboInstr
o Case "11110"
o Call FiltreMultiple(12, cboAppréciation, 8, cboInterprétation, 7, cboInstr
o Case "11111"
o Call FiltreMultiple(12, cboAppréciation, 8, cboInterprétation, 7, cboInstr
o Case Else
o MsgBox "Problème Select Case dans ExécutionDésires(strBit)"
o End Select
o
o End Sub

La sous-routine précédente fait à chaque Case appel à la sous-routine suivante :

o 'Procédure appelée par Private Sub ExécutionDésires(ByRef strBit As String)


o Private Sub FiltreMultiple(ByRef F1 As Integer, C1 As String, F2 As Integer
o F3 As Integer, C3 As String, F4 As Integer, C4 As String
o
o Dim TriSurCompositeurs As Boolean
o
o TriSurCompositeurs = frmRecherche.optCompositeur
o Unload frmRecherche
o
o 'Pour empêcher une erreur si rien n'est demandé, par exemple si on n'a demandé
o 'qu'un compositeur et rien d'autre
o On Error Resume Next
o
o 'On lance le filtre
o Selection.AutoFilter
o
o 'Les lignes suivantes font que si l'utilisateur a choisi p. ex. les compositeur,
o 'mais n'a rien spécifié, tous les compositeurs s'affichent.
o If C1 = "" Then Selection.AutoFilter Field:=F1 Else Selection.AutoFilter Field:=F1
o If C2 = "" Then Selection.AutoFilter Field:=F2 Else Selection.AutoFilter Field:=F2
o If C3 = "" Then Selection.AutoFilter Field:=F3 Else Selection.AutoFilter Field:=F3
o If C4 = "" Then Selection.AutoFilter Field:=F4 Else Selection.AutoFilter Field:=F4
o If C5 = "" Then Selection.AutoFilter Field:=F5 Else Selection.AutoFilter Field:=F5
o
o If TriSurCompositeurs Then
o Selection.Sort Key1:=Range("B2"), Order1:=xlAscending, _
o Key2:=Range("C2"), Order2:=xlAscending, _
o Header:=xlGuess, OrderCustom:=1, MatchCase:=False, _
o Orientation:=xlTopToBottom
o End If
o
o End Sub
de 0 et de 1

n de la chaîne de 0 et de 1

à droite pour permettre une concaténation.


tion et en dernier le compositeur.

= strBit & "0"


= strBit & "0"
trBit & "0"
trBit & "0"

ue en fonction de la chaîne de 0 et de 1
. Chaque "bit" allumé représente

chaîne de 0 et de 1
oCompositeurs)

sique, 0, "")

sique, 2, cboCompositeurs)

on, 0, "", 0, "")

on, 0, "", 2, cboCompositeurs)

on, 9, cboTypeMusique, 0, "")

on, 9, cboTypeMusique, 2, cboCompositeurs)

", 0, "", 0, "")

", 0, "", 2, cboCompositeurs)

", 9, cboTypeMusique, 0, "")

", 9, cboTypeMusique, 2, cboCompositeurs)

boInstrumentation, 0, "", 0, "")

boInstrumentation, 0, "", 2, cboCompositeurs)

boInstrumentation, 9, cboTypeMusique, 0, "")

boInstrumentation, 9, cboTypeMusique, 2, cboCompositeurs)

, 0, "", 0, "")

, 0, "", 2, cboCompositeurs)

, 9, cboTypeMusique, 0, "")

, 9, cboTypeMusique, 2, cboCompositeurs)

oInstrumentation, 0, "", 0, "")

oInstrumentation, 0, "", 2, cboCompositeurs)

oInstrumentation, 9, cboTypeMusique, 0, "")


oInstrumentation, 9, cboTypeMusique, 2, cboCompositeurs)

rétation, 0, "", 0, "", 0, "")

rétation, 0, "", 0, "", 2, cboCompositeurs)

rétation, 0, "", 9, cboTypeMusique, 0, "")

rétation, 0, "", 9, cboTypeMusique, 2, cboCompositeurs)

rétation, 7, cboInstrumentation, 0, "", 0, "")

rétation, 7, cboInstrumentation, 0, "", 2, cboCompositeurs)

rétation, 7, cboInstrumentation, 9, cboTypeMusique, 0, "")

rétation, 7, cboInstrumentation, 9, cboTypeMusique, 2, cboCompositeurs)

As String)
As Integer, C2 As String, _
eger, C4 As String, F5 As Integer, C5 As String)

si on n'a demandé

x. les compositeur,

.AutoFilter Field:=F1, Criteria1:=C1


.AutoFilter Field:=F2, Criteria1:=C2
.AutoFilter Field:=F3, Criteria1:=C3
.AutoFilter Field:=F4, Criteria1:=C4
.AutoFilter Field:=F5, Criteria1:=C5
:=False, _
### Recherche par période

Le bouton de recherche par période exige que nous reformations la sous-procédure ci-dessous :

o Private Sub cmdOK_Click()


o Dim strBit As String
o
o If ContrôleAuMoinsUneCaseACocherValide = True Then
o
o If chkCollectionJuju Then
o Call CollectionParticulière
o Else
o If chkPériode Then
o Call ParPériode
o Else
o If chkRechercheLibre Then
o 'Call RechercheLibre A faire dans prochaine feuille "Bout
o Else
o 'Cette procédure construit une chaîne de caractères faite de 0 et de
o Call AnalyseDésires(strBit)
o
o 'Cette procédure exécute le filtre automatique en fonction de la chaî
o Call ExécutionDésires(strBit)
o End If
o End If
o End If
o
o End If
o End Sub

Pour l'exécution du code qui suit, nous avons inséré la ligne suivante dans la section General de la procédure principale

o Public Const ECART = 50 'on choisit de donner 50 ans d'écart par défaut autour d'une date

o 'Procédure appelée par Private Sub cmdOK_Click()


o 'Cette procédure sert à analyser la période demandée, éventuellement dans un certain écar
o 'Si aucun écart n'est demandé, on prend un écart de 50 ans par défaut
o Private Sub ParPériode()
o Dim bolRempliJuste As Boolean
o
o bolRempliJuste = True
o 'Il ne peut y avoir que 4 cas où c'est juste : 000 , 100 , 101 , 110
o Call ContrôlePériode(bolRempliJuste)
o If bolRempliJuste = False Then Exit Sub
o
o Worksheets("Opera Omnia").Activate
o Range("A2").Activate
o
o If frmRecherche.txtDe.Value = "" And frmRecherche.txtA.Value = "" And frmRecherche.tx
o 'Cas 000
o Selection.AutoFilter
o Range("A2").Select
o Selection.AutoFilter Field:=4, Criteria1:="="
o Selection.AutoFilter Field:=5, Criteria1:="="
o Else
o If frmRecherche.txtDe.Value <> "" And frmRecherche.txtA.Value = "" And
o 'Cas 100, écart de ECART ans (défini dans procédure principale)
o Call FiltreElaboré(CInt(frmRecherche.txtDe.Value) - ECART, CInt(frmRecherche.
o Else
o If frmRecherche.txtDe.Value <> "" And frmRecherche.txtA.Value = ""
o 'Cas 101
o Call FiltreElaboré(CInt(frmRecherche.txtDe.Value) - CInt(frmRecherche.txt
o CInt(frmRecherche.txtDe.Value) + CInt(frmRecherche.txt
o Else
o 'Cas 110
o Call FiltreElaboré(CInt(frmRecherche.txtDe.Value), CInt(frmRecherche.txtA
o End If
o End If
o End If
o
o Unload frmRecherche
o End Sub

Si la procédure suivante se déroule sans que bolRempliJuste soit mis à False, c.-à-d. sans que l'utilisateur rentre une
procédure après celle-ci qui se déclenche.

o 'Cette sous-routine contrôle si l'utilisateur a été logique dans son choix de période(s)
o Private Sub ContrôlePériode(ByRef bolRempliJuste As Boolean)
o '000 JUSTE ! On avertit l'utilisateur qu'il va recevoir uniquement des compositio
o If frmRecherche.txtDe.Value = "" And frmRecherche.txtA.Value = "" And frmRecherche.tx
o MsgBox "Vous n'avez choisi aucune période." & vbCrLf & _
o "Vous allez obtenir tous les morceaux de date absolument inconnue."
o End If
o
o '001 FAUX
o If frmRecherche.txtDe.Value = "" And frmRecherche.txtA.Value = "" And frmRecherche.tx
o bolRempliJuste = False
o MsgBox "Vous n'avez rentré qu'un écart." & vbCrLf & _
o "C'est une impossibilité sans indiquer une date de début."
o Exit Sub
o End If
o
o '010 FAUX
o If frmRecherche.txtDe.Value = "" And frmRecherche.txtA.Value <> "" And frmRecherche.t
o bolRempliJuste = False
o MsgBox "Vous n'avez rentré qu'une date de fin." & vbCrLf & _
o "C'est une impossibilité sans indiquer une date de début."
o Exit Sub
o End If
o
o '011 FAUX
o If frmRecherche.txtDe.Value = "" And frmRecherche.txtA.Value <> "" And frmRecherche.t
o bolRempliJuste = False
o MsgBox "Vous avez rentré une période de fin ainsi qu'un écart." & vbCrLf & _
o "C'est une impossibilité ..."
o Exit Sub
o End If
o
o '100 JUSTE ! On averti l'utilisateur de l'écart par défaut.
o If frmRecherche.txtDe.Value <> "" And frmRecherche.txtA.Value = "" And frmRecherche.t
o MsgBox "Vous n'avez pas d'écart." & vbCrLf & _
o "L'écart par défaut autour de la période de début est de 50 ans."
o Exit Sub
o End If
o
o '101 JUSTE !
o ' If frmRecherche.txtDe.Value <> "" And frmRecherche.txtA.Value = "" And frmRecherche.
o ' Exit Sub
o ' End If
o
o '110 JUSTE !
o ' If frmRecherche.txtDe.Value <> "" And frmRecherche.txtA.Value <> "" And frmRecherche
o ' Exit Sub
o ' End If
o
o '111 FAUX
o If frmRecherche.txtDe.Value <> "" And frmRecherche.txtA.Value <> "" And frmRecherche.
o bolRempliJuste = False
o MsgBox "Vous avez rentré une période de début et de fin ainsi qu'un écart." & vbC
o "C'est une impossibilité ..."
o Exit Sub
o End If
o
o End Sub

L'utilisateur a rempli les champs de texte pour la période correctement. On peut procéder au filtre élaboré suivant :

o 'Sous-procédure appelée par Private Sub ParPériode()


o 'Sert à difinir les dates de début et de fin pour le filtre élaboré
o Private Sub FiltreElaboré(ByRef De As Integer, A As Integer)
o Range("AA2").Value = ">=" & CStr(De)
o Range("Ab2").Value = "<=" & CStr(A)
o Range("A1:N342").AdvancedFilter Action:=xlFilterInPlace, CriteriaRange:= _
o Range("AA1:AB2"), Unique:=False
o Range("A2").Select
o End Sub
dans prochaine feuille "Bouton Recherche 6"

res faite de 0 et de 1

n fonction de la chaîne de 0 et de 1

de la procédure principale :

aut autour d'une date de recherche

dans un certain écart.


" And frmRecherche.txtEcart.Value = "" Then

e = "" And frmRecherche.txtEcart.Value = "" Then

T, CInt(frmRecherche.txtDe.Value) + ECART)

Value = "" And frmRecherche.txtEcart.Value <> "" Then

CInt(frmRecherche.txtEcart.Value), _
CInt(frmRecherche.txtEcart.Value))

Int(frmRecherche.txtA.Value))

s que l'utilisateur rentre une ineptie, ce sera la

choix de période(s) et d'écart

uement des compositions non datées.


" And frmRecherche.txtEcart.Value = "" Then

ent inconnue."

" And frmRecherche.txtEcart.Value <> "" Then


"" And frmRecherche.txtEcart.Value = "" Then

"" And frmRecherche.txtEcart.Value <> "" Then

t." & vbCrLf & _

"" And frmRecherche.txtEcart.Value = "" Then

de 50 ans."

"" And frmRecherche.txtEcart.Value <> "" Then

> "" And frmRecherche.txtEcart.Value = "" Then

"" And frmRecherche.txtEcart.Value <> "" Then

i qu'un écart." & vbCrLf & _

ltre élaboré suivant :


aRange:= _
### Recherche libre

Nous finissons ce chapitre de recherche en activant la ligne de code désactivée de Private Sub cmdOK_Click()

o Private Sub cmdOK_Click()


o Dim strBit As String
o
o If ContrôleAuMoinsUneCaseACocherValide = True Then
o
o If chkCollectionJuju Then
o Call CollectionParticulière
o Else
o If chkPériode Then
o Call ParPériode
o Else
o If chkRechercheLibre Then
o Call RechercheLibre(txtRechercheLibre)
o Else
o 'Cette procédure construit une chaîne de caractères faite de 0 et de
o Call AnalyseDésires(strBit)
o
o 'Cette procédure exécute le filtre automatique en fonction de la chaî
o Call ExécutionDésires(strBit)
o End If
o End If
o End If
o
o End If
o End Sub

L'idée est la suivante : l'utilisateur voudrait faire une recherche sur un mot clé, mais ne sachant pas très bien où il se trouve
trois colonnes : les œuvres, l'interprétation et les remarques ; ce sont là les seuls champs où on peut rentrer un peu n'impo
dans ces champs s'apparente beaucoup à la recherche que nous avons fait pour une colleciton particulière.

o 'Procédure appelée par Private Sub cmdOK_Click()


o 'Cette procédure recherche un mot clé dans trois colonnes :
o 'les oeuvres, les interprétations, les remarques
o 'puis un filtre automatique est fait pour afficher les morceaux désirés
o Private Sub RechercheLibre(ByRef MotClé As String)
o Dim Cell As Range
o 'Cette variable sert à placer le bouton de Retour au Menu au bon endroit
o Dim Lin As Long
o 'Cette variable se souvient si l'utilisateur a demandé un tri sur les
o 'compositeur, ceci avant que le formulaire soit refermé.
o Dim TriSurCompositeurs As Boolean
o Dim bolTrouvéUneOccurence As Boolean
o
o bolTrouvéUneOccurence = False
o
o TriSurCompositeurs = frmRecherche.optCompositeur
o
o Unload frmRecherche
o
o Worksheets("Opera Omnia").Activate
o Range("N2:N65536").Clear
o Range("A2").Select
o Do While ActiveCell.Value <> ""
o '1.) Colonne 6 des oeuvres
o Set Cell = ActiveCell.Offset(0, 5)
o
o 'La deuxième partie du If suivant génère une erreur si la cellule contient une ch
o 'que le mot clé n'est pas trouvé. En mettant On Error Resume Next, un VRAI est q
o 'même marqué dans la colonne 13 ce que nous voulons éviter. La parade, c'est de
o 'à la sous-routine d'aller chercher sous l'étiquette :Erreur ce qu'il faut faire.
o 'cet endroit on fait sauter une ligne de code afin que le mot VRAI ne soit pas in
o On Error GoTo Erreur_1
o If Cell.Value <> "" And Application.WorksheetFunction.Find(MotClé, Cell) > 0
o ActiveCell.Offset(0, 13).Value = 1
o bolTrouvéUneOccurence = True
o Lin = Lin + 1
o Prochain_1:
o End If
o
o 'Il ne vaut la peine de continuer la recherche que si aucune occurence n'a été tr
o 'dans la colonne des oeuvres
o If bolTrouvéUneOccurence = False Then
o '2.) Colonne 8 des interprètes
o Set Cell = ActiveCell.Offset(0, 7)
o
o On Error GoTo Erreur_2:
o If Cell.Value <> "" And Application.WorksheetFunction.Find(MotClé, Cell) > 0
o ActiveCell.Offset(0, 13).Value = 1
o bolTrouvéUneOccurence = True
o Lin = Lin + 1
o Prochain_2:
o End If
o End If
o
o 'Il ne vaut la peine de continuer la recherche que si aucune occurence n'a été tr
o 'dans la colonne des interprétations
o If bolTrouvéUneOccurence = False Then
o '3.) Colonne 11 des remarques
o Set Cell = ActiveCell.Offset(0, 10)
o
o On Error GoTo Erreur_3:
o If Cell.Value <> "" And Application.WorksheetFunction.Find(MotClé, Cell) > 0
o ActiveCell.Offset(0, 13).Value = 1
o bolTrouvéUneOccurence = True 'Cette ligne est en fait inutile
o Lin = Lin + 1
o Prochain_3:
o End If
o End If
o
o ActiveCell.Offset(1, 0).Activate
o 'Remise à False pour la prochaine ligne
o bolTrouvéUneOccurence = False
o Loop
o
o Call FiltreAutomatique(14, 1, Lin, TriSurCompositeurs)
o
o Exit Sub
o
o Erreur_1:
o Resume Prochain_1
o Erreur_2:
o Resume Prochain_2
o Erreur_3:
o Resume Prochain_3
o End Sub
Sub cmdOK_Click() dans la feuille Bouton Recherche 5.

res faite de 0 et de 1

n fonction de la chaîne de 0 et de 1

pas très bien où il se trouve. Cela concerne


n peut rentrer un peu n'importe quoi. La recherche
n particulière.
llule contient une chaîne
e Next, un VRAI est quand-
La parade, c'est de dire
ce qu'il faut faire. A
t VRAI ne soit pas inscrit.

otClé, Cell) > 0 Then

occurence n'a été trouvée

nd(MotClé, Cell) > 0 Then

occurence n'a été trouvée


nd(MotClé, Cell) > 0 Then

n fait inutile
Améliorations au formulaire de recherche

Mis en ordre du code


Nous avons mis du code aussi bien dans le module principal que dans le code rattaché aux formulaires.
Le code de formulaire contient à présent aussi bien du code événementiel que du code non événementiel. Il convient
le code de formulaire que du code événementiel. Nous allons donc créer un module que nous nommerons
contiendra tout le code non événementiel rattaché au formulaire de recherche.

Les sous-routines suivantes doivent être transférées dans le module FormulaireRecherche :

Private Sub RechercheLibre(ByRef MotClé As String)


Private Sub ExécutionDésires(ByRef strBit As String)
Private Sub FiltreMultiple(ByRef F1 As Integer, C1 As String, F2 As Integer
C3 As String, F4 As Integer, C4 As String, F5 As Integer
Private Sub ParPériode()
Private Sub FiltreElaboré(ByRef De As Integer, A As Integer)
Private Sub ContrôlePériode(ByRef bolRempliJuste As Boolean)
Private Sub DésactiverListeDéroulantes()
Private Sub DésactiverZonesTexte()
Private Sub AnalyseDésires(ByRef strBit As String)

Les sous-routines suivantes doivent être transférées depuis le module FonctionnementClasseur vers le module

Sub RemplirListeDéroulante(ByRef frm As String, sh As String, rge As String


Sub ContrôleAuMoinsUneCaseACocherValide()
Sub CollectionParticulière()
Sub FiltreAutomatique(ByRef Col As Integer, Valeur As Integer, _
Lin As Long, TriSurCompositeurs As Boolean)

Vous devrez sans doute faire quelques ajustement en rajoutant la chaîne de


caractère "frmRecherche." devant les objets faisant partie de ce formulaire…

De plus, tous les Private dans les modules doivent disparaître !

Les sous-routines qui restent dans le formulaire frmRecherche sont les suivantes :

Private Sub UserForm_Activate()


Private Sub chkAppréciation_Click()
Private Sub chkCollectionJuju_Click()
Private Sub chkCompositeur_Click()
Private Sub chkInstrumentation_Click()
Private Sub chkInterprétation_Click()
Private Sub chkPériode_Click()
Private Sub chkTypeMusique_Click()
Private Sub chkRechercheLibre_Click()
Private Sub cmdAnnuler_Click()
Private Sub cmdOK_Click()
Testez soigneusement votre programme ! Il vous faudra plusieurs mois pour
stabiliser, sans compter les erreurs de saisie dans certaines feuilles !

Placer le curseur au bon endroit avec la méthode SetFocus


Lorsque l'utilisateur clique sur une case à cocher affublée d'une zone de texte, il serait sympatique que le curseur se tr
cette zone de texte sans que l'utilisateur ait besoin de cliquer dedans. Voici les changements apportés :

o Private Sub chkRechercheLibre_Click()


o txtRechercheLibre.Visible = Not txtRechercheLibre.Visible
o If txtRechercheLibre.Visible = True Then
o Call DésactiverListeDéroulantes
o chkCollectionJuju = False
o chkPériode = False
o
o txtRechercheLibre.SetFocus
o End If
o End Sub

o Private Sub chkPériode_Click()


o txtDe.Visible = Not txtDe.Visible
o txtA.Visible = Not txtA.Visible
o txtEcart.Visible = Not txtEcart.Visible
o lblDe.Visible = Not lblDe.Visible
o lblA.Visible = Not lblA.Visible
o lblEcart.Visible = Not lblEcart.Visible
o If txtDe.Visible = True Then
o Call DésactiverListeDéroulantes
o chkCollectionJuju = False
o chkRechercheLibre = False
o
o txtDe.SetFocus
o End If
o End Sub

Permettre la recherche, quelle que soit la capitalisation


Il est gênant de devoir rentrer une chaîne de caractère avec la capitalisation exacte. Ainsi, si vous essyez de rentrer "c
le programme ne trouve rien. C'est la raison pour laquelle il convient de changer la fonction Find (TROUVE) utilisée d
RechercheLibre(ByRef MotClé As String) et CollectionParticulière() par la fonction Search

Remplissage d'une liste déroulante simplifiée


Vous pouvez sensiblement améliorer votre code de remplissage des listes déroulantes de la façon suivante :

o Private Sub UserForm_activate()


o Application.ScreenUpdating = False
o Call RemplirListeDéroulante(Me, "Compositeurs", RANGE_COMPOSITEURS, "cboCompositeu
o Call RemplirListeDéroulante(Me, "Appréciation", RANGE_APPRECIATION, "cboAppréciati
o Call RemplirListeDéroulante(Me, "Instrumentation", RANGE_INSTRUMENTATION, "cboInst
o Call RemplirListeDéroulante(Me, "Interprétation", RANGE_INTERPRETATION, "cboInterp
o Call RemplirListeDéroulante(Me, "Type de musique", RANGE_TYPE_MUSIQUE, "cboTypeMus
o Worksheets("Menu").Select
o Application.ScreenUpdating = True
o End Sub

o 'Sous-routine servant remplir les différentes listes déroulantes


o 'Sous-routine appelée par UserForm_Activate() aussi bien dans le formulaire
o frmRecherche que frmNouveauCD.
o 'Amélioration aimablement transmise par Pascal Pannatier.
o Sub RemplirListeDéroulante(ByRef frm As UserForm, sh As String, rge As String
o Worksheets(sh).Activate
o frm.Controls(cbo).RowSource = Worksheets(sh).Range(rge).Address
o End Sub
formulaires.
événementiel. Il convient de ne laisser dans
ous nommerons FormulaireRecherche qui

As Integer, C2 As String, F3 As Integer, _


F5 As Integer, C5 As String)

asseur vers le module FormulaireRecherche :

As String, cbo As String)


lusieurs mois pour le
es feuilles !

patique que le curseur se trouve tout de suite dans


ts apportés :

si vous essyez de rentrer "cri" au lieu de "Cri",


Find (TROUVE) utilisée dans les procédures
la fonction Search (CHERCHE).

a façon suivante :

TEURS, "cboCompositeurs")
ATION, "cboAppréciation")
RUMENTATION, "cboInstrumentation")
PRETATION, "cboInterprétation")
_MUSIQUE, "cboTypeMusique")

formulaire

ge As String, cbo As String)