Peaufiner un fonction de recherche dans un TABLO()

dionys0s

XLDnaute Impliqué
Salut le forum,

Ces temps-ci, j'apprends de plus en plus à travailler dans des variables tableau (plages passées en RAM), et j'essaye de mettre un point une fonction le plus générique possible (et jolie et propre et courte et etc.) pour faire des recherches et remplacer la fonction .Find qui je trouve est bien lente quand elle est utilisée fréquemment dans un programme (quelques tests m'ont fait éprouver les différences de rapidités : elles sont manifestes !)

Donc voici la fonction :

En tête de module, j'ai placé ceci :
VB:
Option Explicit
Option Base 1
Option Compare Binary

Enum Recherche
    Verticale = xlVertical
    Horizontale = xlHorizontal
End Enum

Enum Regarde
    Tout = xlWhole
    Partie = xlPart
End Enum

Et dans le code :
VB:
Function Trouve(ByRef TABLO As Variant, ByVal Depart As Long, ByVal Arrivee As Long, _
                ByVal Orientation As Integer, ByVal Rang As Integer, ByVal Valeur As String, _
                ByVal RespectCasse As Boolean, ByVal Precision As Integer, _
                Optional ByVal Saut As Integer = 1) As Integer
'TABLO est forcément en 2D
'Depart : ligne ou colonne de départ de la recherche
'Arrivee : ligne ou colonne limite de la recherche
'Orientation : recherche verticale ou horizontale
'Rang : rang de la colonne de recherche (si recherche verticale) ou de la ligne de recherche (si etc.)
'Valeur : valeur recherchée
'RespectCasse : respecter la casse ou non
'Partie : la valeur doit-elle être tout ou partie de la "case" recherchée
'Saut : recherche sur tous les rangs (1), un rang sur 2 (2), ou sur 3 (3), etc...

    Dim ValTest As String, i As Long, j As Long

    'Ici, une fonction de vérification du nombre de dimensions de TABLO est intégrée,
    'mais je l'ai enlevée ici pour alléger le code

    'Modification ou non de la valeur recherchée suivant le paramètre RespectCasse
    If RespectCasse = False Then Valeur = LCase(Valeur)

    Select Case Orientation

        Case Recherche.Verticale

            Select Case Precision

                Case Regarde.Tout
                    For i = Depart To Arrivee Step Saut
                        If RespectCasse = False Then ValTest = LCase(TABLO(i, Rang))
                        If ValTest = Valeur Then
                            Trouve = i
                            Exit Function
                        End If
                    Next i

                Case Regarde.Partie
                    For i = Depart To Arrivee Step Saut
                        If RespectCasse = False Then ValTest = LCase(TABLO(i, Rang))
                        If InStr(1, ValTest, Valeur, vbTextCompare) <> 0 Then
                            Trouve = i
                            Exit Function
                        End If
                    Next i

            End Select

        Case Recherche.Horizontale

            Select Case Precision

                Case Regarde.Tout
                    For j = Depart To Arrivee Step Saut
                        If RespectCasse = False Then ValTest = LCase(TABLO(Rang, j))
                        If ValTest = Valeur Then
                            Trouve = j
                            Exit Function
                        End If
                    Next j

                Case Regarde.Partie
                    For j = Depart To Arrivee Step Saut
                        If RespectCasse = False Then ValTest = LCase(TABLO(Rang, j))
                        If InStr(1, ValTest, Valeur, vbTextCompare) <> 0 Then
                            Trouve = j
                            Exit Function
                        End If
                    Next j

            End Select

    End Select

End Function

Ma question est donc la suivante : y a-t-il un moyen de raccourcir ce code ? J'ai l'impression qu'on pourrait le raccourcir assez fortement, notamment la manière que j'ai de gérer le paramètre Orientation. En effet, ce qui se trouve sous 'Recherche.Horizontale' et 'Recherche.Verticale' dans le code est quasi identique : il faut juste placer Rang au bon endroit dans les coordonnées de la case inspectée.

Je continue de chercher, mais je suis preneur de toute idée.

D'avance merci pour votre aide

dionys0s
 

dionys0s

XLDnaute Impliqué
Re : Peaufiner un fonction de recherche dans un TABLO()

Re le forum,

bon j'ai pondu un code bien plus court, mais dont le temps d'exécution est un peu plus long, puisqu'il réexamine certains paramètres à chaque passage dans la boucle :

En tête de module :
VB:
Option Explicit
Option Base 1
Option Compare Binary

Enum Recherche
    Verticale = xlVertical
    Horizontale = xlHorizontal
End Enum

Enum Regarde
    Tout = xlWhole
    Partie = xlPart
End Enum

Enum Casse
    Vrai = vbBinaryCompare
    Faux = vbTextCompare
End Enum

Et la fonction :
VB:
Function Trouve(ByRef TABLO As Variant, ByVal Depart As Long, ByVal Arrivee As Long, _
ByVal Orientation As Integer, ByVal Rang As Integer, ByVal Valeur As String, _
ByVal RespectCasse As Integer, ByVal Precision As Integer, _
Optional ByVal Saut As Integer = 1) As Integer

    Dim ValTest As String, i As Long, j As Long, k As Long
    Dim TestOK As Boolean

    'Modification ou non de la valeur suivant le paramètre RespectCasse
    If RespectCasse = vbTextCompare Then Valeur = LCase(Valeur)

    For k = Depart To Arrivee
        TestOK = False
        Select Case Orientation
            Case Recherche.Verticale
                i = k
                j = Rang
            Case Recherche.Horizontale
                i = Rang
                j = k
        End Select
        ValTest = TABLO(i, j)
        If RespectCasse = vbTextCompare Then ValTest = LCase(ValTest)
        If Precision = Regarde.Tout Then 
            TestOK = ValTest = Valeur
        Else
            TestOK = InStr(1, ValTest, Valeur, RespectCasse) <> 0
        End If
        If TestOK = True Then Trouve = k: Exit Function
    Next k

End Function

Je le soumets à votre jugement, et suis preneur de toute suggestion pour l'éméliorer.

Good day all

dionys0s
 
Dernière édition:

dionys0s

XLDnaute Impliqué
Re : Peaufiner un fonction de recherche dans un TABLO()

Bonjour Efgé

Le problème de la fonction .Match est qu'il ne s'agit pas d'une fonction VBA à proprement parler, mais d'une fonction Excel qui s'utilise avec Application.WorksheetFunction. J'ai fait des tests il y a quelques temps déjà pour comparer la rapidité des différentes méthodes, et manipuler directement la variable tableau est beaucoup plus rapide (ce lien me l'avait confirmé).

Quand à la solution proposée un peu après (création d'un objet scripting.dictionnary), je n'y ai pas accès ne travaillant pas sur un PC mais sur un Mac.

Mais cette page est géniale et m'avait été d'une très grande aide pour l'élaboration d'une fonction de QuickSort.
 

Discussions similaires

Statistiques des forums

Discussions
314 647
Messages
2 111 533
Membres
111 192
dernier inscrit
F.Venne