Wie kann ich VLOOKUP dazu bringen, das * letzte * Match zurückzugeben?

12

Ich bin es gewohnt, mit VLOOKUP zu arbeiten, aber diesmal habe ich eine Herausforderung. Ich möchte nicht den ersten übereinstimmenden Wert, sondern den letzten. Wie? (Ich arbeite mit LibreOffice Calc, aber eine MS Excel-Lösung sollte ebenso nützlich sein.)

Der Grund ist, dass ich zwei Textspalten mit Tausenden von Zeilen habe. Nehmen wir an, eine ist eine Liste der Transaktionsempfänger (Amazon, Ebay, Arbeitgeber, Lebensmittelgeschäft usw.) und die andere ist eine Liste der Ausgabenkategorien (Löhne, Steuern, Haushalt, Miete usw.). Einige Transaktionen haben nicht jedes Mal dieselbe Ausgabenkategorie, und ich möchte die zuletzt verwendete auswählen. Beachten Sie, dass die Liste nach keiner Spalte (tatsächlich nach Datum) sortiert ist und ich die Sortierreihenfolge nicht ändern möchte.

Was ich habe (ohne Fehlerbehandlung), ist die übliche "First-Match" -Formel:

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

Ich habe solche Lösungen gesehen , aber ich erhalte #DIV/0!Fehler:

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

Die Lösung kann eine beliebige Formel sein, nicht unbedingt VLOOKUP. Ich kann auch die Spalten des Zahlungsempfängers / der Kategorie vertauschen. Nur bitte keine Änderung in der Sortierspalte.


Bonuspunkte für eine Lösung, die eher den häufigsten als den letzten Wert auswählt!

Torben Gundtofte-Bruun
quelle

Antworten:

3

Sie können eine Array-Formel verwenden, um Daten aus dem letzten übereinstimmenden Datensatz abzurufen.

=INDEX(IF($A$1:$A$20="c",$B$1:$B$20),MAX(IF($A$1:$A$20="c",ROW($A$1:$A$20))))

Geben Sie die Formel mit Ctrl+ Shift+ ein Enter.

Dies funktioniert wie die INDEX/ MATCHKonstruktion von a VLOOKUP, jedoch mit einer Bedingung, MAXdie anstelle von verwendet wird MATCH.

Beachten Sie, dass dies davon ausgeht, dass Ihre Tabelle in Zeile 1 beginnt. Wenn Ihre Daten in einer anderen Zeile beginnen, müssen Sie das ROW(...)Teil anpassen, indem Sie die Differenz zwischen der oberen Zeile und 1 subtrahieren.

Excellll
quelle
Ich bin verwirrt über dieses wörtliche "c" - ich würde denken, dass die Bewertung immer falsch ist. Was macht es also wirklich?
Torben Gundtofte-Bruun
Ich habe Ihren Vorschlag getestet (und überprüft, ob er als Array-Formel akzeptiert wurde). Ich nehme an, Col A ist Zahlungsempfänger und B ist Kategorie, oder? Leider gibt LibreOffice "ERR: 502" zurück, was übersetzt "Ungültiges Argument: Funktionsargument ist ungültig. Beispiel: Eine negative Zahl für die Funktion SQRT (), verwenden Sie dazu bitte IMSQRT ()". Ich habe überprüft, ob alle Funktionen mit diesem Namen in LibreOffice vorhanden sind, aber ich frage mich, ob LibreOffice IFkeine Arrays verarbeiten kann.
Torben Gundtofte-Bruun
Entschuldigung, das wörtliche "c" war nur der Name des Zahlungsempfängers, mit dem Sie übereinstimmen wollten. Das war ein Relikt aus meinen Beispieldaten, mit denen ich gespielt habe. Ich gehe davon aus, dass dies durch eine Zellreferenz in Ihrem Blatt ersetzt wird.
Excellll
@ TorbenGundtofte-Bruun Möchten Sie die Formel teilen, die Sie verwenden? Ich kann möglicherweise Fehler beheben, wenn ich es sehe. Sie können auch jederzeit versuchen, die Formel mit Evaluate Formulazu durchlaufen, um festzustellen , welcher Teil der Formel den Fehler generiert. Diese Funktion ist in Excel vorhanden, und ich wäre überrascht, wenn LibreOffice Calc nicht dieselbe Funktion hätte.
Excellll
Meine ursprüngliche Formel ist unkompliziert, deshalb ist sie nicht ausreichend :-) =VLOOKUP(J1061;$J$2:$K$9999;2;0)wobei Spalte J Zahlungsempfänger und Spalte K die Kategorien enthält. Es gibt das erste Match wie erwartet zurück.
Torben Gundtofte-Bruun
2

(Beantwortung hier als keine separate Frage für sortierte Daten.)

Wenn die Daten wurden sortiert, könnten Sie VLOOKUPmit dem range_lookupArgument TRUE(oder weggelassen wird , da es die Standardeinstellung), die offiziell für Excel beschrieben wird als „für ungefähre Übereinstimmung finden“.

Mit anderen Worten für sortierte Daten:

  • Setzen des letzten Arguments, FALSEum den ersten Wert zurückzugeben, und
  • Wenn Sie das letzte Argument so einstellen, dass TRUEder letzte Wert zurückgegeben wird.

Dies ist weitgehend undokumentiert und unklar, stammt jedoch aus VisiCalc (1979) und gilt heute zumindest für Microsoft Excel, LibreOffice Calc und Google Sheets. Dies ist letztendlich auf die anfängliche Implementierung LOOKUPin VisiCalc (und von dort VLOOKUPund HLOOKUP) zurückzuführen, als es keinen vierten Parameter gab. Der Wert wird durch binäre Suche unter Verwendung von inklusive linker und exklusiver rechter Grenze (eine übliche und elegante Implementierung) gefunden, was zu diesem Verhalten führt.

Technisch bedeutet dies, dass man die Suche mit dem Kandidatenintervall startet [0, n), wobei ndie Länge des Arrays ist, und die schleifeninvariante Bedingung ist, dass A[imin] <= key && key < A[imax](die linke Grenze ist <= das Ziel, die rechte Grenze, die eine nach dem Ende beginnt, ist > das Ziel (zu validieren, entweder die Werte an den Endpunkten vorher oder das Ergebnis danach zu überprüfen) und nacheinander die Seite zu halbieren und auszuwählen, die diese Invariante beibehält: durch Ausschluss wird eine Seite, bis Sie zu einem Intervall mit 1 Term kommen [k, k+1), und die Der Algorithmus kehrt dann zurück k. Dies muss keine exakte Übereinstimmung (!) Sein: Es ist nur die engste Übereinstimmung von unten. Bei doppelten Übereinstimmungen wird die letzte Übereinstimmung zurückgegeben, da der nächste Wert größer sein mussals der Schlüssel (oder das Ende des Arrays). Im Falle von Duplikaten benötigen Sie ein gewisses Verhalten, das sinnvoll und einfach zu implementieren ist.

Dieses Verhalten wird in diesem alten Microsoft Knowledge Base-Artikel explizit angegeben (Hervorhebung hinzugefügt): "XL: Zurückgeben der ersten oder letzten Übereinstimmung in einem Array" ( Q214069 ):

Mit der Funktion LOOKUP () können Sie nach einem Wert in einem Array sortierter Daten suchen und den entsprechenden Wert an dieser Position in einem anderen Array zurückgeben. Wenn der Suchwert innerhalb des Arrays wiederholt wird, wird die zuletzt gefundene Übereinstimmung zurückgegeben . Dieses Verhalten gilt für die Funktionen VLOOKUP (), HLOOKUP () und LOOKUP ().

Offizielle Dokumentation für einige Tabellenkalkulationen folgt; In beiden Fällen wird das Verhalten "Letzte Übereinstimmung" nicht angegeben, es ist jedoch in der Google Sheets-Dokumentation enthalten:

  • Microsoft Excel

    TRUE geht davon aus, dass die erste Spalte in der Tabelle entweder numerisch oder alphabetisch sortiert ist, und sucht dann nach dem nächstgelegenen Wert .

  • Google Sheets :

    Wenn is_sortedist TRUEoder weggelassen wird , das nächste Spiel ( kleiner oder gleich dem Suchschlüssel) zurückgegeben

Nils von Barth
quelle
Das nächste Match machte mich verrückt!
Davetapley
1

Wenn die Werte im Sucharray sequentiell sind (dh Sie suchen nach dem größten Wert, z. B. dem letzten Datum), müssen Sie nicht einmal die INDIRECT-Funktion verwenden. Versuchen Sie diesen einfachen Code:

=MAX(IF($A$1:$A$20="c",$B$1:$B$20,)

Geben Sie die Formel erneut mit STRG + UMSCHALT + EINGABETASTE ein

Der Stich
quelle
0

Ich habe es mit dem häufigsten Wert versucht. Ich bin mir nicht sicher, ob es in libreOffice funktionieren würde, aber es scheint in Excel zu funktionieren

= 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))

Spalte A wäre der Zahlungsempfänger, Spalte B wäre die Kategorie, D2 ist der Zahlungsempfänger, nach dem Sie filtern möchten. Ich bin mir nicht sicher, warum es in der obigen Funktion zusätzliche Zeilenumbrüche verursacht.

Meine Funktion, um die letzte Zelle zu finden, wäre wie folgt:

= INDIREKT ("B" & MAX (- ($ A $ 2: $ A $ 9 = D2) * REIHE ($ A $ 2: $ A $ 9))

Indirekt kann ich die Spalte angeben, die ich zurückgeben möchte, und die Zeile direkt suchen (sodass ich die Anzahl der Kopfzeilen nicht subtrahieren muss.

Beide Funktionen müssen mit Strg + Umschalt + Eingabetaste eingegeben werden

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

Dadurch erhalten Sie den letzten Wert

Bekomme ich Bonuspunkte für 3 Jahre Verspätung?

DavePenn
quelle
-1

Sie haben #DIV/0!Fehler erhalten, weil Sie Ihre Formel lieber wie folgt schreiben sollten:

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

Dies wird funktionieren und das letzte Spiel finden.

([payee range] = [search value]) : Boolesche Matrix TRUE / FALSE

IF(([payee range] = [search value]);1;"") : Pseudo-Boolesche Matrix 1 / ""

=LOOKUP(2; {pseudo-boolean matrix 1/""} );[category range]): Immer die letzte 1Position zurückgeben

Samuel
quelle
LOOKUPFunktioniert nur mit sortierten Listen. Die Ausgabe Ihres Vergleichs führt zu einer Liste von 1s und Leerzeichen auf nicht sortierte Weise, sodass kein korrektes Ergebnis erzielt wird .
Máté Juhász