Organisation de procédure (recherche)

Résolu
1Globule Messages postés 62 Statut Membre -  
michel_m Messages postés 18903 Date d'inscription   Statut Contributeur Dernière intervention   -
Bonjour à tous,

J'ai du mal à organiser ma macro, qui n'est pourtant pas si compliquée.

Je recherche une valeur (stockée en variable) dans mon classeur actif qui contient trois feuilles.
Si je la trouve dans une des feuille, je récupère les informations qui se trouvent sur la même ligne, je les indique en msgbox et je termine ma macro.
Si je ne la trouve pas je vais chercher dans un autre classeur, qui contient un nombre indéterminé de feuilles.
Si je la trouve, idem, je récupère les données de la ligne, je les affiche et je termine.
Si je ne la trouve pas du tout, dans aucun des deux classeurs, j'indique dans un msgbox une info de type "Valeur non trouvée".

Simple non ?

J'ai essayé avec des boucles et des if multiples, au final ça fonctionne très bien mais c'est une véritable usine à gaz.
Pourriez-vous m'indiquer la structure la plus simple à adopter ?

Merci beaucoup !

4 réponses

  1. yg_be Messages postés 23437 Date d'inscription   Statut Contributeur Dernière intervention   Ambassadeur 1 588
     
    bonjour, cela me semble une bonne idée d'utiliser des boucles et des IF.
    une moins bonne idée d'en faire une usine à gaz.
    0
    1. 1Globule Messages postés 62 Statut Membre 2
       
      J'ai pour l'instant une structure qui ressemble à ça, elle fonctionne mais elle ne me semble pas du tout optimale.

      For p = 1 To 2 ' Boucler sur 2 classeurs
      If p = 1 Then ' Savoir s'il y a 3 feuilles ou un nombre indéterminé
      a = 3
      Else
      a = Sheets.Count
      End If

      For i = 1 To a ' Boucler sur les x feuilles
      Sheets(i).Select
      For j = 2 To Cells(Rows.Count, 1).End(xlUp).Row ' Boucler sur toutes les lignes
      If Cells(j, 2).Value Like "*" & VAR Then ' Chercher la variable
      r = 1 ' Mettre un indicateur si valeur est trouvée
      ' Récupérer toutes les infos
      End If
      Next
      Next
      If r = 1 Then ' Si la valeur est trouvée, sortir de la boucle
      Exit For
      Else
      s = 1 ' Sinon mettre un indicateur quand le deuxième classeur s'ouvre
      Workbooks.Open Filename:="Documents/Archives.xlsx", ReadOnly:=True' Ouvrir le deuxième classeur
      End If
      Next


      If s = 1 Then ' Si le deuxième classeur est ouvert, le fermer
      Windows("Archives.xlsx").Close
      End If
      0
      1. yg_be Messages postés 23437 Date d'inscription   Statut Contributeur Dernière intervention   1 588 > 1Globule Messages postés 62 Statut Membre
         
        moi je ferais plutôt ainsi:
        option explicit
        Sub cherchepartout(quoi As String)
        Dim wb As Workbook
        If Not cherchedansunfichier(ThisWorkbook, quoi) Then
            Set wb = Workbooks.Open("Documents/Archives.xlsx", , True)
            If Not cherchedansunfichier(wb, quoi) Then
                'rien trouvé
            End If
            wb.Close
        End If
        End Sub
        Private Function cherchedansunfichier(wb As Workbook, Var As String) As Boolean
        Dim sh As Worksheet, lig As Range
        For Each sh In wb.Sheets
            For Each lig In sh.Rows
                If lig.Cells(1, 2).Value Like "*" & Var Then
                    'trouvé
                    cherchedansunfichier = True
                    Exit Function
                End If
            Next lig
        Next sh
        cherchedansunfichier = False
        End Function
        
        0
    2. 1Globule Messages postés 62 Statut Membre 2
       
      Merci beaucoup.
      Je vais tester et je te tiens informé.
      C'est très gentil en tout cas.
      0
    3. 1Globule Messages postés 62 Statut Membre 2
       
      Hum. visiblement ça ne fonctionne pas très bien.

      A première vue, il me semble qu'il faudrait boucler sur les lignes non vides pour gagner du temps, et ensuite j'aurais besoin de sélectionner la cellule concernée quand la valeur est trouvée.

      Je vais essayer de chercher un peu ce qui pose problème.
      0
  2. michel_m Messages postés 18903 Date d'inscription   Statut Contributeur Dernière intervention   3 320
     
    Bonjour;
    on peut certainement éviter la boucle dans les feuilles

     If Application.CountIf(Columns("B"), "*" & Var) = 1 Then
    lig = Columns("B").Find(what:=Var, LookIn:=xlValues).Row
    MsgBox Range(Cells(lig, "A"), Cells(lig, "G"))
    End If


    Exemple à adapter

    0
    1. 1Globule Messages postés 62 Statut Membre 2
       
      Merci à vous deux,

      J'ai adapté le code mais comme il ne fonctionnait pas j'ai essayé de reprendre déjà tel quel celqui de yg_be.
      Je ne parviens pas à lancer la macro, à moins d'enlever l'argument ("quoi", dans l'exemple).

      Est-ce que je fais quelque chose de travers ?
      Pour l'instant je suis dans un module simple...
      0
    2. 1Globule Messages postés 62 Statut Membre 2
       
      En enlevant l'argument, j'arrive à trouver ma variable quand elle se trouve sur la première page uniquement. Si elle est sur la deuxième ou sur une autre, la macro ne la détecte pas.

      De plus, si elle se trouve en première page jj'ai une erreur d'exécution 91 sur la ligne suivante :
      lig = Columns("B").Find(what:=Var, LookIn:=xlValues).Row
      0
    3. 1Globule Messages postés 62 Statut Membre 2
       
      Je commente, je commente... :o)

      En modifiant le type de variable lig en integer, c'est ok pour le deuxième problème.

      Par contre le premier reste entier : Si ma valeur se trouve sur une autre page que la première, on ne la détecte pas.

      Je cherche encore, et je commente si nécessaire...
      0
    4. 1Globule Messages postés 62 Statut Membre 2
       
      J'ai réussi à contourner le problème avec la méthode de Michel pour éviter la bouche !

      Bon, il faut sélectionner chaque page parcourue avec un sh.Select,
      C'est vrai qu'avec un ScreenUpdating à False on ne remarque rien, mais je trouve que c'est moins propre.

      Vous auriez une solution ?
      0
      1. yg_be Messages postés 23437 Date d'inscription   Statut Contributeur Dernière intervention   1 588 > 1Globule Messages postés 62 Statut Membre
         
        peut-être ainsi:
        Private Function cherchedansunfichier(wb As Workbook, Var As String) As Boolean
        Dim sh As Worksheet, lig As Range
        For Each sh In wb.Sheets
            If Application.CountIf(sh.Columns("B"), "*" & Var) = 1 Then
                Set lig = sh.Columns("B").Find(what:=Var, LookIn:=xlValues).EntireRow
                'trouvé
                MsgBox lig.Cells(1, 2).Value
                cherchedansunfichier = True
                Exit Function
            End If
        Next sh
        cherchedansunfichier = False
        End Function
        0
  3. michel_m Messages postés 18903 Date d'inscription   Statut Contributeur Dernière intervention   3 320
     
    Bonjour
    une proposition à adapter à ton contexte
    https://mon-partage.fr/f/wh79n738/

    Tu dis...

    0
  4. 1Globule Messages postés 62 Statut Membre 2
     
    Bonjour à vous deux, et merci encore pour votre aide.

    Je crains que la solution de yg_be (set lig) ne soit pas efficace : Si la valeur se trouve en deuxième feuille on ne la détecte toujours pas.

    Quant à la proposition de Michel, malheureusement je ne peux pas y accéder : Le lien est bloqué depuis mon bureau, je pense pour des raisons de sécurité.
    0
    1. yg_be Messages postés 23437 Date d'inscription   Statut Contributeur Dernière intervention   1 588
       
      avec ceci, je trouve en deuxième feuille:
      Private Function cherchedansunfichier(wb As Workbook, Var As String) As Boolean
      Dim sh As Worksheet, lig As Range
      For Each sh In wb.Sheets
          If Application.CountIf(sh.Columns("B"), "*" & Var) = 1 Then
              Set lig = sh.Columns("B").Find(what:=Var, LookIn:=xlValues).EntireRow
              'trouvé
              MsgBox lig.Cells(1, 2).Value
              cherchedansunfichier = True
              Exit Function
          End If
      Next sh
      cherchedansunfichier = False
      End Function
      0
    2. 1Globule Messages postés 62 Statut Membre 2
       
      Au temps pour moi, en adaptant j'ai oublié de modifier ma variable.
      Je crois bien que c'est tout bon !

      Un grand merci à toi et à Michel pour le temps consacré à aider les autres.
      Je clôture le sujet.
      0
    3. michel_m Messages postés 18903 Date d'inscription   Statut Contributeur Dernière intervention   3 320
       
      Bon, j'ai encore perdu plusieurs heures à vouloir aider!!!

      Dans le cas de blocage de pièces jointes, tu passes en message personnel et tu donnes à ton interlocuteur une adresse où tu peux les recevoir

      Adieu Globule
      0
      1. yg_be Messages postés 23437 Date d'inscription   Statut Contributeur Dernière intervention   1 588 > michel_m Messages postés 18903 Date d'inscription   Statut Contributeur Dernière intervention  
         
        michel_m, ta suggestion #6 a été très utile.
        0
    4. michel_m Messages postés 18903 Date d'inscription   Statut Contributeur Dernière intervention   3 320
       
      je m'adressais à globule et uniquement à lui, donc...
      0