全網(wǎng)首發(fā) Power BI DAX 純原生高性能分頁矩陣

在 Power BI 中顯示一個大型的表,并不擅長,因為 Power BI 更傾向于制作高度聚合的可視化圖表,但如果就是希望做到可以顯示大篇幅的分頁表格怎么辦呢?本文就是來給出答案的。
背景說明
先看效果吧:

這是一個擁有上千筆訂單的表格,用戶只想看其中的一部分,并通過分頁實現(xiàn)。這里要實現(xiàn)的動態(tài)效果包括三點:
用戶可以自主決定每頁多少行數(shù)
用戶可以自主決定要顯示的頁碼
表格要進(jìn)行標(biāo)識當(dāng)前所在的行數(shù)
另外,以該案例為例,表格的顯示應(yīng)該依據(jù)具體的一個列排序,當(dāng)出現(xiàn)重復(fù)值的時候,依然可以平滑處理。在本案例中,是按照訂單日期排序的,但會出現(xiàn)訂單日期一樣的訂單,它們的排名是不同的,被有效錯開了。
當(dāng)然,最最重要的是:該解決方案必須具有通用性。
很顯然,以上全部已經(jīng)實現(xiàn)。
實現(xiàn)方法
該控件的實現(xiàn)方法非常巧妙。大致思路如下:
先給出動態(tài)可選的頁面控件,表現(xiàn)為:兩個切片器。
再給出表格是否在某個頁面的判斷,用度量值作為表格的篩選器。
再計算行號。
根據(jù)這個實現(xiàn)思路就可以逐步來構(gòu)建這個通用方法了。
分頁控件的構(gòu)造
可以用以下 DAX 構(gòu)建分頁控件如下:
PageControl =
// 請設(shè)置三個參數(shù)
VAR vOptionNumber = 10 // 有多少種每頁行數(shù)的選擇
VAR vUnit = 5 // 行數(shù)變化的單位基數(shù)
VAR vTotalPageNumber = 100 // 頁面數(shù)
// 以下代碼無需修改
RETURN
GENERATEALL(
ADDCOLUMNS(
SELECTCOLUMNS( GENERATESERIES( 1 , vOptionNumber ) , "OptionNumber" , [Value] ) ,
"RowsPerPage" , [OptionNumber] * vUnit ,
"RowsPerPageName" , [OptionNumber] * vUnit & " 行/頁"
) ,
VAR vIDList =
SELECTCOLUMNS(
GENERATESERIES( 1 , vTotalPageNumber * [RowsPerPage] , 1 ) , "Row" , [Value]
)
VAR vPageList =
ADDCOLUMNS(
vIDList ,
"PageNumber" , INT( ( [Row] - 1 ) / [RowsPerPage]) + 1 ,
"PageName" , "第 " & INT( ( [Row] - 1 ) / [RowsPerPage] ) + 1 & " 頁"
)
RETURN vPageList
)這是一個模板,用戶僅僅只需要改變參數(shù)設(shè)置,就可以自動完成。
用度量值做篩選判斷
用度量值做篩選在很多場景中,其實是一個重要的技巧,這里正好用到這個技巧,如下:

關(guān)鍵是如何構(gòu)建這個度量值,用 DAX 實現(xiàn)如下:
PageControl.IsInPage =
VAR vRowMin = MIN( PageControl[Row] )
VAR vRowMax = MAX( PageControl[Row] )
VAR vCurrentValue =
SELECTCOLUMNS( SUMMARIZE( 'Order' , 'Order'[OrderDate] , 'Order'[OrderID] ) ,
"@Value" , FORMAT( [OrderDate] , "yyMMdd" ) & [OrderID]
)
RETURN SWITCH( TRUE() ,
vCurrentValue >
MAXX(
TOPN(
vRowMax ,
SELECTCOLUMNS(
ALL( 'Order'[OrderDate] , 'Order'[OrderID] ) ,
"@Value" , FORMAT( [OrderDate] , "yyMMdd" ) & [OrderID]
) , [@Value] , ASC ) ,
[@Value]
) , "No" ,
vCurrentValue <
MAXX(
TOPN(
vRowMin ,
SELECTCOLUMNS(
ALL( 'Order'[OrderDate] , 'Order'[OrderID] ) ,
"@Value" , FORMAT( [OrderDate] , "yyMMdd" ) & [OrderID]
) , [@Value] , ASC ) ,
[@Value]
) , "No" ,
"Yes"
)沒有錯,根據(jù)業(yè)務(wù)邏輯中的按照訂單日期進(jìn)行排序,在排序相同時這里巧妙地借用訂單號來進(jìn)一步比較,就可以確保排序的唯一性了。
顯示行號
對當(dāng)前的表格顯示行號也是非常重要的,用 DAX 實現(xiàn)度量值如下:
PageControl.RowNumber =
VAR vRowNumberStartInPage = MIN( PageControl[Row] )
VAR vCurrentValue =
SELECTCOLUMNS( SUMMARIZE( 'Order' , 'Order'[OrderDate] , 'Order'[OrderID] ) ,
"@Value" , FORMAT( [OrderDate] , "yyMMdd" ) & [OrderID]
)
VAR vTableView =
CALCULATETABLE(
ADDCOLUMNS(
SUMMARIZE( 'Order' , 'Order'[OrderDate] , 'Order'[OrderID] ) ,
"@Value" , FORMAT( [OrderDate] , "yyMMdd" ) & [OrderID]
)
,
ALLSELECTED( )
)
RETURN vRowNumberStartInPage + RANKX( vTableView , [@Value] , vCurrentValue , ASC ) - 1沒有錯,這里用到了我們?nèi)W(wǎng)首發(fā)的 Power BI DAX 視圖層計算技巧,并借助頁面信息,將計算僅僅控制在一個頁面的范圍,進(jìn)一步降低運算量級,提升性能。
總結(jié)
通過掌握《BI 真經(jīng)》, 也就掌握了 DAX 思考問題的真諦,用《BI 真經(jīng)》打好的堅實基礎(chǔ)的確可以超越 Power BI 本身的限制,盡量將可塑性很強(qiáng)的 DAX 發(fā)揮到極限。本案例方法非常巧妙,但還有兩個點要進(jìn)一步思考:
其實對于大型表格的顯示會遇到密集計算的問題進(jìn)而導(dǎo)致性能問題,本案例源文件已經(jīng)用額外的技巧破除了一些限制,但這里限于篇幅就不再展開。
本案例僅僅展示了按照基表的列進(jìn)行排序分頁的情況,如果是按照度量值的大小來排序,要做一定調(diào)整。
這兩個問題就留給讀者進(jìn)一步探索了。您大可復(fù)制粘貼上述 DAX 表達(dá)式來實現(xiàn)強(qiáng)大的通用分頁控件。如果您還沒有堅實的 DAX 基礎(chǔ),趕快系統(tǒng)化學(xué)習(xí)起來吧。


在訂閱了BI佐羅講授的《BI真經(jīng)》之《BI進(jìn)行時》課程區(qū),除了可以下載本文案例,還可以觀看視頻講解。

讓數(shù)據(jù)真正成為你的力量
Create value through simple and easy with fun by PowerBI
Excel BI | DAX Pro | DAX 權(quán)威指南 | 線下VIP學(xué)習(xí)
掃碼與PBI精英一起學(xué)習(xí),驗證碼:data2021
PowerBI MVP 帶你正確而高效地學(xué)習(xí) PowerBI
點擊“閱讀原文”,即刻開始
↙
