Comment obtenir VLOOKUP pour renvoyer la * dernière * correspondance?

12

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, disons que l'une est une liste de bénéficiaires de transactions (Amazon, Ebay, employeur, épicerie, etc.) et l'autre est une liste de catégories de dépenses (salaires, impôts, ménage, loyer, etc.). Certaines transactions n'ont pas la même catégorie de dépenses à chaque fois, et je veux saisir la dernière utilisée. Notez que la liste n'est triée par aucune colonne (en fait par date), et je ne veux pas changer l'ordre de tri.

Ce que j'ai (à l'exclusion de la gestion des erreurs) est la formule habituelle de "première correspondance":

=VLOOKUP( 
[payee field] , [payee+category range] , [index of category column] , 
0 )

J'ai vu des solutions comme celle-ci, mais je reçois des #DIV/0!erreurs:

=LOOKUP(2 , 1/( [payee range] = [search value] ) , [category range] )

La solution peut être n'importe quelle formule, pas nécessairement RECHERCHEV. Je peux également permuter les colonnes bénéficiaire / catégorie. Pas de changement dans la colonne de tri, s'il vous plaît.


Points bonus pour une solution qui choisit la valeur la plus fréquente plutôt que la dernière!

Torben Gundtofte-Bruun
la source

Réponses:

3

Vous pouvez utiliser une formule matricielle pour obtenir les 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))))

Saisissez la formule à l'aide de Ctrl+ Shift+ Enter.

Cela fonctionne comme la construction INDEX/ MATCHde a VLOOKUP, mais avec un conditionnel MAXutilisé à 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 ROW(...)pièce en soustrayant la différence entre la ligne supérieure et 1.

Excellll
la source
Je suis confus au sujet de ce «c» littéral - je pense que l'évaluation est toujours fausse, alors que fait-elle vraiment?
Torben Gundtofte-Bruun
J'ai testé votre suggestion (et vérifié qu'elle a été acceptée comme formule de tableau). Je suppose que le Col A est le bénéficiaire et B est la catégorie, non? Malheureusement, LibreOffice renvoie "ERR: 502" qui se traduit par "Argument invalide: l'argument de la fonction n'est pas valide. Par exemple, un nombre négatif pour la fonction SQRT (), pour cela, veuillez utiliser IMSQRT ()". J'ai vérifié que toutes les fonctions existent avec ce nom dans LibreOffice, mais je me demande si LibreOffice ne IFpeut pas gérer les tableaux.
Torben Gundtofte-Bruun
Désolé, le "c" littéral n'était que le nom du bénéficiaire que vous vouliez faire correspondre. C'était une relique de mes données d'échantillon avec lesquelles je jouais. Je suppose que cela sera remplacé par une référence de cellule dans votre feuille.
Excellll
@ TorbenGundtofte-Bruun Care pour partager la formule que vous utilisez? Je pourrai peut-être le dépanner si je le vois. En outre, vous pouvez toujours essayer de parcourir la formule avec Evaluate Formulapour voir quelle partie de la formule génère l'erreur. Cette fonctionnalité existe dans Excel, et je serais surpris si LibreOffice Calc ne dispose pas de la même fonctionnalité.
Excellll
Ma formule originale est simple, c'est pourquoi elle n'est pas adéquate :-) =VLOOKUP(J1061;$J$2:$K$9999;2;0)où le col J contient les bénéficiaires et le col K les catégories. Il renvoie la première correspondance comme prévu.
Torben Gundtofte-Bruun
2

(Répondre ici comme aucune question distincte pour les données triées.)

Si les données ont été triées, vous pouvez les utiliser VLOOKUPavec l' range_lookupargument TRUE(ou omis, car c'est la valeur par défaut), qui est officiellement décrit pour Excel comme "rechercher une correspondance approximative".

En d'autres termes, pour les données triées:

  • définir le dernier argument pour FALSEretourner la première valeur, et
  • la définition du dernier argument TRUErenvoie la dernière valeur.

Ceci est en grande partie non documenté et obscur, mais remonte à VisiCalc (1979), et il existe aujourd'hui au moins dans Microsoft Excel, LibreOffice Calc et Google Sheets. C'est finalement dû à l'implémentation initiale de LOOKUPdans VisiCalc (et de là VLOOKUPet HLOOKUP), quand il n'y avait pas de quatrième paramètre. La valeur est trouvée par recherche binaire , en utilisant la limite gauche et la droite exclusives (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ù nest la longueur du tableau, et la condition invariante de la boucle est que A[imin] <= key && key < A[imax](la limite de gauche est <= la cible, la limite de droite, qui commence une après la fin, est > la cible; pour valider, soit vérifier les valeurs aux points de terminaison avant, soit vérifier le résultat après), et bissecter et choisir successivement le côté qui préserve cet invariant: par exclusion, un côté le fera, jusqu'à ce que vous arriviez à un intervalle avec 1 terme [k, k+1), et le l'algorithme revient ensuite k. Cela ne doit pas nécessairement être une correspondance exacte (!): C'est juste la correspondance la plus proche d'en bas. En cas de doublons, cela se traduit par le retour de la dernière correspondance, car cela nécessite que la valeur suivante soit supérieureque la clé (ou la fin du tableau). En cas de doublons, vous avez besoin d'un certain comportement, ce qui est raisonnable et facile à mettre en œuvre.

Ce comportement est indiqué explicitement dans cet ancien article de la Base de connaissances Microsoft (non souligné dans l'original): "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; dans aucun des deux, le comportement de "dernière correspondance" n'est indiqué, mais cela est implicite dans la documentation de Google Sheets:

  • Microsoft Excel

    VRAI suppose que la première colonne du tableau est triée numériquement ou alphabétiquement, puis recherchera la valeur la plus proche .

  • Google Sheets :

    Si is_sortedest TRUEou omis, la correspondance la plus proche ( inférieure ou égale à la clé de recherche) est renvoyée

Nils von Barth
la source
Ce match le plus proche me rendait fou!
davetapley
1

Si les valeurs du tableau de recherche sont séquentielles (c'est-à-dire que vous recherchez la plus grande valeur, comme la dernière date), 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 à l'aide de CTRL + MAJ + ENTRÉE

The Stich
la source
0

J'ai essayé la valeur la plus fréquente. Je ne sais pas si cela fonctionnerait dans libreOffice, mais il semble fonctionner dans Excel

= INDEX ($ B $ 2: $ B $ 9, MATCH (MAX (- ($ A $ 2: $ A $ 9 = D2) * COUNTIFS ($ B $ 2: $ B $ 9, $ B $ 2: $ B $ 9, $ A $ 2 $) : $ A $ 9, D2)), - ($ A $ 2: $ A $ 9 = D2) * COUNTIFS ($ B $ 2: $ B $ 9, $ B $ 2: $ B $ 9, $ A $ 2: $ A $ 9, D2 ), 0))

La colonne A serait le bénéficiaire, la colonne B serait la catégorie, D2 est le bénéficiaire que vous souhaitez filtrer. Je ne sais pas pourquoi cela met 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 (- ($ A $ 2: $ A $ 9 = D2) * ROW ($ A $ 2: $ A $ 9))))

Indirect me permet de spécifier la colonne que je veux retourner et de trouver la ligne directement (donc je n'ai pas besoin de soustraire le nombre de lignes d'en-tête.

Ces deux fonctions doivent être saisies en utilisant Ctrl + Maj + Entrée

gtwebb
la source
0
=LOOKUP([payee field] , [payee range] , [category range])

Cela vous donnera la dernière valeur

Puis-je obtenir des points bonus pour 3 ans de retard?

DavePenn
la source
-1

Vous avez des #DIV/0!erreurs car vous devriez plutôt écrire votre formule comme:

=LOOKUP(2;IF(([payee range] = [search value]);1;"");[category range])

cela fonctionnera et trouvera la dernière correspondance.

([payee range] = [search value]) : matrice booléenne TRUE / FALSE

IF(([payee range] = [search value]);1;"") : matrice pseudo-booléenne 1 / ""

=LOOKUP(2; {pseudo-boolean matrix 1/""} );[category range]): toujours revenir dernière 1position

Samuel
la source
LOOKUPne fonctionne que sur une liste triée, la sortie de votre comparaison entraînera une liste de 1s et d'espaces de manière non triée, donc elle ne donnera pas un résultat correct.
Máté Juhász