Im ersten Artikel über Kontext haben wir uns angesehen, worin der Unterschied zwischen dem Zeilenkontext und dem Benutzerkontext besteht. In diesem Teil zeigen wir Auswirkungen, die vielleicht überraschend, aber ungemein nützlich sind und erläutern die Funktion EARLIER().

Funktionen in berechneten Spalten

Eine berechnete Spalte anlegen, um beispielsweise den Bruttowert aus den Spalten Netto und Umsatzsteuer zu berechnen, ist mittlerweile nicht mehr spannend. Was passiert aber, wenn ich in der Spalte folgende Formel angebe:

SumX in einer berechneten Spalte Wir erhalten den summierten Wert der Spalte [Netto] der ganzen Tabelle... Warum? Wir haben doch nur den Zeilenkontext, mit dem wir arbeiten!? Wir haben gesehen, dass die Funktionen mit einem X sog. Iteratoren sind, also eigenständig auf der übergebenen Tabelle einen Zeilenkontext erstellen. Das bedeutet, dass der Zeilenkontext der aktuellen Zeile zwar bestehen bleibt, innerhalb der SumX-Funktion aber ein eigener Zeilenkontext angelegt wird. Und über diesen summieren wir den Ausdruck Auftrags[Netto]. Das bedeutet, dass der bestehende Zeilenkontext quasi überschrieben wird. Im nächsten Kapitel sehen wir, warum das sehr nützlich ist. Theoretisch bedeutet das, dass für jede Zeile die Summe der ganzen Tabelle berechnet wird, also bei N-Zeilen N*N Berechnungen. Das stimmt natürlich nicht; die Ausdrücke werden intern optimiert.

Ranking

Eine weitere interessante Eigenschaft von Kontexten lässt sich über eine Rangfolge oder ein “Ranking” zeigen. Ziel ist es, dass wir die Aufträge nach Netto-Umsatz einordnen. Dazu erstellen wir eine weitere Spalte “Rangfolge”. Das Feld soll die Anzahl an Zeilen beinhalten, deren Nettopreis größer ist, als der eigene – dafür verwenden wir die Iterator-Funktion COUNTROWS(). Die Formel könnte folgendermaßen aussehen:

Countrows Das Ergebnis ist leer. ==> Filter() ist ebenfalls ein Iterator – das bedeutet, dass Filter() einen eigenen Zeilenkontext erstellt. COUNTROWS() zählt die Zeilen, die Filter zurückgegeben hat. Der Ausdruck in Filter vergleicht den Nettopreis mit allen anderen Nettopreisen. Da wir aber einen neuen, eigenen Zeilenkontext erstellt haben, vergleichen wir jede Zeile mit sich selbst – und kein Nettopreis ist größer als er selbst… Wir brauchen Zugriff auf den ursprünglichen Zeilenkontext, also auf unsere ursprüngliche Zeile! Und dafür gibt es eine Funktion:

EARLIER() und EARLIEST()

Diese Funktionen scheinen schwierig zu verstehen sein – sind sie aber nicht. Im Beispiel benötigen wir Zugriff auf unseren umgebenden Zeilenkontext – genau dafür gibt es die Funktion EARLIER(). Wir schreiben unsere Rangfolgen-Funktion um:

Wir sagen damit explizit, dass der Nettowert der aktuell betrachteten Zeile nicht mit sich selbst, sondern bitte mit der Zeile laut umgebenden Zeilenkontext verglichen werden soll. Und damit am Ende die Rangfolge nicht bei “Null” anfängt, addieren wir am Schluss noch eine 1: EARLIER() Da man Funktionen auch schachteln kann, kann man bei EARLIER als zweiten, optionalen Parameter  angeben, wie viele Zeilenkontexte er überspringen soll in der aktuellen Schachtelung. Und als Vereinfachung haben wir EARLIEST() – die Funktion gibt einfach den äußersten Zeilenkontext zurück.