IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Macros et VBA Excel Discussion :

Problème étrange Méthode Find() [XL-2010]


Sujet :

Macros et VBA Excel

  1. #1
    Membre averti
    Homme Profil pro
    Inscrit en
    Mars 2012
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mars 2012
    Messages : 27
    Par défaut Problème étrange Méthode Find()
    Bonjour à tous,

    Bon après avoir perdu bon nombre d'heures à me pencher sur le problème en vain et avoir épluché pas mal de discussions, je me décide à vous demander de l'aide parce que j'ai un problème très étrange avec la méthode Find (.Find(what:= etc) et je bloque.
    Je ne peux poster ni fichier ni code complet car je pense que ça embrouillerait tout le monde d'avoir le projet complet, le code est assez long et écrit bizarrement sans doute.
    Je tente donc de l'expliquer le plus clairement possible au niveau conceptuel:

    Le problème se pose dans une base de données, composée de:
    • Colonne 1: Un numéro qui s'étend sur plusieurs lignes [appelons le range "numéro"], qui passe ensuite à un autre numéro sur plusieurs lignes à son tour.
    • Colonne 2: Une lettre allant de A à Z (appelons le range [lettre], à l'intérieur du range(numéro).
    • Colonne 3,4 jusque 10, des données quelconques qui doivent être déplacées.


    Nous avons donc un range "numéro" de 75 lignes (par exemple), à l'intérieur duquel se succède en colonne 2 donc un range "lettre" A (15 lignes), ensuite B (15 lignes) etc etc.
    Ce qui donne (en très simplifié):
    Nom : colonne.JPG
Affichages : 263
Taille : 20,0 Ko


    Et ainsi de suite, les numéros vont jusqu'à 40, et il y a jusque 20 lettre différentes à l'intérieur d'un range "numéro".
    A côté de ces deux colonnes se trouvent des données associées quelconques (qui ne servent pas à identifier).

    L'idée c'est que le script aille chercher dans le database si le numéro cherché est présent (ex:1), une fois trouvé, il définit un Range de la première à la dernière ligne contenant ce numéro, et ira ensuite chercher à l'intérieur de ce range la lettre choisie (ex:B, à l'intérieur de 1). La raison de ces étapes et que je ne veux pas qu'il trouve B dans range(2) mais B dans range(1) et prendre ces données là précisemment. C'est la raison pour laquelle une premier range est préalablement définit, pour ensuite y effectuer une recherche avec Find(whatetc.

    Mon problème est le suivant:
    Je définit le range(numéro), imaginons de 2 à 450. A l'intérieur duquel on trouve le range(lettres) qui est plus courts, exemple: range(1B = ligne 2 jusque 10, 1C = ligne 11 jusque 26) et ainsi de suite.
    Mais en définissant ce second range, il semble que la recherche démarre après le première cellule du range (si le range démarre à B250, la première occurence trouvée sera minimum B251, même si en B250 la donnée y est également.
    Constatant cela, j'ai décalé le début de la recherche à Range(ligne - 1), afin qu'il démarre la recherche sur la première ligne du range.
    Cela fonctionne jusque...à ce qu'on arrive à la dernière lettre cherchée, qui est également la lettre présente dans Range(ligne - 1)! (les séquences de lettres se succèdent dans le même ordre, donc après 1Z, on trouvera 2A, et ainsi de suite). Le script cherchant Z, il le trouve dans Range(ligne - 1) et me colle donc les données ici.

    Je pense avoir trouvé la raison mais elle est incensée! Quand le script se met à chercher, il cherche à partir de la ligne 2 en gros, mais s'il ne trouve rien, il revient quand même à la ligne 1 et là trouve ma donnée. Pourquoi cela ne fonctionnait pas avec le premier cas ? Car en cherchant dès la ligne 2, il trouve la donnée! (la lettre va de ligne 1 à ligne 5 par exemple) donc se dit 'ok j'ai trouvé' et n'a donc pas besoin de venir checker en arrière. Or pour la dernière lettre (1Z), il ne la trouve pas et revient sur Range(ligne - 1) et là la trouve (mais elle est hors-range!).

    Ma question est donc: y'a-t-il un moyen de définir un range, de commencer à chercher dès la première ligne du range, sans avoir recours au ligne-1 qui le fait sortir du range ?
    Est-ce si illogique que ça de vouloir chercher dès la première ligne du range ?

    Je sais je pourrai faire un controle à côté de la lettre pour voir si le numéro correspond mais cela me semble absurde qu'aucun code ne fonctionne sans ce controle qui n'a pas de sens.

    D'avance merci à vous qui avez pris la peine de lire, j'espère avoir un minimum expliquer mon problème...j'ai essayé d'être le plus clair possible.
    En espérant vous lire

    LeSmoox

  2. #2
    Expert éminent Avatar de Menhir
    Homme Profil pro
    Ingénieur
    Inscrit en
    Juin 2007
    Messages
    16 037
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 16 037
    Par défaut
    Pourquoi ne pas revenir aux fondamentaux en remplaçant tes Find compliqués par une simple combinaison de For to et de If.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    For Lig = 1 to Range("A1").End(xlDown.Row
        If Cells(Lig,1).Value = MonNumero And Cells(Lig,2) = MaLettre Then
     
     
        End If
    Next Lig
    Tu perdrais sans doute en rapidité d'exécution mais tu gagnerais en vitesse de conception.

  3. #3
    Membre averti
    Homme Profil pro
    Inscrit en
    Mars 2012
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mars 2012
    Messages : 27
    Par défaut
    Bonjour Menhir,

    Merci pour la réponse. Oui j'y ai pensé, le problème c'est que cette macro fait partie d'un script assez long et varié qui contient beaucoup d'autres macro et qui est déjà très lourd à faire tourner.
    La méthode avec If est en effet plus facile à utiliser mais elle ralentirait encore plus l'exécution, c'est pourquoi j'ai privilégié Find() qui me semblait fonctionner rès bien jusqu'à ce problème.

    Il s'agissait également de comprendre ce problème qui me semble tout simplement absurde...
    Si je ne trouve aucune solution je serais bien obligé de repasser aux If mais j'espérais trouver.

    Salutations

  4. #4
    Expert éminent Avatar de Menhir
    Homme Profil pro
    Ingénieur
    Inscrit en
    Juin 2007
    Messages
    16 037
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 16 037
    Par défaut
    Tu peux accélérer le code en commençant par un Find qui te permette de commencer le For to à une ligne plus appropriée que la première.

    Ensuite, tu pourrais avoir une variable binaire utilisée comme drapeau que tu mets à 1 quand tu as trouvé la première ligne et si cette variable est à 1 mais que les conditions ne sont plus remplies, faire un Exit For, ce qui t'évite de scruter des lignes inutiles.

  5. #5
    Membre averti
    Homme Profil pro
    Inscrit en
    Mars 2012
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mars 2012
    Messages : 27
    Par défaut
    Oui j'ai simplement ajouté un controle une fois l'occurence trouvée, il faut que la le 'numéro' corresponde.
    Cela dit, si quelqu'un connait la raison de ce problème précisément, et comment le résoudre sans le contourner je suis preneur car ça n'a aucun sens, il doit y avoir une explication.

    Merci Mehnir

  6. #6
    Invité
    Invité(e)
    Par défaut
    Salut,

    Pour la recherche avec Find, c'est expliqué dans l'aide:

    expression .Find(What, After, LookIn, LookAt, SearchOrder, SearchDirection, MatchCase, MatchByte, SearchFormat)

    Paramètres:
    Nom Obligatoire/Facultatif Type de données Description
    ... ... ... ...
    After Facultatif Variant Cellule après laquelle vous souhaitez commencer la recherche. Elle correspond à la position de la cellule active quand une recherche est lancée à partir de l'interface utilisateur. Notez que le paramètre After doit désigner une cellule unique dans la plage, et que la recherche commence après cette cellule qui n'est analysée que quand la méthode y revient après avoir analysé les autres cellules. Si vous ne définissez pas cet argument, la recherche commence après la cellule figurant dans l'angle supérieur gauche de la plage.
    ... ... ... ...
    Lorsque tu utilise Find, il faut définir tous ces paramètres (regarde dans l'aide).
    Méthode Range.Find (Excel) - MSDN

  7. #7
    Membre averti
    Homme Profil pro
    Inscrit en
    Mars 2012
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mars 2012
    Messages : 27
    Par défaut
    Oui, sauf que (je crois que je me suis mal exprimé dans le premier post en fait), la valeur cherchée est trouvable sans revenir en arrière! Ce qui veut dire qu'il ne devrait pas revenir en arrière pour chercher dans la première cellule qu'il avait ignoré, mais il devrait la trouver dans le range définit (vérifié et revérifié)! C'est comme si en cherchant A, il commençait à la deuxième cellule, mais en cherchant Z, il commence dès la première cellule (qui est ligne -1)! Z est bel et bien trouvable dans le range, à la fin, mais dans le range quand même! Bref merci pour l'aide mais j'avais déjà lu l'explication justement

  8. #8
    Invité
    Invité(e)
    Par défaut
    Je te donne un petit exemple qui recherche le mot bonjour dans la partie Value d'un Range plutôt que la partie Formula.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    ' Recherche la 1ère occurence du mot "Bonjour" en tant que valeur
    ' dans la 1ère colonne d'une feuille en partant de la 1ère cellule.
     
    Sub TestFind()
        Dim Rng As Range
        Feuil2.Range("A2,A5,B1,B7").Formula = "= ""Bon"" & ""jour"""
        If TryGetCustomRangeFind("Bonjour", Feuil2.Range("A:B"), Rng) Then
            MsgBox Rng.Address & vbNewLine & Rng.Value
        End If
    End Sub
     
     
    Function TryGetCustomRangeFind(What, In_Range As Range, Out_Range As Range) As Boolean
        Dim Rng As Range
     
        With In_Range
            Set Rng = .Find(What, .Cells(.Rows.Count, .Columns.Count), xlValues, xlPart, xlByColumns, xlNext, False, False, False)
        End With
     
        If Not Rng Is Nothing Then
            Set Out_Range = Rng
            TryGetCustomRangeFind = True
        End If
    End Function
    Cependant, je ne l'ai pas trop testé mais je t'explique vite fait comment elle marche comme ça, si ça marche pas, tu pourras facilement la modifier.

    Je définit la cellule de départ en tant que dernière cellule du range (en bas à droite), j'utilise Next plutôt que Previous pour que la recherche commence sur la 1ère cellule car après la dernière cellule, c'est la 1èere cellule en haut à gauche qui est la suivante. Cependant, il y a 2 possibilités, rechercher en balayant colonne après colonne, ou alors en balayant ligne après ligne. J'ai choisi Colonne.
    Egalement, le dernier paramètre est important et peut te faire échouer la recherche si il est à vrai et que Application.FindFormat est définit.

  9. #9
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par LeSmoox Voir le message
    C'est comme si en cherchant A, il commençait à la deuxième cellule...
    Oui, mais c'est écrit dans l'aide justement avec le paramètre After.

    Si vous ne définissez pas cet argument, la recherche commence après la cellule figurant dans l'angle supérieur gauche de la plage.

  10. #10
    Membre averti
    Homme Profil pro
    Inscrit en
    Mars 2012
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mars 2012
    Messages : 27
    Par défaut
    Citation Envoyé par Nouveau2 Voir le message
    Oui, mais c'est écrit dans l'aide justement avec le paramètre After.
    Oui mais la phrase complète justement était: "C'est comme si en cherchant A, il commençait à la deuxième cellule, mais en cherchant Z, il commence dès la première cellule (qui est ligne -1)!"
    Quand il cherche A, il commence à la seconde cellule et OK, sauf que quand il cherche Z, il commence à la première (j'en suis sûr puisque là il trouve l'occurence erronée).
    Bref je suis en train de contourner le problème même si ça m'agace de devoir procéder à des contrôles supplémentaires que je ne comprends pas.

    Merci pour ton astuce, je vais tester ça

  11. #11
    Invité
    Invité(e)
    Par défaut
    As-tu le code de la méthode Find ?

    Tu as bien définis la totalité des paramètres ?

    Dans le code que je t'es fournis par exemple, tu verras qu'en changeant le paramètre xlByColumns par xlByRows, le résultat n'est pas le même, c'est pour ça que j'ai mis "bonjour" en B1 (1ère cellule lors d'un balayage ligne par ligne) de manière à ce que le résultat ne soit pas identique avec une recherche par ligne ou par colonne. Egalement, avec l'argument Formulas plutôt que Values, cette formule ne renvoie rien parce que j'utilise une concaténation pour former le mot bonjour.

  12. #12
    Membre averti
    Homme Profil pro
    Inscrit en
    Mars 2012
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mars 2012
    Messages : 27
    Par défaut
    Oui, j'utilise celui-ci (j'ai remplacé les noms de variables pour mieux comprendre):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Set RangeDeRecherche = Sheets("Feuil1").Range("B" & DébutDeRange.Row - 1 & ":B" & FinDeRange).Find(what:=Lettre, LookAt:=xlWhole)
    En gros, je ne définis par le paramètre After car je fais partir la recherche manuellement à DébutDeRange.Row - 1. Ce qui revient au même (de plus, j'avais essayé After: mais combiné avec une variable il me posait des problèmes donc j'ai choisi l'autre option).

  13. #13
    Invité
    Invité(e)
    Par défaut
    Donc, la réponse est non plutôt que oui, puisque tu ne définis pas xlByColumns ou xlByRows, ni le sens de la recherche avec xlNext ou xlPrevious.

  14. #14
    Membre averti
    Homme Profil pro
    Inscrit en
    Mars 2012
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mars 2012
    Messages : 27
    Par défaut
    Citation Envoyé par Nouveau2 Voir le message
    As-tu le code de la méthode Find ?

    Tu as bien définis la totalité des paramètres ?

    Dans le code que je t'es fournis par exemple, tu verras qu'en changeant le paramètre xlByColumns par xlByRows, le résultat n'est pas le même, c'est pour ça que j'ai mis "bonjour" en B1 (1ère cellule lors d'un balayage ligne par ligne) de manière à ce que le résultat ne soit pas identique avec une recherche par ligne ou par colonne. Egalement, avec l'argument Formulas plutôt que Values, cette formule ne renvoie rien parce que j'utilise une concaténation pour former le mot bonjour.
    Pardon je n'avais pas tout lu dans le message.
    En fait la recherche s'effectue dans une Range désigné mais qui ne comporte qu'une seule Colonne (Range("B" & Variable#1,"B"& variable#2)) ce qui ne permet pas de changer de colonne.
    Et toutes les valeurs dans le database sont des données brutes et non des résultats dynamiques de formules.

  15. #15
    Membre averti
    Homme Profil pro
    Inscrit en
    Mars 2012
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mars 2012
    Messages : 27
    Par défaut
    Citation Envoyé par Nouveau2 Voir le message
    Je te donne un petit exemple qui recherche le mot bonjour dans la partie Value d'un Range plutôt que la partie Formula.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    ' Recherche la 1ère occurence du mot "Bonjour" en tant que valeur
    ' dans la 1ère colonne d'une feuille en partant de la 1ère cellule.
     
    Sub TestFind()
        Dim Rng As Range
        Feuil2.Range("A2,A5,B1,B7").Formula = "= ""Bon"" & ""jour"""
        If TryGetCustomRangeFind("Bonjour", Feuil2.Range("A:B"), Rng) Then
            MsgBox Rng.Address & vbNewLine & Rng.Value
        End If
    End Sub
     
     
    Function TryGetCustomRangeFind(What, In_Range As Range, Out_Range As Range) As Boolean
        Dim Rng As Range
     
        With In_Range
            Set Rng = .Find(What, .Cells(.Rows.Count, .Columns.Count), xlValues, xlPart, xlByColumns, xlNext, False, False, False)
        End With
     
        If Not Rng Is Nothing Then
            Set Out_Range = Rng
            TryGetCustomRangeFind = True
        End If
    End Function
    Cependant, je ne l'ai pas trop testé mais je t'explique vite fait comment elle marche comme ça, si ça marche pas, tu pourras facilement la modifier.

    Je définit la cellule de départ en tant que dernière cellule du range (en bas à droite), j'utilise Next plutôt que Previous pour que la recherche commence sur la 1ère cellule car après la dernière cellule, c'est la 1èere cellule en haut à gauche qui est la suivante. Cependant, il y a 2 possibilités, rechercher en balayant colonne après colonne, ou alors en balayant ligne après ligne. J'ai choisi Colonne.
    Egalement, le dernier paramètre est important et peut te faire échouer la recherche si il est à vrai et que Application.FindFormat est définit.
    Donc tu veux dire que si je définis la plage de recherche B2:B500, et j'ajoute After: B500, il commencera obligatoirement par B2 (la Next de B500) et ce sans lire d'abord B500 ?
    Cela m'a l'air d'une bonne solution je vais essayer!

  16. #16
    Invité
    Invité(e)
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    ' Recherche la 1ère occurence du mot "Bonjour" en tant que valeur
    ' dans la 1ère colonne d'une feuille en partant de la 1ère cellule.
    Sub FindTest()
        Dim Rng As Range
     
        Feuil2.Range("A2,A5,B1,B7").Formula = "= ""Bon"" & ""jour """
     
        If TryGetCustomRangeFind("bonjour", Feuil2.Range("A:B"), Rng) Then
            MsgBox Rng.Address & vbNewLine & Rng.Value
        End If
    End Sub
     
     
    Function TryGetCustomRangeFind(What, In_Range As Range, Out_Range As Range) As Boolean
        With In_Range
            Set Out_Range = .Find(What, .Cells(.Rows.Count, .Columns.Count), xlValues, xlPart, xlByColumns, xlNext, False, False, False)
            TryGetCustomRangeFind = Not (Out_Range Is Nothing)
        End With
    End Function
    J'ai modifié l'exemple, maintenant, il y a un espace à la fin du mot bonjour, et je fais la recherche sans respecter la casse. Cette exemple montre qu'en changeant 1 des parmètres de la fonction (par exemple : xlPart => xlWhole ou encore MatchCase = False => MatchCase = True), ça ne marchera pas.
    Il faut renseigner tous les paramètres. Tous les paramètres sont important.

  17. #17
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par LeSmoox Voir le message
    Donc tu veux dire que si je définis la plage de recherche B2:B500, et j'ajoute After: B500, il commencera obligatoirement par B2 (la Next de B500) et ce sans lire d'abord B500 ?
    Cela m'a l'air d'une bonne solution je vais essayer!
    C'est ce que j'ai voulu te faire comprendre depuis le tout début
    Je t'ai cité le texte de l'aide VBA car c'est clairement expliqué.

    After est lié à d'autres paramètres. Il y a un sens fourni par xlNext/xlPrevious donc ça dépend du sens de la recherche.

  18. #18
    Membre averti
    Homme Profil pro
    Inscrit en
    Mars 2012
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mars 2012
    Messages : 27
    Par défaut
    Au temps pour moi Nouveau2 En ajoutant l'After:=FinduRange ça marche parfaitement...Désolé j'avais pas saisis que la recherche repartirait du début comme ça.
    Encore merci pour ta patience et pour ton coup de main!

  19. #19
    Invité
    Invité(e)
    Par défaut
    Salut,

    De rien, mais si tu ne défini pas tous les paramètres, il est possible que ta fonction ne marche plus après utilisation de la boite de dialogue "Recherche" dans Excel. C'est toi qui voit.

    @+

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème avec ma méthode Find
    Par cdurep dans le forum Excel
    Réponses: 2
    Dernier message: 04/03/2014, 11h30
  2. [XL-2010] Problème avec la méthode find d'un objet Range dans une zone filtrée
    Par stargates01 dans le forum Macros et VBA Excel
    Réponses: 10
    Dernier message: 01/03/2014, 00h27
  3. Problème méthode Find de Redemption
    Par Samildanach dans le forum Bibliothèques
    Réponses: 0
    Dernier message: 12/08/2008, 14h34
  4. Problème méthode find
    Par tazmania dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 01/06/2007, 16h37
  5. VBA-E Problème méthode .find
    Par popo68 dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 03/01/2007, 11h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo