W dzisiejszym artykule chciałbym powiedzieć Wam parę słów na temat tego w jaki sposób zbudować Current Selection Box czyli miejsce gdzie będą wyświetlane nasze bieżące selekcje. Serdecznie zapraszam do lektury.
Seleciton Box jest znanym tworem szczególnie w narzędziach takich jak np. QlikView gdzie funkcjonalność ta jest dostępna natywnie.
W Power BI nie mamy takiej wizualizacji z pudełka, ale mamy możliwość zbudowania sobie czegoś takiego przy pomocy dostępnych narzędzi. Sama funkcjonalność nie jest zbyt trudna w implementacji, jednak wymaga wyjaśnienia kilku aspektów co zamierzam zrobić w ramach tego artykułu. Zanim przejdziemy do meritum spójrzmy na model użyty w tym artykule, który został stworzony za pomocą tabeldostępnych w AdventureWorksDW:
Aby móc wizualizować selekcje to musimy posiadać coś do sterowania nimi, dlatego też w warstwie raportowej stworzyłem kilka slicerów, które przedstawiają się w następujący sposób:
Mając już gotowe slicery możemy przejść do implementacji. Pierwszym krokiem do budowy okna selekcji jest znalezienie metody na wyświetlenie aktualnie wybranych atrybutów na naszych slicerach. Sposobów aby tego dokonać jest kilka i prawie wszystkie opierają się na języku DAX. Pierwszym z nich jest funkcja SELECTEDVALUE, która w swojej konstrukcji jest bardzo prosta i sprowadza się do podania atrybutu, który chcemy śledzić jako parametru. Poniżej znajduje się jej wywołanie sprawdzające wybraną wartość dla atrybutu DimProduct[Class]:
Selected Class= SELECTEDVALUE(DimProduct[Class])
Aby zobaczyć jej działanie dodałem na pole raportu kartę z wyżej przedstawioną miarą:
Otrzymaliśmy wartość pustą (BLANK) ponieważ funkcja SELECTEDVALUE może zwracać dwie wartości:
- BLANK – jeśli nic nie zostało wybrane lub wybrana została więcej niż jedna wartość,
- wybraną wartość atrybutu jeśli tylko jedna została wybrana.
Problemem tej funkcji jest właśnie wartość BLANK w momencie wyboru więcej niż jednej wartości ale również jej zachowanie w przypadku filtracji innych atrybutów. Poniżej możecie zauważyć, że jeśli nic nie wybraliśmy na DimProduct[Class] ale została tam jedna wartość ze względu na filtrację na innych atrybutach to SELECTEDVALUE zwórci właśnie tą jedną wartość:
SELECTEDVALUE jest przydatna w momencie gdy nasz slicer może przyjąć tylko jedną wartość, chociaż oczywiście możemy ją nieco podrasować i dodać np. obsługę w przypadku zaznaczenia więcej niż jednej wartości:
Selected Class = IF ( ISBLANK ( SELECTEDVALUE ( DimProduct[Class] ) ); "More than one"; SELECTEDVALUE ( DimProduct[Class] ) )
Dzięki czemu odzwierciedlimy w jakiś sposób aktualny stan slicera:
Oczywiście nawet w tym zapisie mamy kilka problemów ale rozwiążemy je nieco później korzystając z innego podejścia. Na ten moment myślę, że mamy świadomość jak działa wspomniana funkcja. Wiemy zatem w jaki sposób wyświetlić więcej jedną wybraną wartość odczytaną ze slicera, w jaki zatem sposób przechwycić wiele wartości? Używając kolejnej funkcji w DAX jaką jest CONCATENATEX. Funkcja ta przyjmuje kilka parametrów, w naszym zastosowaniu przedstawimy opcję z dwoma z nich, a mianowicie tabelę oraz separator:
Concatenated Color = CONCATENATEX(VALUES(DimProduct[Color]);DimProduct[Color];",")
Po przeciągnięciu na kartę otrzymaliśmy następujący rezultat:
Wybrane wartości atrybutu DimProduct[Color] oddzielone przez nas wybranym separatorem, wygląda to naprawdę dobrze. Zobaczmy działanie w praktyce:
Również w tym przypadku mamy kilka problemów jak np.:
- w przypadku filtracji krzyżowej na innych slicerach wpływa to na nasz odczyt,
- CONCATENATEX jest iteratorem tak więc wyświetla w linii wszystkie wartości podane jako pierwszy parametr co na dużych zbiorach może być problemem wydajnościowym,
- w przypadku większych zbiorów nie jesteśmy w stanie wyświetlić wszystkich zaznaczonych wartości.
Część z tych problemów możemy oczywiście przezwyciężyć. Wyobraźmy sobie sytuację w której chcemy wyświetlić jedynie pierwsze trzy wybrane wartości oraz liczbę pozostałych, których wyświetlić nie możemy. Opracowanie takiej miary sprowadza się do odpowiedniego użycia COUNTROWS oraz TOPN:
Concatenated Colors = VAR vValue = COUNTROWS ( VALUES ( DimProduct[Color] ) ) VAR vValueToConcatenate = IF ( vValue <= 3; ""; " + " & vValue - 3 & " more" ) RETURN CONCATENATEX ( TOPN ( 3; VALUES ( DimProduct[Color] ) ); DimProduct[Color]; " ." ) & vValueToConcatenate
Z czym mamy tutaj do czynienia? Najpierw zliczamy ile zostało wybranych wartości atrybutu DimProduct[Color], a następnie wynik zachowujemy w zmiennej vValue. W dalszym kroku sprawdzamy czy wybranych jest więcej niż trzy wartości, jeśli tak to budujemy ciąg poprzez konkatenację liczby wybranych wartości pomniejszonej o 3 (bo trzy wartości wyświetlilimy bezpośrednio) + słówko ” more” – rezultat naszych działań zapisujemy w zmiennej vValueToConcatenate. Następnie CONCATENATEX wybiera 3 pierwsze wybrane wartości przy pomocy TOPN i w razie potrzeby podstawia zbudowany wcześniej string. Brzmi skomplikowanie? Wcale nie jest szczególnie gdy zobaczymy efekt działania:
Mamy coraz większy wachlarz możliwości, a to jeszcze nie koniec! Trzecia i chyba najprostsza możliwość nie wiąże się z DAX ale z samym Power BI! Każdy slicer w postaci listy ma jedną specjalną właściwość o nazwie Filter Restatement:
Daje ona dodatkową informację do nagłówka, a mianowicie wyświetla jaka wartość została wybrana lub informację, że wiele elementów zostało zaznaczonych:
Taka prosta funkcjonalność, a w wielu przypadkach może wystarczyć prawda? Co ciekawe niejako “z pudełka” jest ona odporna na filtrowanie krzyżowe czyli inne slicery nie wpływają na to co wyświetla się w nagłówku.
No dobrze znamy podstawowe możliwości przechwytywania zaznaczeń ze slicerów czyli:
- SELECTEDVALUE
- CONCATENATEX
- Filter Restatement
Do zbudowania specjalnej tabeli z wybranymi wartościami parametrów posłuży nam CONCATENATEX. Najpierw musimy stworzyć miarę, która obsłuży nam problemy z filtracją krzyżową oraz zaznaczeniem więcej niż jednego atrybutu. Miara ta dla atrybutu DimProduct[Class] wygląda następująco:
Selected Class = VAR vValue = COUNTROWS ( VALUES ( DimProduct[Class] ) ) VAR vValueToConcatenate = IF ( vValue <= 3; ""; " + " & vValue - 3 & " more" ) RETURN IF ( ISFILTERED ( DimProduct[Class] ); CONCATENATEX ( TOPN ( 3; VALUES ( DimProduct[Class] ) ); DimProduct[Class]; " ," ) & vValueToConcatenate; "-" )
Dodatkowym elementem, którego nie było wcześniej jest ISFILTERED (o którym swoją drogą już pisałem tutaj).W skrócie funkcja ta sprawdza czy atrybut był filtrowany bezpośrednio jeśli tak to cały opisany wcześniej mechanizm zostanie uruchomiony, jeśli nie to wyświetlimy kreskę “-“. W ten sam sposób stworzyłem miary dla kilku wybranych atrybutów i wszystko ułożyłem w tabeli:
Na powyższej prezentacji widać “białe strzałki”, które są niczym innym jak przyciskami z podpiętymi bookmarkami, które czyszczą selekcje na konkretnych slicerach.Oczywiście można całe rozwiązanie dodatkowo podrasować tak aby było bardziej dostosowane do konkretnych scenariuszy.
To by było na tyle na ten moment. Jak widzicie tworzenie Selection Boxa nie jest takie trudne jak mogłoby się wydawać.Wystarczy tak naprawdę znajomość dwóch, trzech funkcji DAX i chwila czasu na testy. Mam nadzieję, że znajdziecie zastosowania dla przedstawionej powyżej techniki.
- Avoiding Issues: Monitoring Query Pushdowns in Databricks Federated Queries - October 27, 2024
- Microsoft Fabric: Using Workspace Identity for Authentication - September 25, 2024
- Executing SQL queries from Azure DevOps using Service Connection credentials - August 28, 2024
Hi Adrian,
Great post, really helpful.
One thing I didn’t understand though: how did you put together the final attribute selection table? As in, how did you put the created measures vertically in one column? Can you help me with this please?
Many thanks,
Sukh
Hello Sukh,
It is just a standard matrix visual with values on rows.
Best Regards,
Adrian