VBA recherche V selon colonne
Bonsoir,
J'aurais besoin de votre aide pour trouver la forme d'un code pour réaliser l'action suivante :
Faire une rechercheV d'une valeur dans une matrice selon un numéro de colonne.
Ca donnerait donc, dans la forme (à transformer en VBA) : rechercheV(valeur;table;variableColonne).
Le truc, c'est que je ne connais pas à l'avance le numéro de la colonne.
Il faudrait donc d'abord, il me semble, faire une rechercheH pour trouver le numéro de la colonne en fonction du titre du tableau
Voici un fichier joint pour que vous saisissiez plus facilement :
L'objectif ici serait de trouver les valeurs des colonnes B et C (titres du tableau : Titre 3 et Titre 4) pour les valeurs x et z, ce en fonction des valeurs associés dans la base de donnée (un peu plus à droite sur la feuille).
J'ai des notions de VBA, mais je ne vois pas vraiment comment m'y prendre (je pense que je me complique la tâche).
Si vous souhaitez des précisions afin de mieux cerner ce que je souhaite faire, n'hésitez pas.
En vous remerciant chaleureusement pour votre aide,
Alex
Salut,
Dans le fichier ci-joint j'ai placé une formule en A2 que j'ai incrémentée vers la droite et vers le bas :
=INDEX($G$3:$K$5;LIGNE(A1);EQUIV(A$1;$G$2:$K$2;0))Si cette formule correspond à ton attente, tu voudrais l'équivalent en VBA ?
A te relire.
En fait j'ai déjà cherché un code VBA correspondant pour la même plage :
Option Explicit
Sub aa()
Dim Cellule As Range
For Each Cellule In Range("A2:C4")
Cellule = Application.WorksheetFunction.Index(Range("G3:K5"), Cellule.Row - 1, Application.WorksheetFunction.Match(Cells(1, Cellule.Column), Range("G2:K2"), 0))
Next
End SubCordialement.
Dans le principe c'est effectivement ça.
Le soucis, c'est que je voudrais également formater le tableau de gauche en fonction du nombre de résultats dans le tableau "BASE DE DONNEE".
J'ai tenté le code suivant, mais j'ai dû me tromper quelque part il y a une erreur sur la ligne au milieu de la boucle.
Je pense que je n'ai pas bien saisi la place de chaque élément dans le code VBA suivant :
Cellule = Application.WorksheetFunction.Index(Range("G3:K5"), Cellule.Row - 1, Application.WorksheetFunction.Match(Cells(1, Cellule.Column), Range("G2:K2"), 0))Voici ma proposition (avec erreur donc), afin de formater la tableau également en fonction du nombre de lignes dans "BASE DE DONNEE" :
Merci pour votre aide.
Edit :
Je viens de trouver une erreur sur la ligne suivante :
For Each Cellule In Range("A" & NbResults, Cells(4, NbTitres))=>
For Each Cellule In Range("A2", Cells(NbResults, NbTitres))Mais ça ne résout pas mon problème.
Tout d’abord BONJOUR et ensuite MERCI INFINIMENT de m’avoir répondu
Voici un code qui devrait répondre à ton attente :
Option Explicit
Sub Test()
Dim Cellule As Range, DerLig As Integer
DerLig = Range("G" & Rows.Count).End(xlUp).Row
For Each Cellule In Range("A2:D" & DerLig - 1)
Cellule = Application.WorksheetFunction.Index(Range("G3:K" & DerLig), Cellule.Row - 1, Application.WorksheetFunction.Match(Cells(1, Cellule.Column), Range("G2:K2"), 0))
Next
End SubA te relire.
Bonjour Yvouille,
Toutes mes excuses ; omettre des remerciements n'est pas dans mes habitudes. Je devais avoir la tête ailleurs
Evidemment, ce n'est pas pour cela que je ne vous étais pas sincèrement reconnaissant.
Pour repréciser mon problème ;
la base de donnée sera variable tant sur le nombre de lignes (résultats) que sur le nombre de colonnes (critères).
Le tableau de gauche, quant à lui, devrait être formaté pour que tous les résultats de la "BASE DE DONNEE" y figurent, mais seulement pour les titres du tableau (au niveau des colonnes donc) spécifiés.
Selon moi, il faudrait donc prendre en compte deux paramètres pour formater le résultat :
DerLig = Range("G" & Rows.Count).End(xlUp).Row
DerCol = Range("G2").End(xlToRight).ColumnPour l'appliquer à la suite de la formule, j'ai un peu de mal. Je crois que je mélange l'utilité de chaque terme.
Pour moi, ça devrait donner ça pour la boucle :
For Each Cellule In Range("A2", Cells(DerLig - 1, DerCol - 6))
Cellule = Application.WorksheetFunction.Index(Range(Range("G3"), Cells(DerCol, DerLig)), Cellule.Row - 1, Application.WorksheetFunction.Match(Cells(1, Cellule.Column), Range("G2:K2"), 0))
NextIl y a forcément quelque chose que je ne saisis pas.
Mes remerciements,
Cordialement,
Alexandre
Ca se complique un peu
Voici un code qui devrait convenir :
Option Explicit
Sub Test()
Dim Cellule As Range, DerLig As Integer, DerCol As Integer
DerLig = Range("G" & Rows.Count).End(xlUp).Row
DerCol = Range("G2").End(xlToRight).Column
For Each Cellule In Range("A2:D" & DerLig - 1)
Cellule = Application.WorksheetFunction.Index(Range(Cells(3, 7), Cells(DerLig, DerCol)), Cellule.Row - 1, Application.WorksheetFunction.Match(Cells(1, Cellule.Column), Range(Cells(2, 7), Cells(2, DerCol)), 0))
Next
End SubA te relire.
EDIT : Grâce à toi j'ai appris quelque chose à l'instant : que l'on pouvait mélanger des Range et des Cells en référence d'une range
Tu peux donc remplacer la très longue ligne ci-dessus par celle-ci :
Cellule = Application.WorksheetFunction.Index(Range(Range("G3"), Cells(DerLig, DerCol)), Cellule.Row - 1, Application.WorksheetFunction.Match(Cells(1, Cellule.Column), Range(Range("G2"), Cells(2, DerCol)), 0))
C'est quasiment ça !
Le seul détail qui cloche encore :
Le nombre de titres du tableau de gauche peut varier (dans l'exemple il y en a 4, mais on pourrait en avoir moins ou plus).
Ainsi, le soucis est que dans le code à cet endroit :
For Each Cellule In Range("A2:D" & DerLig - 1)D est fixe. Ainsi, cela fixe le nombre de colonnes pour le tableau de gauche.
J'ai essayé :
Option Explicit
Sub Test()
Dim Cellule As Range, DerLig As Integer, DerCol As Integer
DerLig = Range("G" & Rows.Count).End(xlUp).Row
DerCol = Range("E1").End(xlToLeft).Column
For Each Cellule In Range(Range("A2"), Cells(DerLig - 1, DerCol))
Cellule = Application.WorksheetFunction.Index(Range(Cells(3, 7), Cells(DerLig, DerCol)), Cellule.Row - 1, Application.WorksheetFunction.Match(Cells(1, Cellule.Column), Range(Cells(2, 7), Cells(2, DerCol)), 0))
Next
End Sub(j'ai également modifié la ligne de DerCol pour que ça compte le nombre de titres du tableau de gauche)
Mais ça ne fonctionne pas.
Un grand merci pour ton aide,
Alex
Edit :
Ah, je pense que c'est bon ; j'ai simplement ajouté une variable suplémentaire pour contrôler le nombre de titres dans la tableau de droite, et modifié la plage de la boucle.
Ca donne ça :
Option Explicit
Sub Test()
Dim Cellule As Range, DerLig As Integer, DerCol As Integer, DerColT As Integer
DerLig = Range("G" & Rows.Count).End(xlUp).Row
DerCol = Range("G2").End(xlToRight).Column
DerColT = Range("F1").End(xlToLeft).Column
For Each Cellule In Range(Range("A2"), Cells(DerLig - 1, DerColT))
Cellule = Application.WorksheetFunction.Index(Range(Cells(3, 7), Cells(DerLig, DerCol)), Cellule.Row - 1, Application.WorksheetFunction.Match(Cells(1, Cellule.Column), Range(Cells(2, 7), Cells(2, DerCol)), 0))
Next
End SubEt il semble que ça marche (pour l'exemple tout du moins, il me reste à appliquer cela à mon cas de figure bien plus complexe).
Je vous reprécise plus tard ce que ça donne concrètement.
Re,
J’avais bien vu tes tentatives de modifier la largeur du tableau de gauche, mais je trouvais cela assez illogique car si ton tableau peut avoir n’importe quelle largeur, je veux dire s’il a plus que 5, voire 6 colonnes, il faudra déplacer le tableau de droite vers la droite et alors tous tes codes concernant cette partie sont à refaire (il faudrait notamment en plus déterminer à quelle colonne commence ce tableau flottant, actuellement ancré en colonne G).
Mais si ta solution actuelle te convient, j’en suis également très content
EDIT : Tu peux également alléger ton code en supprimant les Application. devant les WorksheetFunction
Le tableau ici présent n'est qu'un test.
Dans mon cas pratique, le tableau de gauche est sur une feuille différente de celle où est la "BASE DE DONNEE".
Ainsi, aucun soucis de place
Si cette solution ne fonctionne pas, j'en ai une autre peut être un peu plus simple en réserve.
Mais je préfère néanmoins celle sur laquelle je travaille actuellement car elle est bien plus simple à coder (quoique...
A ce titre, mes sincères remerciements pour votre contribution qui m'est d'une grande aide.
Cordialement,
Alexandre.
Effectivement que si tu nous fourni des fichiers ne correspondant pas à la réalité, on ne peut pas vraiment te donner les meilleures solutions possibles. C'est juste dommage pour toi
Bonne continuation.
Pas vraiment, ça m'apprend plutôt à adapter les codes que vous m'indiquez, et non uniquement les recopier.
Ça me permet également de tenter de créer des codes assez souples.
Je pense que c'est plutôt bénéfique de ce point de vue.
De plus, le document que je manipule contient certaines données "sensibles", que je ne peux pas uploader sur internet.
En prenant un exemple simple pour l'explication, je peux probablement plus aisément l'adapter à des codes futurs
Le code que vous m'avez fourni devrait fonctionner pour mon cas de figure, bien que j'ai quelques difficultés liées aux références aux autres feuilles à incorporer dans la formule.
Je validerai le sujet une fois le soucis entièrement réglé.
Tous mes remerciements,
Alexandre.
Toi tu as l'impression d'apprendre, moi j'ai l'impression de perdre du temps inutilement. Mais bon, je n'étais pas non plus obligé de te répondre. Mais bon, d'autres membres respectent plus nos interventions. A la prochaine.
Toi tu as l'impression d'apprendre, moi j'ai l'impression de perdre du temps inutilement. Mais bon, je n'étais pas non plus obligé de te répondre. Mais bon, d'autres membres respectent plus nos interventions. A la prochaine.
Je pense qu'il y a un mal entendu ; je n'ai nullement l'intention de vous faire perdre ni à vous ni aux autres votre temps ô combien précieux. Je n'ai pas non plus eu l'impression de manquer de respect à qui que ce soit ici.
Quelles que soient donc les raisons qui vous font dire cela, sachez que ma volonté n'est pas là.
Si vous préférez une version plus parlante (je ne peux malheureusement pas faire plus proche de la réalité, les données réelles sont d'une certaine sensibilité), la suivante devrait convenir.
Après modification du fichier de démonstration et de légers changements au niveau de la forme de mon programme, voici une pièce jointe qui sera plus parlante je l'espère :
La feuille Data correspond à la base de donnée. Le nombre de colonnes (donc de titres) de cette feuille-ci restera fixe.
La feuille Results est l'équivalent du tableau de gauche sur l'ancien fichier ; ainsi le nombre de titres changera. Le nombre de lignes sera en revanche le même que dans la feuille "Data".
L'objectif est donc d'afficher les valeurs associées dans les colonnes appropriées, en fonction du titre de la colonne donc.
Le code commencerait donc par ça, je pense :
Option Explicit
Sub Test()
Dim Cellule As Range, DerLig As Integer, DerCol As Integer, DerColT As Integer
Dim DebMatrice As Range, DataMatrice As Range
DerLig = Sheets("Data").Range("A" & Rows.Count).End(xlUp).Row
DerCol = Sheets("Data").Range("A1").End(xlToRight).Column
DerColT = Sheets("Results").Range("Z1").End(xlToLeft).Column
For Each Cellule In Range(Range("A2"), Cells(DerLig, DerColT))
Cellule = ?
Next
End SubJ'ai tenté différentes solutions pour la formule Cellule = ... Sans parvenir à ne plus obtenir d'erreur (avant même que le code s’exécute).
Cordialement
Salut Alexandre,
Je te propose de partir dans une direction un peu différente. Dans le fichier ci-joint, à chaque fois que tu modifies un titre de colonne sur la feuille ‘Results’, les données en dessous sont réactualisées.
A te relire.
Bonjour Yvouille,
Merci pour cette proposition qui semble très intéressante.
N'ayant pas suffisamment de temps pour y regarder en détail ce midi, je verrai cela ce soir.
Pourriez-vous commenter brièvement le code ? Il y a des lignes que je ne comprends pas, notamment celles-ci :
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim DerLig As Integer, Nombre_colonnes As Integer, i As Integer, j As Integer
Application.ScreenUpdating = False
If Target.Count > 1 Then Exit Sub
Application.EnableEvents = False
Range("A2:IV" & Rows.Count).ClearContents
If Not Application.Intersect(Target, Range("A1").EntireRow) Is Nothing Then
DerLig = Sheets("Data").Range("A" & Rows.Count).End(xlUp).Row
Nombre_colonnes = Range("A1").End(xlToRight).Column
For i = 1 To Nombre_colonnes
On Error Resume Next
j = Application.WorksheetFunction.Match(Cells(1, i), Sheets("Data").Range("A1:IV1"), 0)
If j > 0 Then Sheets("Data").Range(Sheets("Data").Cells(2, j), Sheets("Data").Cells(DerLig, j)).Copy Cells(2, i)
j = 0
Next i
End If
Application.EnableEvents = True
End SubCordiales salutations,
Alexandre.
Bonsoir,
Merci pour ce code. Néanmoins :
Après tentatives d'adaptation du code pour mon programme, j'ai un petit soucis.
J'ai un peu de mal à cerner la composition de la variable j, donc je peine à décaler tout ça pour mon cas.
Mon tableau, sur l'équivalent de la feuille "Results", débute en B20.
Alors je n'arrive pas à modifier le code en conséquence. Il ne se passe rien.
Voici ce que j'ai essayé :
Option Explicit
Public Sub Worksheet_Change(ByVal Target As Range)
Dim DerLig As Integer, Nombre_colonnes As Integer, i As Integer, j As Integer
Application.ScreenUpdating = False
If Target.Count > 1 Then Exit Sub
Application.EnableEvents = False
Range("A21:O10000").ClearContents
'POURQUOI NE PAS INSERER ICI LE CODE POUR FORMATER LES TITRES
If Not Application.Intersect(Target, Range("B20").EntireRow) Is Nothing Then
DerLig = Sheets("Screener Result").Range("A" & Rows.Count).End(xlUp).Row
Nombre_colonnes = Sheets("Screener Result").Range("A1").End(xlToRight).Column
For i = 2 To Nombre_colonnes + 1
On Error Resume Next
j = Application.WorksheetFunction.Match(Cells(21, i), Sheets("Screener Result").Range("A1:IV1"), 0)
If j > 0 Then Sheets("Screener Result").Range(Sheets("Screener Result").Cells(2, j), Sheets("Data").Cells(DerLig, j)).Copy Cells(21, 2)
j = 0
Next i
End If
Application.EnableEvents = True
End SubJ'ai évidemment placé ce code non pas dans un module mais dans la feuille correspondante dans "Microsoft Excel Objets".
Qu'ai-je mal fait ?
Bonne soirée,
Alex
Edit :
Une hypothèse d'erreur :
Je pense que le fait que les deux tableaux n'aient pas les mêmes coordonnées complexifie légèrement le code, non ?
L'erreur doit forcement venir de là (c'est il me semble la seule chose qui différencie mon cas pratique du cas exposé ici).
Re-bonjour,
Evite les messages ‘à épisodes’, ça rend leur lecture très pénible. Laisse-toi le temps de réfléchir et poste lorsque tu es certain d’avoir tout dit
Evite les ‘UP’ ; ça énerve plus que ce que ça aide à avancer. Nous t’offrons notre aide gratuitement et ne sommes pas 24 heures sur 24 à ta disposition
Laisse-moi le temps de répondre entre deux de tes demandes
Yvouille a écrit :Effectivement que si tu nous fournis des fichiers ne correspondant pas à la réalité, on ne peut pas vraiment te donner les meilleures solutions possibles. C'est juste dommage pour toi
Dans le fichier ci-joint, un code corrigé en fonction de tes nouvelles indications :
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim DerLig As Integer, Dernière_colonne As Integer, i As Integer, j As Integer
Application.ScreenUpdating = False
If Target.Count > 1 Then Exit Sub
Application.EnableEvents = False
If Not Application.Intersect(Target, Range("B20:IV20")) Is Nothing Then
Range("B21:IV" & Rows.Count).ClearContents
DerLig = Sheets("Data").Range("A" & Rows.Count).End(xlUp).Row
Dernière_colonne = Range("B20").End(xlToRight).Column
For i = 2 To Dernière_colonne
On Error Resume Next
j = Application.WorksheetFunction.Match(Cells(20, i), Sheets("Data").Range("A1:IV1"), 0)
If j > 0 Then Sheets("Data").Range(Sheets("Data").Cells(2, j), Sheets("Data").Cells(DerLig, j)).Copy Cells(21, i)
j = 0
Next i
End If
Application.EnableEvents = True
End Sub
Ça marche, c'est parfait. Merci infiniment !
Dernier point :
Serait-ce possible n'empêcher ce code de s'exécuter en continu ?
(c'est à dire pouvoir l'attacher uniquement à une macro déclenchée manuellement)
Cordialement,
Alex.