Optimisation de la création d’un filtre VBA.

Publié le par Raymond

Sur un formulaire d’interrogation vous avez disposé sept contrôles, texte ou combo ou cases à cocher, pour sélectionner des enregistrements selon un filtre composé des sept éléments si ceux-ci contiennent une valeur. Si un contrôle est Null, il n’entre pas dans le filtre. Vous faîtes donc une fonction, appelée dans tous les événements AfterUpdate des sept contrôles, qui génère et applique le filtre.
La façon la plus simple est d’utiliser des instructions If qui testent la valeur Null de ces contrôle :
Private Function loadFilter()
    Dim myFilter as String
    myFilter = ""
    If Not IsNull(Me!f_num) Then
        myFilter = myFilter & "[cli_code]= '" & Me!f_num & "' and "
    End If
    If Not IsNull(Me!f_lib) Then
        myFilter = myFilter & "[cli_rais] like '" & Me!f_lib & "' and "
    End If
    If Not IsNull(Me!f_nom) Then
        myFilter = myFilter & "[cli_nom] like '" & Me!f_nom & "' and "
    End If
    If Not IsNull(Me!f_vil) Then
        myFilter = myFilter & "[cli_vil]= '" & Me!f_vil & "' and "
    End If
    If Not IsNull(Me!f_pays) Then
        myFilter = myFilter & "[cli_pays]= '" & Me!f_pays & "' and "
    End If
    If Not IsNull(Me!f_rep) Then
        myFilter = myFilter & "[cli_rep]= '" & Me!f_rep & "' and "
    End If
    If Not IsNull(Me!f_sect) Then
        myFilter = myFilter & "[cli_secteur]= " & Me!f_sect & " and "
    End If
    If myFilter <> "" Then
        Me.Filter = Left$(myFilter, Len(myFilter) - 4)
        Me.FilterOn = True
    Else
        Me.Filter = ""
        Me.FilterOn = False
    End If
End Function
 
Vous pouvez commencer par réduire le code de cette fonction ainsi :
Private Function loadFilter()
    Dim myFilter As String
    myFilter = ""
    If Not IsNull(Me!f_num) Then myFilter = myFilter & "[cli_code]= '" & Me!f_num & "' and "
    If Not IsNull(Me!f_lib) Then myFilter = myFilter & "[cli_rais] like '" & Me!f_lib & "' and "
    If Not IsNull(Me!f_nom) Then myFilter = myFilter & "[cli_nom] like '" & Me!f_nom & "' and "
    If Not IsNull(Me!f_vil) Then myFilter = myFilter & "[cli_vil]= '" & Me!f_vil & "' and "
    If Not IsNull(Me!f_pays) Then myFilter = myFilter & "[cli_pays]= '" & Me!f_pays & "' and "
    If Not IsNull(Me!f_rep) Then myFilter = myFilter & "[cli_rep]= '" & Me!f_rep & "' and "
    If Not IsNull(Me!f_sect) Then myFilter = myFilter & "[cli_secteur]= " & Me!f_sect & " and "
    If myFilter <> "" Then
        Me.Filter = Left$(myFilter, Len(myFilter) - 4)
        Me.FilterOn = True
    Else
        Me.Filter = ""
        Me.FilterOn = False
    End If
End Function
Ce qui n'apportera qu'un gain de place sur l'écran. 
Mais, surtout, vous pouvez modifier le code, non seulement en le réduisant mais en l’optimisant, en appliquant les expressions conditionnelles de la propagation Null :
Private Function loadFilter()
    Dim myFilter As String
    myFilter = ""
    myFilter = myFilter & ("[cli_code]= '" + Me!f_num + "' and ")
    myFilter = myFilter & ("[cli_rais] like '" + Me!f_lib + "' and ")
    myFilter = myFilter & ("[cli_nom] like '" + Me!f_nom + "' and ")
    myFilter = myFilter & ("[cli_vil]= '" + Me!f_vil + "' and ")
    myFilter = myFilter & ("[cli_pays]= '" + Me!f_pays + "' and ")
    myFilter = myFilter & ("[cli_rep]= '" + Me!f_rep + "' and ")
    myFilter = myFilter & ("[cli_secteur]= " + Me!f_sect + " and ")
    If myFilter <> "" Then
        Me.Filter = Left$(myFilter, Len(myFilter) - 4)
        Me.FilterOn = True
    Else
        Me.Filter = ""
        Me.FilterOn = False
    End If
End Function
L’opérateur + placé dans les expressions conditionnelles indique de retourner une valeur Null pour l’expression entière si un de ses membres est Null. Donc si le champ de sélection est Null, toute l’expression sera null et rien ne sera ajouté dans myFilter. Non seulement vous économisez du code mais vous gagnez beaucoup de temps d’exécution.
Explications sur la propagation Null : http://officesystem.access.over-blog.com/article-15664382.html
 
 

Publié dans Astuces

Commenter cet article

Snoopy 28/03/2012 11:13

Bonjour Raymond,

Merci beaucoup pour cet article fort intéressant qui m'a permis de résoudre mon problème de filtre multicritères.

Juste une question supplémentaire : je dois également filtrer sur une date (Between date_debut and date_fin).

J'ai formaté les dates de référence en format américain et introduit les "#" :

myFilter = myFilter & ("[MISSION_DATE] BETWEEN #" + Format(Forms!F_SELECTION_RECHERCHE!date_debut, "dd/mm/yyyy") + "# AND #" + Format(Forms!F_SELECTION_RECHERCHE!date_fin, "dd/mm/yyyy") + "#
and ")

mais j'obtiens un message d'erreur : "Erreur d'exécution 3075 / Erreur de syntaxe dans la date dans l'expression "[MISSION_DATE] BETWEEN #01.01.2012# AND #30.03.2012# ".

Merci de votre aide !

Snoopy

Naphta 11/05/2008 17:09

Bonjour,
Si je puis me permettre,
un tableau dont la taille dépend du nombre de critère ?
en plus si on y ajoute 1 dimension on y colle des commentaires
je ne l'ai jamais vu proposé c'est pourtant cool les tableaux!!
A+