J'ai l'habitude de travailler avec VLOOKUP mais cette fois, j'ai un défi. Je ne veux pas la première valeur correspondante, mais la dernière. Comment? (Je travaille avec LibreOffice Calc mais une solution MS Excel devrait être tout aussi utile.)
La raison en est que j’ai deux colonnes de texte avec des milliers de lignes, l’une est une liste des bénéficiaires des transactions (Amazon, Ebay, un employeur, une épicerie, etc.) et l’autre une liste de catégories de dépenses (salaires, taxes, ménage, loyer, etc.). Certaines transactions n'ont pas la même catégorie de dépenses à chaque fois et je veux saisir la plus récente. Notez que la liste est triée par aucune des deux colonnes (en fait, par date), et je ne veux pas changer l’ordre de tri.
Ce que j’ai (à l’exception du traitement des erreurs) est la formule habituelle de "premier match":
=VLOOKUP(
[payee field] , [payee+category range] , [index of category column] ,
0 )
J'ai vu des solutions comme ceci, mais j'obtiens des erreurs #DIV/0!
:
=LOOKUP(2 , 1/( [payee range] = [search value] ) , [category range] )
La solution peut être n’importe quelle formule, pas nécessairement VLOOKUP. Je peux également échanger les colonnes bénéficiaire/catégorie. Juste pas de changement dans la colonne de tri, s'il vous plaît.
Points bonus pour une solution qui sélectionne la valeur la plus fréquente plutôt que la dernière!
Vous pouvez utiliser une formule matricielle pour extraire des données du dernier enregistrement correspondant.
=INDEX(IF($A$1:$A$20="c",$B$1:$B$20),MAX(IF($A$1:$A$20="c",ROW($A$1:$A$20))))
Entrez la formule en utilisant Ctrl+Shift+Enter.
Cela fonctionne comme la construction INDEX
/MATCH
d'un VLOOKUP
, mais avec un MAX
conditionnel utilisé à la place de MATCH
.
Notez que cela suppose que votre table commence à la ligne 1. Si vos données commencent à une ligne différente, vous devrez ajuster la partie ROW(...)
en soustrayant la différence entre la ligne du haut et 1.
(Répondez ici sans poser de question distincte pour les données triées.)
Si les données étaient triées , vous pouvez utiliser VLOOKUP
avec l'argument range_lookup
TRUE
(ou omis, car il s'agit de la valeur par défaut), qui est officiellement décrit pour Excel comme "recherche d'une correspondance approximative".
En d'autres termes, pour les données triées:
FALSE
renvoie la première valeur , etTRUE
renvoie la dernière valeur .Ceci est en grande partie non documenté et obscur, mais remonte à VisiCalc (1979) et est au moins valable aujourd'hui dans Microsoft Excel, LibreOffice Calc et Google Sheets. Cela est finalement dû à la mise en œuvre initiale de LOOKUP
dans VisiCalc (et donc VLOOKUP
et HLOOKUP
), alors qu’il n’y avait pas de quatrième paramètre. La valeur est trouvée par recherche binaire , en utilisant la borne inclusive gauche et la limite exclusive droite (une implémentation commune et élégante), ce qui entraîne ce comportement.
Techniquement, cela signifie que l’on commence la recherche avec l’intervalle candidat [0, n)
, où n
est la longueur du tableau et la condition invariante de la boucle est celle A[imin] <= key && key < A[imax]
(la borne de gauche est <= la cible, la borne de droite, qui commence un après le end, est> la cible; pour valider, vérifiez les valeurs aux points finaux avant ou le résultat après), puis divisez et choisissez successivement quel côté préserve cet invariant: par exclusion un côté, jusqu'à ce que vous obteniez un intervalle avec 1 terme, [k, k+1)
, et l'algorithme renvoie alors k
. Ce n'est pas nécessairement une correspondance exacte (!): C'est simplement la correspondance la plus proche d'en bas. En cas de correspondances en double, cela revient à renvoyer la dernière correspondance , car elle nécessite que la valeur suivante soit supérieure à la clé (ou à la fin). du tableau). En cas de doublons, vous avez besoin de comportements , ce qui est raisonnable et facile à mettre en œuvre.
Ce comportement est indiqué explicitement dans cet ancien article de la Base de connaissances Microsoft (soulignement ajouté): "XL: Comment renvoyer la première ou la dernière correspondance dans un tableau" ( Q214069 ):
Vous pouvez utiliser la fonction LOOKUP () pour rechercher une valeur dans un tableau de données triées et renvoyer la valeur correspondante contenue dans cette position dans un autre tableau. Si la valeur de recherche est répétée dans le tableau, elle renvoie la dernière correspondance rencontrée . Ce comportement est vrai pour les fonctions VLOOKUP (), HLOOKUP () et LOOKUP ().
La documentation officielle de certaines feuilles de calcul suit; Le comportement de "dernière correspondance" n'est pas non plus mentionné, mais il est impliqué dans la documentation de Google Sheets:
TRUE suppose que la première colonne du tableau est triée par ordre numérique ou alphabétique, puis recherchera la valeur la plus proche .
Si
is_sorted
estTRUE
ou omis, la correspondance la plus proche ( inférieure ou égale à la clé de recherche) est renvoyée.
Si les valeurs du tableau de recherche sont séquentielles (c’est-à-dire que vous recherchez la valeur la plus grande, telle que la date la plus récente), vous n’avez même pas besoin d’utiliser la fonction INDIRECT. Essayez ce code simple:
=MAX(IF($A$1:$A$20="c",$B$1:$B$20,)
Encore une fois, entrez la formule en utilisant CTRL + SHIFT + ENTRÉE
=LOOKUP([payee field] , [payee range] , [category range])
Cela vous donnera la dernière valeur
Est-ce que je reçois des points bonus pour mon retard de 3 ans?
J'ai eu un essai à la valeur la plus fréquente. Pas sûr que cela fonctionne dans libreOffice, mais cela semble fonctionner dans Excel
= INDEX ($ B $ 2: $ B $ 9, MATCH (MAX (- (2 $ A: 9 $ A = D2)) * PAYTIFS ($ B $ 2: 9 $ B, $ B $ 2: B $ 9 $, 2 $ A : 9 dollars australiens, D2)), - (2 dollars australiens: 9 dollars australiens = D2) * Pays (2 milliards de dollars: 9 dollars, 2 dollars: 2 dollars: 2 dollars: 2 dollars: 2 dollars ), 0))
La colonne A serait le bénéficiaire, la colonne B serait la catégorie, D2 le bénéficiaire que vous souhaitez filtrer. Je ne sais pas pourquoi il ajoute des sauts de ligne supplémentaires dans la fonction ci-dessus.
Ma fonction pour trouver la dernière cellule serait la suivante:
= INDIRECT ("B" & MAX (- (2 $ A: 9 $ = D2) * ROW (2 $ A: 9 $ A)))
Indirecte me permet de spécifier la colonne que je veux renvoyer et de trouver la ligne directement (je n'ai donc pas besoin de soustraire le nombre de lignes d'en-tête.
Ces deux fonctions doivent être entrées avec Ctrl + Maj + Entrée