
加入 PowerBI自己学 知识星球:下载源文件,边学边练;遇到问题,提问交流,有问必答。
P&L statement,损益表,也被叫做Income statement,是企业的三大核心财务报表之一,它从Revenue收入(因其位于报表顶部常被称作top line)到Net Income净收益/净利润(因其位于报表底部常被称作bottom line),反映公司在特定会计期间(如季度或年度)的收入、成本、费用以及最终盈利(或亏损)状况。通过将其与去年同期数据、预算目标以及滚动预测的不同版本进行对比,管理层可以追踪和分析企业的经营业绩(或财务表现)。
解决方案
在PowerBI中实现上方的P&L损益表,涉及以下知识点:
1 搭建星型架构模型。每个事实表(实际、预算、预测)分别与公共的日期表、科目表建立多对一关系。
参考<100例>2.1 天下大模型必作于小的星型架构。

2 报表中有些科目是计算得来的,不是数据源SUM来的,比如Revenue的total、Gross margin、Operating income、Operating income%等,因此不需要数据源提供这些数据。通过Switch度量值可以计算各个科目的数字,注意因为有跨科目之间的运算,会用到All函数清除外部筛选。同时,数据源中数字都是按正数记录的,报表中需要将支出类数字体现为负值,可以乘以科目表中的正负属性切换为负值。
Actual_Full_Accounts =
VAR _vm_revenue = CALCULATE([Actual], FILTER(ALL(Dim_Account), [Account_Group]="Revenue"))
VAR _vm_cost = CALCULATE([Actual], FILTER(ALL(Dim_Account), [Account_Group]="Cost"))
VAR _vm_expense = CALCULATE([Actual], FILTER(ALL(Dim_Account), [Account_Group]="Expense"))
VAR _vm_otherincome = CALCULATE([Actual], FILTER(ALL(Dim_Account), [Account_Group]="Other income, net"))
VAR _vm_provision = CALCULATE([Actual], FILTER(ALL(Dim_Account), [Account_Group]="Provision for income taxes"))
RETURN
SWITCH(SELECTEDVALUE(Dim_Account[Account]),
"Revenue", _vm_revenue,
"Cost", _vm_cost,
"Gross margin", _vm_revenue-_vm_cost,
"Gross margin%", DIVIDE(_vm_revenue-_vm_cost,_vm_revenue),
"Expense", _vm_expense,
"Operating income", _vm_revenue-_vm_cost-_vm_expense,
"Operating income%", DIVIDE(_vm_revenue-_vm_cost-_vm_expense,_vm_revenue),
"Net Income", _vm_revenue-_vm_cost-_vm_expense+_vm_otherincome-_vm_provision,
"Net Income%", DIVIDE(_vm_revenue-_vm_cost-_vm_expense+_vm_otherincome-_vm_provision,_vm_revenue),
[Actual]
) * SELECTEDVALUE(Dim_Account[+/-])
参考<100例>2.29 多个度量值合并为一个共有维度的度量值,2.10 核心函数CALCULATE。
3 不同科目的显示格式不同,比如Actual度量值,在Revenue科目是整数,在Gross margin%科目是百分数。使用度量值的动态格式可以在不改变底层数字的前提下,调整显示格式。以Variance_LY为例,格式字符串如下:
IF(CONTAINSSTRING(SELECTEDVALUE(Dim_Account[Account]), "%"), "#,##0.0 pts", "#,##0;(#,##0)")
参考<100例>2.38 数字单位的3种方案。

4 科目都是文本,按文本排序不符合要求,需要按照自定义的顺序排列。在创建科目表的时候,把序号列一并生成,然后使用按列排序功能排序。以Account_Group为例。
参考<100例>1.14 添加条件列,给维度添加排序列。

5 Actual用条形体现数字大小,这个用的是普通的条件格式数据条。
参考<100例>3.9 条件格式:用图标或形状制作红绿灯。

6 合计行需要统一的底色高亮显示出来。对每一个字段使用条件格式背景色,按照行标签返回颜色值,注意考虑到报表只有Account_Group不向下钻取的场景。
Color_Total = IF(SELECTEDVALUE(Dim_Account[Account]) IN {"Revenue","Cost","Gross Margin","Gross Margin%","Expense","Operating income","Operating income%","Net Income","Net Income%"} && ISINSCOPE(Dim_Account[Account]) || NOT ISINSCOPE(Dim_Account[Account]), "#EFF5FB")
参考<100例>3.10 条件格式:使用颜色度量值,实现多条件格式。


7 Δ在追踪中比较重要,因此在报表中,将其可视化为带颜色的条形,收入类正增长为绿色,支出类正增长为红色。因为颜色的特殊性,此处没有使用自带的条件格式,使用SVG矩形实现。以ΔLY为例。
Variance_LY_SVG_Bar =
VAR Pct = IF(NOT CONTAINSSTRING(SELECTEDVALUE(Dim_Account[Account]),"%"), DIVIDE(ABS([Variance_LY]), CALCULATE(MAXX(VALUES(Dim_Account[Account]),ABS([Variance_LY])), ALLSELECTED(Dim_Account)))) //度量值
VAR Width = 50 //宽度
VAR Height = 20 //高度
VAR Color = IF(SELECTEDVALUE(Dim_Account[+/-])=1, IF([Variance_LY]>=0,"#7ACA00","#FF0000"), IF([Variance_LY]>=0,"#FF0000","#7ACA00")) //根据项目类型区分不同的红绿颜色,绿色是好,红色是不好
Var Graph = IF([Variance_LY]>=0,
"<rect x='" & Width/2 & "' y='0' width='" & Width/2 *Pct & "' height='" & Height & "' fill='" & Color &"'/>",
"<rect x='" & Width/2-Width/2 *Pct & "' y='0' width='" & Width/2 *Pct & "' height='" & Height & "' fill='" & Color &"'/>"
)
RETURN "data:image/svg+xml;utf8, <svg xmlns='http://www.w3.org/2000/svg' width= '" & Width & "' height= '" & Height & "' >" & Graph & "</svg>"
8 Δ%的红绿色与Δ条形一致,使用颜色度量值可实现。以ΔLY%为例。
Color_Variance_LY = IF(SELECTEDVALUE(Dim_Account[+/-])=1, IF([Variance_LY]>=0,"#7ACA00","#FF0000"), IF([Variance_LY]>=0,"#FF0000","#7ACA00"))

9 通过切片器切换预算和滚动预测与实际做对比。基于B/F辅助表写一个Switch度量值,并使用新的按钮切片器融入到矩阵中。
B/F =
SWITCH(MAX('B/F'[B/F]),
"Budget", [Budget_Full_Accounts],
"Forecast", [Forecast_Full_Accounts]
)

10 时间段切片器可切换MTD和YTD,用计算组和时间智能函数可以实现对页面中度量值的整体控制。以YTD为例。
YTD = TOTALYTD(SELECTEDMEASURE(), Dim_Date[Date])
参考<100例>2.33 计算组用于衍生度量值、双层表头、切片器等。

1568

被折叠的 条评论
为什么被折叠?



