Recherche V VBA

Bonjour à tous,

Tout nouveau sur le forum, et novice en vba, je viens ici exposer mon problème. Bien que j'ai déjà trouvé un début de réponse sur un autre fil de discussion, notamment sur le code de base, je bloque sur son développement pour qu'il fonctionne avec mon cas :

J'ai un fichier excel qui est un fichier pdf convertit (fiches de salaire). Cette conversion affecte l'emplacement des données sur chaque feuille qui peuvent être déplacées d'une ou deux colonnes (rarement plus) et/ou une ou deux lignes. Je souhaite effectuer une recherche v d'une valeur cible : exemple Salaire horaire (cf fichier joint) et que la formule me donne la correspondance de cette valeur pour chaque feuille.

Voici le code de base que j'ai trouvé :

Sub test()

With Sheets("Test")

.Range("B1").Value = WorksheetFunction.VLookup(.Range("A1").Value, Sheets("Feuil2").Range("A1:AA100"), 2, False)

End With

End Sub

Il fonctionne très bien avec une feuille, mais comment l'adapter pour qu'il fonctionne sur chaque feuille et avec des données rarement à la même place, sans avoir à écrire un code pour chaque feuille?

De plus la valeur cible peut avoir une écriture différente, toujours à cause de cette conversion... Dans mon exemple, salaire horaire peut se retrouver écrit : "salaire horaire", "Salaire Horaire", "salaireHoraire" etc...

Pour compléter, je joins un fichier excel type sur lequel j'ai travaillé. Pour des raisons de confidentialité, j'ai enlevé les infos importantes, s'agissant de bulletins de salaires. Je n'ai laissé que 6 feuilles mais ce sont des fichiers d'en moyenne 150 et ça peut aller jusqu'à plusieurs milliers (pour des très grosses entreprises).

Dans l'attente de votre retour, merci d'avance,

Benjamin

19exple.xlsm (35.42 Ko)

bonsoir,

un proposition

Sub test()
' wst = feuille de synthèse
    Set wst = Worksheets("test")
    i = 0
    ' on parcourt chacune des fiches
    For Each ws In Worksheets
    ' si le nom de la feuille est <> de la feuille de synthèse
        If ws.Name <> wst.Name Then
        ' dlw dernière ligne sur la fiche
        dlw = ws.Range("a" & Rows.Count).End(xlUp).Row
        ' on boucle sur les écriture possibles de salaire horaire
            For Each sa In Array("Salaire  Horaire", "Salaire Horaire", "SalaireHoraire")
             ' recherche dans la fiche
                Set re = ws.Range("c1:A" & dlw).Find(sa, lookat:=xlPart, MatchCase:=False)
                If Not re Is Nothing Then
                'si trouvé on incrémente compteur de ligne
                    i = i + 1
                    ' on met le nom de la feuille en colonne 1
                    wst.Cells(i, 1) = ws.Name
                    ' on met le salaire horaire trouvé en colonne 2
                    If re.Offset(0, 14) <> "" Then wst.Cells(i, 2) = re.Offset(0, 14) Else wst.Cells(i, 2) = re.Offset(0, 15)
                    ' on a trouvé une occurrence de salaire horaire, inutile de chercher les autres sur la même fiche on sort de la boucle
                    Exit For
                End If
            Next
        End If
    Next
    Set re = Nothing
    Set wst = Nothing
End Sub

Merci pour votre réponse rapide! Je n'ai pas encore eu le temps de tester le code, je pourrais le faire en fin de journée ou demain. Je vous tiens au courant.


Merci pour votre réponse rapide! Je n'ai pas encore eu le temps de tester le code, je pourrais le faire en fin de journée ou demain. Je vous tiens au courant.

Bonjour H2so4,

Ta proposition fonctionne très bien, c'est bien cool! Malgré les explications en vert, j'ai un peu de mal à saisir le code mais c'est une question de temps. Pour avoir le nom de l'employé à la place du nom de la feuille, est-ce que je peux remplacer

wst.Cells(i, 1) = Ws.Name

par wst.Cells(i, 1) = une recherchev style vlookup

sachant que le nom de l'employé est toujours sur la même ligne mais pas forcément sur la même colonne?

Par avance merci!

Bonjour H2so4,

J'aurai encore besoin de tes conseils avisés! J'ai appliqué ton code à d'autres recherches (heures complémentaires, allègement fillon...). Le problème est que ce sont des éléments que ne se trouvent pas forcément sur chaque fiche de salaire et lorsque j'exécute le code, il me met la réponse trouvée dans la 1ère cellule et non dans la cellule correspondant à la feuille. Je te remets l'exemple en fichier joint, ce sera plus parlant.

Autre question, pour éviter de faire "exécuter" chaque macro, peut-on condenser les codes, à la place d'utiliser la fonction call?

Merci d'avance,

Benjamin

10exple.xlsm (42.93 Ko)

Bonsoir,

un code qui permet de récupérer les différentes info sur la feuille

Option Base 1

Sub test()
' wst = feuille de synthèse
    Set wst = Worksheets("test")
    r1 = Array(11, 200, 2100, 6350)    ' code à sélectionner en colonne A:B
    r2 = Array(13, 13, 15, 20)    ' si code trouvé 1ère colonne où chercher l'info
    r3 = Array(1, 1, -1, 1)    ' si pas trouvé dans 1ère colonne,position relative d'une autre colonne où chercher
    i = 0
    ' on parcourt chacune des fiches
    For Each ws In Worksheets
        ' si le nom de la feuille est <> de la feuille de synthèse
        If ws.Name <> wst.Name Then
            ' dlw dernière ligne sur la fiche
            dlw = ws.Range("a" & Rows.Count).End(xlUp).Row
            i = i + 1

            ' on met le nom de l'employé en colonne 1
            If ws.Range("O7") <> "" Then wst.Cells(i, 1) = ws.Range("O7") Else wst.Cells(i, 1) = ws.Range("N7")
            ' on boucle sur les codes à sélectionner

            For j = 1 To UBound(r1, 1)
                ' recherche dans la fiche
                Set re = ws.Range("B1:A" & dlw).Find(r1(j), lookat:=xlWhole, MatchCase:=False)
                If Not re Is Nothing Then

                    ' on met l'info correspondant au code(j) dans la colonne j+1
                    If ws.Cells(re.Row, r2(j)) <> "" Then wst.Cells(i, j + 1) = ws.Cells(re.Row, r2(j)) Else wst.Cells(i, j + 1) = ws.Cells(re.Row, r2(j) + r3(j))
                End If
            Next
        End If
    Next
    Set re = Nothing
    Set wst = Nothing
End Sub
24exple-1.xlsm (40.05 Ko)

Bonjour,

Merci pour ta réactivité! Ton code fonctionne très bien mais je suis toujours confronté au même problème, à savoir que même en spécifiant, comme tu l'as fait, que l'on veut qu'il trouve la valeur exacte avec xlWhole, pour la valeur 200, il me donne comme résultat ce qui correspond à 200 mais aussi à 2200...comment faire?

Bonsoir,

avec ton fichier de test, je n'ai pas vu ce problème.

voici une version adaptée à tester.

Option Base 1

Sub test()
' wst = feuille de synthèse
    Set wst = Worksheets("test")
    r1 = Array(11, 200, 2100, 6350)    ' code à sélectionner en colonne A:B
    r2 = Array(13, 13, 15, 20)    ' si code trouvé 1ère colonne où chercher l'info
    r3 = Array(1, 1, -1, 1)    ' si pas trouvé dans 1ère colonne,position relative d'une autre colonne où chercher
    i = 0
    ' on parcourt chacune des fiches
    For Each ws In Worksheets
        ' si le nom de la feuille est <> de la feuille de synthèse
        If ws.Name <> wst.Name Then
            ' dlw dernière ligne sur la fiche
            dlw = ws.Range("a" & Rows.Count).End(xlUp).Row
            i = i + 1

            ' on met le nom de l'employé en colonne 1
            If ws.Range("O7") <> "" Then wst.Cells(i, 1) = ws.Range("O7") Else wst.Cells(i, 1) = ws.Range("N7")
            ' on boucle sur les codes à sélectionner

            For j = 1 To UBound(r1, 1)
                ' recherche dans la fiche
                Set re = ws.Range("B1:A" & dlw).Find(r1(j), lookat:=xlWhole, MatchCase:=False)
                If Not re Is Nothing Then
                     If re.Value = r1(j) Then
                    ' on met l'info correspondant au code(j) dans la colonne j+1
                    If ws.Cells(re.Row, r2(j)) <> "" Then wst.Cells(i, j + 1) = ws.Cells(re.Row, r2(j)) Else wst.Cells(i, j + 1) = ws.Cells(re.Row, r2(j) + r3(j))
                    End If
                End If
            Next
        End If
    Next
    Set re = Nothing
    Set wst = Nothing
End Sub

Bonjour,

Merci de te décarcasser pour moi! Malheureusement, j'ai toujours le même problème. La valeur cherchée 200 (Heures complémentaires) ne se trouve qu'en "feuil5" dans mon exemple. Or, ce code me renvoie aussi les valeurs de 2200. En toute logique, il ne devrait y avoir en colonne C que la valeur trouvée 7,07 (correspondant à 200 Heures complémentaires)...

C'est pas simple tout ça!

Bonsoir

voici un code adapté, dans lequel j'ai mis une option de traçage de l'information, si elle activée (instructione traceon=true pour l'activer, traceon=false pour la désactiver), on affiche la rubrique, la valeur trouvée et la colonne dans laquelle la valeur a été trouvée. Ceci permet de vérifier si les paramètres R1,R2 et R3 sont corrects.

ces paramètres permettent de sélectionner les infos que tu veux voir affichées dans ta feuille test.

exemple code 11 si trouvé on cherche en colonne 13 l'info, si on ne la trouve pas on prend ce qu'on trouve dans la colonne immédiatement à droite 1 (donc 14)

de même pour

200,16,1

2100,15,-1 (immédiatement à gauche donc 14)

6350,20,1

Option Base 1

Sub test()
' paramètres
    traceon = True 'on active le traçage

    r1 = Array(11, 200, 2100, 6350)    'listes des codes à sélectionner en colonne A:B
    r2 = Array(13, 16, 15, 20)    ' si code trouvé 1ère colonne où chercher l'info
    r3 = Array(1, 1, -1, 1)    ' si pas trouvé dans 1ère colonne,position relative d'une autre colonne où chercher

    ' wst = feuille de synthèse
    Set wst = Worksheets("test")
    i = 0
    ' on parcourt chacune des fiches
    For Each ws In Worksheets
        ' si le nom de la feuille est <> de la feuille de synthèse
        If ws.Name <> wst.Name Then
            ' dlw dernière ligne sur la fiche
            dlw = ws.Range("a" & Rows.Count).End(xlUp).Row
            i = i + 1

            ' on met le nom de l'employé en colonne 1
            If ws.Range("O7") <> "" Then wst.Cells(i, 1) = ws.Range("O7") Else wst.Cells(i, 1) = ws.Range("N7")
            ' on boucle sur les codes à sélectionner

            For j = 1 To UBound(r1, 1)
                ' recherche dans la fiche
                Set re = ws.Range("B1:A" & dlw).Find(r1(j), lookat:=xlWhole, MatchCase:=False)
                If Not re Is Nothing Then

                    ' on met l'info correspondant au code(j) dans la colonne j+1
                    If ws.Cells(re.Row, r2(j)) <> "" Then
                        wst.Cells(i, j + 1) = ws.Cells(re.Row, r2(j))
                        ad = ws.Cells(re.Row, r2(j)).Address
                    Else
                        wst.Cells(i, j + 1) = ws.Cells(re.Row, r2(j) + r3(j))
                        ad = ws.Cells(re.Row, r2(j) + r3(j)).Address
                    End If
                    If traceon Then wst.Cells(i, j + 1) = re.Value & " - " & wst.Cells(i, j + 1) & "(" & ad & ")"

                End If
            Next
        End If
    Next
    Set re = Nothing
    Set wst = Nothing
End Sub

Bonjour,

Ça fonctionne! Un grand merci! J'ai une dernière question. J'ai toujours ce même souci que, lorsque je transforme un pdf en excel, comme tu le sais, il peut y avoir un décalage d'une ou deux colonnes selon les feuilles. Dans mon exemple, toutes les infos en colonne C sur la Feuil2 (salaire horaire, heures majorées, etc) se trouvent en colonne B sur la Feuil3, ce qui décale de fait toutes les infos correspondantes à droite de ces colonnes (je sais pas si cette phrase est super claire, en tout cas surement trop longue!). Bref. Y'a t'il un code pour uniformiser toutes les feuilles? Qu'on retrouve les mêmes infos dans les mêmes colonnes?

Merci à toi

bonsoir,

un essai

Sub reformat()
    Set wst = Worksheets("test")
    For Each ws In Worksheets
        If ws.Name <> wst.Name  Then
            dlw = ws.Range("a" & Rows.Count).End(xlUp).Row
            Set re = ws.Range("B1:A" & dlw).Find(11, lookat:=xlWhole, MatchCase:=False)
            If Not re Is Nothing Then
                If re.Column = 2 Then
                    cl = "B"
                ElseIf re.Offset(-1, 14) = "Taux" Then
                    cl = "N"
                Else
                    cl = ""
                End If
                If cl <> "" Then
                    For Each c In ws.Range(cl & re.Row & ":" & cl & dlw)
                        If c <> "" And c.Offset(0, -1) = "" Then c.Offset(0, -1) = c
                    Next
                    ws.Range(cl & re.Row - 2 & ":" & cl & dlw).Delete shift:=xlToLeft
                End If
            End If
        End If
    Next
End Sub

Nickel!

Un grand merci pour ta disponibilité!! Tu as fais une formation VBA ou tu as appris par toi même? Parce que je compte bien m'y mettre, histoire de comprendre ce qui est écrit et pouvoir faire des codes par moi même!

ponpon a écrit :

Nickel!

(...) Tu as fais une formation VBA ou tu as appris par toi même? (...)

pour répondre à ta question, je suis un autodidacte.

Rechercher des sujets similaires à "recherche vba"