为什么写这篇

在公司给财务部同事分享 PowerBI 时,我发现一个问题:很多人会用 PowerBI 画图,但不会建模。

拖一个柱状图、拉一个折线——这些操作几小时就学会了。但真正让报表"活起来"的是背后的数据模型:M 函数怎么写、表之间怎么关联、度量值怎么算。这些东西不懂,每次换数据源都要重做一遍。

这篇文章把我在华帝做财务看板时的建模经验整理出来,希望能帮到同样在学 PowerBI 的财务同行。

一、数据建模的核心概念

先理解三个东西,这是整个 PowerBI 建模的基础:

概念 是什么 类比
PowerQuery(M 语言) 数据清洗和转换,在数据进 PowerBI 之前处理 洗菜切菜
关系建模 多张表之间怎么关联(一对多、多对一) 搭积木
DAX 度量值 写计算公式,计算毛利率、增长率等指标 菜谱公式

一个完整的 PowerBI 项目,数据流向是这样的:

原始数据(Excel/CSV/数据库/API)
        ↓
   PowerQuery 清洗(M 函数)
        ↓
   数据模型(建表关系)
        ↓
   DAX 度量值(写业务指标)
        ↓
   可视化报告(图表/看板)

二、PowerQuery M 函数实战

M 语言是 PowerQuery 的内置脚本语言。每次你在 PowerQuery 编辑器里点按钮,背后都在生成 M 代码。

常用 M 函数

1. 合并查询(JOIN)

两张表通过关键字段关联,类似 SQL 的 JOIN:

1
2
3
4
5
6
7
8
9
let
    Source = Table.NestedJoin(
        利润表, {"报告期"}, 
        资产负债表, {"报告期"}, 
        "资产负债表", JoinKind.LeftOuter
    ),
    #"Expanded" = Table.ExpandTableColumn(Source, "资产负债表", {"资产总计", "负债合计"})
in
    #"Expanded"

2. 逆透视(把宽表变长表)

财务系统中导出的数据经常是"宽表"——每个月一列。用逆透视转成标准数据表:

1
2
3
4
5
6
let
    Source = Excel.Workbook(File.Contents("费用明细.xlsx")),
    数据 = Source{[Name="Sheet1"]}[Data],
    逆透视 = Table.UnpivotOtherColumns(数据, {"部门", "费用类别"}, "月份", "金额")
in
    逆透视

3. 分组聚合

按部门汇总费用:

1
2
3
4
5
6
7
let
    Source = 费用明细,
    分组 = Table.Group(Source, {"部门"}, {
        {"费用合计", each List.Sum([金额]), type number}
    })
in
    分组

4. 日期处理

生成完整的日期表,财务分析的必需品:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
let
    StartDate = #date(2020,1,1),
    EndDate = #date(2026,12,31),
    日期列表 = List.Dates(StartDate, Duration.Days(EndDate - StartDate) + 1, #duration(1,0,0,0)),
    转表 = Table.FromList(日期列表, Splitter.SplitByNothing(), {"日期"}),
    加列 = Table.AddColumn(转表, "年", each Date.Year([日期])),
    加月 = Table.AddColumn(加列, "月", each Date.Month([日期])),
    加季 = Table.AddColumn(加月, "季度", each "Q" & Number.ToText(Date.QuarterOfYear([日期])))
in
    加季

三、DAX 度量值速查

DAX(Data Analysis Expressions)是 PowerBI 的计算语言,类似 Excel 公式但更强大。

财务分析常用 DAX

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 毛利率
毛利率 = DIVIDE(
    SUM(利润表[营业收入]) - SUM(利润表[营业成本]),
    SUM(利润表[营业收入])
)

// 净利率
净利率 = DIVIDE(SUM(利润表[净利润]), SUM(利润表[营业收入]))

// 收入同比
收入同比 = 
VAR 本期收入 = SUM(利润表[营业收入])
VAR 去年同期 = CALCULATE(
    SUM(利润表[营业收入]),
    SAMEPERIODLASTYEAR(日期表[日期])
)
RETURN DIVIDE(本期收入 - 去年同期, 去年同期)

// 费用率
管理费用率 = DIVIDE(SUM(费用表[管理费用]), SUM(利润表[营业收入]))

// 累计值(YTD)
YTD收入 = TOTALYTD(SUM(利润表[营业收入]), 日期表[日期])

DAX 核心概念

  • CALCULATE:DAX 的灵魂函数,在特定上下文中计算。比如"去年同期的收入"
  • FILTER:过滤条件,“只看华帝品牌的收入”
  • DIVIDE:安全除法,防止除零错误(比直接写 / 好)
  • VAR:定义变量,让长公式更好读、更易调试

四、建模实战:一个财务看板的数据模型

以在华帝做的财务分析看板为例,数据模型长这样:

日期表(日期维度)
    │
    ├─→ 利润表(营业收入、营业成本、净利润)
    │        一对多关系:日期表[日期] → 利润表[报告期]
    │
    ├─→ 费用表(管理费用、销售费用、财务费用)
    │        一对多关系:日期表[日期] → 费用表[月份]
    │
    └─→ 现金流量表
             一对多关系:日期表[日期] → 现金流量表[报告期]

建模原则:

  1. 所有数据表通过日期表关联——不要直接表对表连,所有时间相关的分析都基于日期维度
  2. 一个字段一个职责——费用表和利润表通过日期关联,而不是通过部门、项目等
  3. 度量值统一写在一个地方——不要分散在各张表里,建立一个"度量值"表集中管理所有 DAX 公式

五、和一些小建议

  1. 用 PowerQuery 做数据清洗,不要手动改——今天你手动删了一行,下周同事更新源文件时又要重做。M 函数写好的清洗规则可以反复用

  2. 度量值命名用中文——因为看报告的领导看不懂"GrossMargin",“毛利率"大家都懂

  3. 先建模再画图——很多人一上来直接拖图表,数据源一换全崩。模型搭好了,换数据源只需要刷新,图表自动更新

  4. PowerQuery 和 Excel 不是一个东西——虽然界面长得像,但 PowerQuery 支持的数据量和复杂度远超 Excel

总结

写代码不是程序员的事。在财务数字化时代,PowerQuery M 函数 + DAX 度量值就是财务人的"新算盘”——你会了这套工具,手动做报表的人还在加班复制粘贴,你已经点一下刷新就可以下班了。

这个看板的完整数据链路是:AkShare(Python 自动采集)→ PowerQuery(M 函数清洗)→ PowerBI(DAX 度量值 + 可视化报告),全流程零手工操作。

如果你也在学 PowerBI,或者想搭类似的财务看板,欢迎交流:1649219364@qq.com