Original-Blog von Imke Feldmann auf TheBIccountant.com
Expression.Evaluate ist ein Schweizer Taschenmesser unter den Power-BI-Werkzeugen. Es gibt eine Vielzahl an Anwendungsmöglichkeiten – zum Beispiel können Sie sich wiederholende Aufgaben durchführen ohne Funktionen zu benutzen, und in manchen Fällen kann Expression.Evaluate sogar rekursive Operationen ersetzen. In diesem Artikel beschränken wir uns jedoch auf eine recht einfache Aufgabe:
Wenn Sie nur die Zeilen filtern möchten, in denen keine Felder oder Spalten leer sind, können Sie entweder Nicht-Null-Filter an jede einzelne Spalte übergeben (was aufwändig und nicht dynamisch ist), transponieren oder eine Index-Spalte hinzufügen, entpivotieren und dann weiter filtern: Beides kann jedoch die Performance bei großen Tabellen herunterziehen.
Expression.Evaluate zu benutzen, ist eine dynamische Herangehensweise, die Sie nicht zwingt Ihre Ursprungstabelle zu transformieren oder Ihre Spalten direkt zu benennen: Es nimmt einen Text-String auf und führt ihn so aus, als ob Sie ihn von Hand in die Formel geschrieben hätten. Wenn Sie es schaffen, diesen Textstring dynamisch zu erzeugen entsprechend den unterschiedlichen Tabellen, die eingespielt werden, sorgt Expression.Evaluate dafür, dass diese einzelnen Statements dementsprechend ausgeführt werden.
Für eine Tabelle, die Spalte “A“ und „B“ enthält, würde das Filter-Statement also so aussehen:
FilteredTable = Table.SelectRows(Source, each [A] <> null and [B] <> null)
Und so für eine Tabelle mit den Spalten „You“, „should“, „know“, „that“:
FilteredTable = Table.SelectRows(Source, each [You] <> null and [should] <> null and[know] <> null and [that] <> null)
Man könnte das Statement so aufrufen:
FilteredTable = Table.SelectRows(Source, each Expression.Evaluate(Expression))
Aber wie kreiert man den Expression.Evaluate-Textstring nun automatisch?
Wenn wir eine Liste mit allen zu verändernden Items hätten, könnten wir sie einfach kombinieren, indem wir „and “ als Combiner benutzen: Text.Combine(List, “and “)
Als Startpunkt für die Liste können wir den Spaltennamen (Table.ColumnNames) nehmen und sie in eine Tabelle transferieren:
Dann einfach eine Spalte hinzufügen, die die anderen Text-Teile einfügt:
Table.AddColumn(Custom1, “Text”, each “[“&[Column1]&”] <> null”)
Das erstellt eine neue Spalte, die die Text-Teile für unseren String enthält:
Die Expression wird dann also so erstellt:
So weit zum lustigen Teil: Wenn Sie dies jetzt allerdings ausführen, erwartet Sie folgende Fehlermeldung:
Diese Fehlermeldung liegt an der fehlenden Definition der Umgebung, wie in dem oben bereits verlinkten Artikel von Chris Webb beschrieben. In diesem Fall ist das relativ einfach zu lösen: [ _ = _ ].
Das ergibt dann also:
Table.SelectRows(Source, each Expression.Evaluate(Expression, [ _=_ ]))
Wie Sie in Chris Webbs aktuellem Blogpost lesen können, erstellt dieser Unterstrich eine Art Zeilen-Kontext, indem er alle Werte der aktuellen Zeile übergibt. In vielen Fällen kann er weggelassen werden, hier brauchen wir ihn aber.
Es war dieser Blogpost von Ivan Bond, der mir die ungeheuren Möglichkeiten von Expression.Evaluate vor Augen geführt hat. Allerdings habe ich bereits einige potentielle Nachteile erkennen können: Vielleicht hören Sie auf nach eleganteren Lösungen wie z.B. einigen bislang unerkannten M-Funktionen zu suchen, weil Sie es einfach Expression.Evaluate-coden können. Alles hat seinen Preis ;) .
Geschrieben von Imke Feldmann
Brauchen Sie noch einen Xpertenrat?