前言
这些自定义的功能函数将提供各种标准业务逻辑函数或功能模块函数,比如新老客查找、帕累托分析、重复值排名等各种功能函数。通过这些模块化的功能函数,可以像搭积木一样,让报表的开发更加简单高效。
使用方式
方式一:DAX查询
复制以下DAX查询代码,粘贴到PowerBI的查询视图中运行,即可导入功能函数库。
关于每个函数的具体语法与介绍,请参考左边菜单栏的具体函数页面。
DEFINE
/// 返回帕累托分析的ABC分类。第一参数:任意返回表的表达式,第二参数:任意标量表达式,将在外部计值环境和第一参数提供的行上下文中计值。将迭代第一参数的表的每一行,计算第二参数的表达式,并以第二参数在外部计值环境中的结果为当前值,计算出大于等于当前值的累计值的占比,再基于累计占比计算ABC分类。参数 thresholdA 和 thresholdB 分别表示 A 类与 B 类的累计占比阈值,通常设置为 A=0.8、B=0.9,即:累计占比在 0.8 以内为 A 类,在 0.8~0.9 之间为 B 类,其余为 C 类。注:如果当前值(第二参数在外部计值环境中的结果)为空则直接返回空值
FUNCTION XF.Analysis.ABCClass = (tbl:table,expression:expr,thresholdA:double,thresholdB:double) =>
VAR CurrentVal = expression
RETURN
IF(thresholdA>=thresholdB || thresholdB>=1 || thresholdA<0,
ERROR("ABC阈值参数的范围错误!"),
IF(NOT ISBLANK(CurrentVal),
VAR TempTbl = ADDCOLUMNS(tbl,"@Val",expression)
VAR TotalVal = SUMX(TempTbl,[@Val])
VAR CumulativeSum =
IF(MAXX(TempTbl,[@Val])<CurrentVal,
TotalVal,
SUMX(FILTER(TempTbl,[@Val] >= CurrentVal),[@Val])
)
VAR CumPct = DIVIDE(CumulativeSum,TotalVal)
RETURN
MID("ABC",RANKX({thresholdA,thresholdB,1},[Value],CumPct,ASC),1)
)
)
/// 返回帕累托分析的ABC分类,这是XF.Analysis.ABCClass函数的精确版本,用于要累计的值存在重复时的场景,该函数将逐个处理重复值以得到不同的累计值。注意:该函数的实现使用窗口函数来定位当前值,将以tbl参数作为窗口函数的relation参数,使用时需要满足窗口函数的限制。最佳实践:将要累计的维度字段作为tbl参数
FUNCTION XF.Analysis.ABCClassExact = (tbl:table,expression:expr,thresholdA:double,thresholdB:double) =>
VAR CurrentVal = expression
RETURN
IF(thresholdA>=thresholdB || thresholdB>=1 || thresholdA<0,
ERROR("ABC阈值参数的范围错误!"),
IF(NOT ISBLANK(CurrentVal),
VAR TempTbl = ADDCOLUMNS(tbl,"@Val",expression)
VAR TotalVal = SUMX(TempTbl,[@Val])
VAR CumulativeSum =
IF(MAXX(TempTbl,[@Val])<CurrentVal,
TotalVal,
SUMX(
WINDOW(1,ABS,0,TempTbl,ORDERBY([@Val],DESC)),
[@Val]
)
)
VAR CumPct = DIVIDE(CumulativeSum,TotalVal)
RETURN
MID("ABC",RANKX({thresholdA,thresholdB,1},[Value],CumPct,ASC),1)
)
)
/// 判断在tbl参数中是否所有行都满足conditions参数指定的条件,类似SQL的ALL运算符,conditions参数为布尔表达式,将在tbl参数的行上下文与外部计值环境中计值。如果tbl参数为空表,则返回TRUE
FUNCTION XF.Analysis.AllTrue = (tbl:table,conditions:expr) =>
VAR TotalCount = COUNTROWS(tbl)
VAR TrueCount = COUNTROWS(FILTER(tbl,conditions))
RETURN
TotalCount=TrueCount
/// 判断在tbl参数中是否存在至少一行满足conditions参数指定的条件,类似SQL的ANY运算符,conditions参数为布尔表达式,将在tbl参数的行上下文与外部计值环境中计值。如果tbl参数为空表,则返回FALSE
FUNCTION XF.Analysis.AnyTrue = (tbl:table,conditions:expr) => NOT ISEMPTY(FILTER(tbl,conditions))
/// 将表达式的值自动格式化成合适的单位(无单位,K:千,M:百万,B:十亿),isFormat参数用于声明该函数是否用于度量值的动态格式化表达式中,该函数根据使用位置进行了适配,1:用于动态格式化表达式,0:用于普通度量值等表达式(将以文本类型返回格式化后的值)
FUNCTION XF.Analysis.AutoUnit = (expression:scalar,isFormat:int64) =>
IF(NOT isFormat IN {0,1},
ERROR("isFormat参数的可选取值仅为0或1"),
VAR Val = expression
VAR ValFormat =
SWITCH(
TRUE(),
ABS(val)<1E3,FORMAT(val,"#,##0.0"), // 个位,无单位
ABS(val)<1E6,FORMAT(val/1E3,"#,##0.0K"), // 千位,显示为K
ABS(val)<1E9,FORMAT(val/1E6,"#,##0.0M"), // 百万,显示为M
FORMAT(val/1E9,"#,##0.0B") // 十亿,显示为B
)
RETURN
IF(isFormat=1,
""""&ValFormat&""";"""&ValFormat&"""",
ValFormat
)
)
/// 通用分箱/桶函数,适用于年龄分组、客户价值分组等分箱场景,将根据ranges参数定义的阈值(左闭右开区间),查找expression参数的结果所在的区间,并返回labels参数中对应区间的标签。expression参数:任意标量表达式。ranges参数:阈值字符串,用分号隔开,例如 "0;100;200",其对应的区间为:[0,100)、[100,200)、≥200。labels参数:区间名称字符串,用分号隔开,例如 "Low;Medium;High",将按顺序与ranges参数的区间一一对应。注意:labels参数的标签中不能出现分号与竖杠。另外,若expression参数的值为空 或 小于定义的区间最小边界,则将返回空值
FUNCTION XF.Analysis.BucketByRange = (expression:expr,ranges:string,labels:string) =>
VAR CurVal = expression
VAR RangeList =
VAR TransToPath = SUBSTITUTE(ranges,";","|")
RETURN
ADDCOLUMNS(
GENERATESERIES(1,PATHLENGTH(TransToPath)),
"RangeNbr",PATHITEM(TransToPath,[Value])*1
)
VAR LabelList =
VAR TransToPath = SUBSTITUTE(labels,";","|")
RETURN
ADDCOLUMNS(
GENERATESERIES(1,PATHLENGTH(TransToPath)),
"Label",PATHITEM(TransToPath,[Value])
)
VAR RangeCount = COUNTROWS(RangeList)
VAR LabelCount = COUNTROWS(LabelList)
VAR CheckRangeCorrect =
NOT ISEMPTY(
FILTER(
ADDCOLUMNS(
RangeList,
"PrevRangeNbr",
VAR CurrIndex = [Value]
RETURN
MAXX(FILTER(RangeList,[Value]=CurrIndex-1),[RangeNbr])
),
[RangeNbr]<=[PrevRangeNbr] && [Value]>1
)
)
RETURN
IF(RangeCount<>LabelCount || CheckRangeCorrect,
ERROR("ranges参数与labels参数的区间数量不匹配,或ranges参数的区间定义顺序不正确!"),
IF(NOT ISBLANK(CurVal) && CurVal>=MINX(RangeList,[RangeNbr]),
VAR BucketIndexReverse = RANKX(RangeList,[RangeNbr],CurVal,DESC,Dense)
VAR BucketIndex = RangeCount - BucketIndexReverse + 1
RETURN
MAXX(FILTER(LabelList,[Value]=BucketIndex),[Label])
)
)
/// 统计在tbl参数中满足conditions参数指定的条件的行数,conditions参数为布尔表达式,将在tbl参数的行上下文与外部计值环境中计值
FUNCTION XF.Analysis.CountTrue = (tbl:table,conditions:expr) => COUNTROWS(FILTER(tbl,conditions))
/// 计算基于数值排序的累计值。第一参数:任意返回表的表达式,第二参数:任意标量表达式,将在外部计值环境和第一参数提供的行上下文中计值。将迭代第一参数的表的每一行,计算第二参数的表达式,并以第二参数在外部计值环境中的结果为当前值,最后根据sortOrder参数返回累计结果(0=降序/计算大于等于当前值的和,1=升序/计算小于等于当前值的和),注:如果当前值为空则直接返回空值,另外降序累计时如果当前值比任意明细都大则会返回明细之和
FUNCTION XF.Analysis.Cumulative = (tbl:table,expression:expr,sortOrder:int64) =>
VAR BaseVal = expression
VAR TempTbl = ADDCOLUMNS(tbl,"Val",expression)
RETURN
IF(NOT sortOrder IN {0,1},
ERROR("sortOrder参数的可选取值仅为0或1"),
IF(NOT ISBLANK(BaseVal),
IF(sortOrder>0,
SUMX(FILTER(TempTbl,[Val]<=BaseVal),[Val]),
IF(MAXX(TempTbl,[Val])<BaseVal,
SUMX(TempTbl,[Val]),
SUMX(FILTER(TempTbl,[Val]>=BaseVal),[Val])
)
)
)
)
/// 计算基于数值排序的累计值,这是XF.Analysis.Cumulative函数的精确版本,用于要累计的值存在重复时的场景,该函数将逐个处理重复值以得到不同的累计值。注意:该函数的实现使用窗口函数来定位当前值,将以tbl参数作为窗口函数的relation参数,使用时需要满足窗口函数的限制。最佳实践:将要累计的维度字段作为tbl参数
FUNCTION XF.Analysis.CumulativeExact = (tbl:table,expression:expr,sortOrder:int64) =>
VAR BaseVal = expression
VAR TempTbl = ADDCOLUMNS(tbl,"Val",expression)
RETURN
IF(NOT sortOrder IN {0,1},
ERROR("sortOrder参数的可选取值仅为0或1"),
IF(NOT ISBLANK(BaseVal),
IF(sortOrder>0,
SUMX(
WINDOW(1,ABS,0,TempTbl,ORDERBY([Val],ASC)),
[Val]
),
IF(MAXX(TempTbl,[Val])<BaseVal,
SUMX(TempTbl,[Val]),
SUMX(
WINDOW(1,ABS,0,TempTbl,ORDERBY([Val],DESC)),
[Val]
)
)
)
)
)
/// 计算基于数值排序的累计占比。第一参数:任意返回表的表达式,第二参数:任意标量表达式,将在外部计值环境和第一参数提供的行上下文中计值。将迭代第一参数的表的每一行,计算第二参数的表达式,并以第二参数在外部计值环境中的结果为当前值,最后根据sortOrder参数计算累计值(0=降序/计算大于等于当前值的和,1=升序/计算小于等于当前值的和),最终将累计值除以总计得出累计占比。注:如果当前值为空则直接返回空值
FUNCTION XF.Analysis.CumulativePct = (tbl:table,expression:expr,sortOrder:int64) =>
VAR BaseVal = expression
RETURN
IF(NOT sortOrder IN {0,1},
ERROR("sortOrder参数的可选取值仅为0或1"),
IF(NOT ISBLANK(BaseVal),
VAR TempTbl = ADDCOLUMNS(tbl,"Val",expression)
VAR TotalVal = SUMX(TempTbl,[Val])
VAR CumulativeSum =
IF(sortOrder>0,
SUMX(FILTER(TempTbl,[Val]<=BaseVal),[Val]),
IF(MAXX(TempTbl,[Val])<BaseVal,
TotalVal,
SUMX(FILTER(TempTbl,[Val]>=BaseVal),[Val])
)
)
RETURN
DIVIDE(CumulativeSum,TotalVal)
)
)
/// 计算基于数值排序的累计占比,这是XF.Analysis.CumulativePct函数的精确版本,用于要累计的值存在重复时的场景,该函数将逐个处理重复值以得到不同的累计值。注意:该函数的实现使用窗口函数来定位当前值,将以tbl参数作为窗口函数的relation参数,使用时需要满足窗口函数的限制。最佳实践:将要累计的维度字段作为tbl参数
FUNCTION XF.Analysis.CumulativePctExact = (tbl:table,expression:expr,sortOrder:int64) =>
VAR BaseVal = expression
RETURN
IF(NOT sortOrder IN {0,1},
ERROR("sortOrder参数的可选取值仅为0或1"),
IF(NOT ISBLANK(BaseVal),
VAR TempTbl = ADDCOLUMNS(tbl,"Val",expression)
VAR TotalVal = SUMX(TempTbl,[Val])
VAR CumulativeSum =
IF(sortOrder>0,
SUMX(
WINDOW(1,ABS,0,TempTbl,ORDERBY([Val],ASC)),
[Val]
),
IF(MAXX(TempTbl,[Val])<BaseVal,
TotalVal,
SUMX(
WINDOW(1,ABS,0,TempTbl,ORDERBY([Val],DESC)),
[Val]
)
)
)
RETURN
DIVIDE(CumulativeSum,TotalVal)
)
)
/// 统计出现次数超过1次的唯一值的数量,即:有多少个“项”是重复的,不忽略空值。第一参数:任意返回表的表达式,第二参数:任意标量表达式,将在外部计值环境和第一参数提供的行上下文中计值
FUNCTION XF.Analysis.DuplicatesCount = (tbl:table,expression:expr) =>
VAR ValList = SELECTCOLUMNS(tbl,"@Val",expression)
VAR Grouped = GROUPBY(ValList,[@Val],"@Freq",COUNTX(CURRENTGROUP(),1))
RETURN
COUNTROWS(FILTER(Grouped,[@Freq] > 1))
/// 返回在evalExpr参数最大值的那一行上的resultExpr参数的值,如果有多个最大值则返回resultExpr参数的值较大的那个
FUNCTION XF.Analysis.ItemAtMax = (tbl:table,evalExpr:expr,resultExpr:expr) =>
VAR TempTbl = ADDCOLUMNS(tbl,"_Eval",evalExpr,"_Res",resultExpr)
VAR TopRow = TOPN(1,TempTbl,[_Eval],DESC)
RETURN
MAXX(TopRow,[_Res])
/// 返回在evalExpr参数最小值的那一行上的resultExpr参数的值,如果有多个最小值则返回resultExpr参数的值较小的那个
FUNCTION XF.Analysis.ItemAtMin = (tbl:table,evalExpr:expr,resultExpr:expr) =>
VAR TempTbl = ADDCOLUMNS(tbl,"_Eval",evalExpr,"_Res",resultExpr)
VAR BottomRow = TOPN(1,TempTbl,[_Eval],ASC)
RETURN
MINX(BottomRow,[_Res])
/// 该函数可用于修复小计或总计不等于明细之和的问题,只需要传入对应度量值或表达式,以及当前视觉对象所使用的字段(行列标签、图例等能提供筛选的字段)。因为UDF不支持可选参数,故以函数后缀的数字来标识支持的字段数,请根据视觉对象所使用的字段数选择对应后缀的该函数
FUNCTION XF.Analysis.LetTotalEqualDetails_1 = (expression:expr,axisField:anyref) =>
SUMX(
VALUES(axisField),
CALCULATE(expression)
)
/// 该函数可用于修复小计或总计不等于明细之和的问题,只需要传入对应度量值或表达式,以及当前视觉对象所使用的字段(行列标签、图例等能提供筛选的字段)。因为UDF不支持可选参数,故以函数后缀的数字来标识支持的字段数,请根据视觉对象所使用的字段数选择对应后缀的该函数
FUNCTION XF.Analysis.LetTotalEqualDetails_2 = (expression:expr,axisField1:anyref,axisField2:anyref) =>
SUMX(
CROSSJOIN(
VALUES(axisField1),
VALUES(axisField2)
),
CALCULATE(expression)
)
/// 该函数可用于修复小计或总计不等于明细之和的问题,只需要传入对应度量值或表达式,以及当前视觉对象所使用的字段(行列标签、图例等能提供筛选的字段)。因为UDF不支持可选参数,故以函数后缀的数字来标识支持的字段数,请根据视觉对象所使用的字段数选择对应后缀的该函数
FUNCTION XF.Analysis.LetTotalEqualDetails_3 = (expression:expr,axisField1:anyref,axisField2:anyref,axisField3:anyref) =>
SUMX(
CROSSJOIN(
VALUES(axisField1),
VALUES(axisField2),
VALUES(axisField3)
),
CALCULATE(expression)
)
/// 该函数可用于修复小计或总计不等于明细之和的问题,只需要传入对应度量值或表达式,以及当前视觉对象所使用的字段(行列标签、图例等能提供筛选的字段)。因为UDF不支持可选参数,故以函数后缀的数字来标识支持的字段数,请根据视觉对象所使用的字段数选择对应后缀的该函数
FUNCTION XF.Analysis.LetTotalEqualDetails_4 = (expression:expr,axisField1:anyref,axisField2:anyref,axisField3:anyref,axisField4:anyref) =>
SUMX(
CROSSJOIN(
VALUES(axisField1),
VALUES(axisField2),
VALUES(axisField3),
VALUES(axisField4)
),
CALCULATE(expression)
)
/// 计算基于最后可见日期向前推算指定周期的移动平均值。参数:expression(标量表达式/度量值), dateColumn(日期表的日期列), period(回溯周期数,如3), interval(时间粒度,可选文本值:DAY, MONTH, QUARTER, YEAR)
FUNCTION XF.Analysis.MovingAverage = (expression:expr,dateColumn:anyref,period:int64,interval:string) =>
SWITCH(
interval,
"DAY",
AVERAGEX(
DATESINPERIOD(dateColumn,LASTDATE(dateColumn),-period,DAY),
CALCULATE(expression)
),
"MONTH",
AVERAGEX(
DATESINPERIOD(dateColumn,LASTDATE(dateColumn),-period,MONTH),
CALCULATE(expression)
),
"QUARTER",
AVERAGEX(
DATESINPERIOD(dateColumn,LASTDATE(dateColumn),-period,QUARTER),
CALCULATE(expression)
),
"YEAR",
AVERAGEX(
DATESINPERIOD(dateColumn,LASTDATE(dateColumn),-period,YEAR),
CALCULATE(expression)
)
)
/// 返回下一个非空值。将按tbl参数的所有字段升序排序,然后基于当前行查找其下一个expression参数不为空的行,然后返回该行所对应的expression参数的值。如果当前行的expression参数的值为空,则将直接返回空值。第一参数:任意返回表的表达式,第二参数:任意标量表达式,将在外部计值环境和第一参数提供的行上下文中计值。注意:该函数的实现使用窗口函数来定位当前值,将以tbl参数作为窗口函数的relation参数,使用时需要满足窗口函数的限制。最佳实践:将要排序的维度字段作为tbl参数,另外为避免顺序不正确,建议tbl参数只包含单个字段
FUNCTION XF.Analysis.NextNonBlankValue = (tbl:table,expression:expr) =>
VAR CurVal = expression
RETURN
IF(
NOT ISBLANK(CurVal),
VAR TempTbl = ADDCOLUMNS(tbl,"Val",expression)
VAR PreTbl = FILTER(WINDOW(1,REL,-1,ABS,TempTbl),NOT ISBLANK([Val]))
RETURN
MAXX(INDEX(1,PreTbl),[Val])
)
/// 计算占总计的百分比。第一参数:任意返回表的表达式,第二参数:任意标量表达式,将在外部计值环境和第一参数提供的行上下文中计值。将迭代第一参数的表的每一行,计算第二参数的表达式,并将结果汇总得到总计值,然后以第二参数在外部计值环境中的结果为当前值,最后将当前值除以总计得出占总计的百分比。注:如果当前值为空则直接返回空值
FUNCTION XF.Analysis.PctOfTotal = (tbl:table,expression:expr) =>
VAR CurVal = expression
RETURN
IF(
NOT ISBLANK(CurVal),
DIVIDE(CurVal,SUMX(tbl,expression))
)
/// 返回上一个非空值。将按tbl参数的所有字段升序排序,然后基于当前行查找其上一个expression参数不为空的行,然后返回该行所对应的expression参数的值。如果当前行的expression参数的值为空,则将直接返回空值。第一参数:任意返回表的表达式,第二参数:任意标量表达式,将在外部计值环境和第一参数提供的行上下文中计值。注意:该函数的实现使用窗口函数来定位当前值,将以tbl参数作为窗口函数的relation参数,使用时需要满足窗口函数的限制。最佳实践:将要排序的维度字段作为tbl参数,另外为避免顺序不正确,建议tbl参数只包含单个字段
FUNCTION XF.Analysis.PreNonBlankValue = (tbl:table,expression:expr) =>
VAR CurVal = expression
RETURN
IF(
NOT ISBLANK(CurVal),
VAR TempTbl = ADDCOLUMNS(tbl,"Val",expression)
VAR PreTbl = FILTER(WINDOW(1,ABS,-1,REL,TempTbl),NOT ISBLANK([Val]))
RETURN
MAXX(INDEX(-1,PreTbl),[Val])
)
/// 返回当前值在值列表中的连续排名,适用于要排名的值存在重复时的场景,该函数将逐个处理重复值以得到不同的排名,排名时忽略空值,sortOrder参数用于控制排名方向,0=降序,1=升序。注意:该函数的实现使用窗口函数来定位当前值,将以tbl参数作为窗口函数的relation参数,使用时需要满足窗口函数的限制。最佳实践:将要排名的维度字段作为tbl参数
FUNCTION XF.Analysis.RankByContinued = (tbl:table,expression:expr,sortOrder:anyref) =>
VAR BaseVal = expression
RETURN
IF(NOT ISBLANK(BaseVal),
VAR TempTbl = FILTER(ADDCOLUMNS(tbl,"Val",expression),NOT ISBLANK([Val]))
RETURN
ROWNUMBER(TempTbl,ORDERBY([Val],sortOrder))
)
/// 计算加权平均值。迭代第一参数的表的每一行,在其提供的行上下文与外部计值环境中计算第二参数(权重表达式)与第三参数(数值表达式),最后计算加权平均值。计算公式:SUMX(tbl,weight*val)/SUMX(tbl,weight)
FUNCTION XF.Analysis.WeightedAvg = (tbl:table,weightExpr:expr,valExpr:expr) =>
VAR TempTbl = ADDCOLUMNS(tbl,"@Weight",weightExpr,"@Val",valExpr)
VAR Numerator = SUMX(TempTbl,[@Weight] * [@Val])
VAR Denominator = SUMX(TempTbl,[@Weight])
RETURN
DIVIDE(Numerator,Denominator)
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的上年同期值
FUNCTION XF.Analysis.PY = (expression:expr,dateColumn:anyref) => CALCULATE(expression,DATEADD(dateColumn,-1,YEAR))
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的上季同期值
FUNCTION XF.Analysis.PQ = (expression:expr,dateColumn:anyref) => CALCULATE(expression,DATEADD(dateColumn,-1,QUARTER))
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的上月同期值
FUNCTION XF.Analysis.PM = (expression:expr,dateColumn:anyref) => CALCULATE(expression,DATEADD(dateColumn,-1,MONTH))
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式与上年同期值的同比增长率,YOY Pct = (CY-PY)/PY
FUNCTION XF.Analysis.YOY.Pct = (expression:expr,dateColumn:anyref) =>
VAR CurVal = expression
VAR PreVal = CALCULATE(expression,DATEADD(dateColumn,-1,YEAR))
RETURN
DIVIDE(CurVal-PreVal,PreVal)
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式与上年同期值的同比差值,YOY Gap = CY-PY
FUNCTION XF.Analysis.YOY.Gap = (expression:expr,dateColumn:anyref) =>
VAR CurVal = expression
VAR PreVal = CALCULATE(expression,DATEADD(dateColumn,-1,YEAR))
RETURN
CurVal-PreVal
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式与上季同期值的环比增长率,QOQ Pct = (CQ-PQ)/PQ
FUNCTION XF.Analysis.QOQ.Pct = (expression:expr,dateColumn:anyref) =>
VAR CurVal = expression
VAR PreVal = CALCULATE(expression,DATEADD(dateColumn,-1,QUARTER))
RETURN
DIVIDE(CurVal-PreVal,PreVal)
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式与上季同期值的环比差值,QOQ Gap = CQ-PQ
FUNCTION XF.Analysis.QOQ.Gap = (expression:expr,dateColumn:anyref) =>
VAR CurVal = expression
VAR PreVal = CALCULATE(expression,DATEADD(dateColumn,-1,QUARTER))
RETURN
CurVal-PreVal
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式与上月同期值的环比增长率,MOM Pct = (CM-PM)/PM
FUNCTION XF.Analysis.MOM.Pct = (expression:expr,dateColumn:anyref) =>
VAR CurVal = expression
VAR PreVal = CALCULATE(expression,DATEADD(dateColumn,-1,MONTH))
RETURN
DIVIDE(CurVal-PreVal,PreVal)
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式与上月同期值的环比差值,MOM Gap = CM-PM
FUNCTION XF.Analysis.MOM.Gap = (expression:expr,dateColumn:anyref) =>
VAR CurVal = expression
VAR PreVal = CALCULATE(expression,DATEADD(dateColumn,-1,MONTH))
RETURN
CurVal-PreVal
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的年初至今值
FUNCTION XF.Analysis._YTD = (expression:expr,dateColumn:anyref) => CALCULATE(expression,DATESYTD(dateColumn))
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的年初至今值的上年同期值
FUNCTION XF.Analysis._YTD.PY = (expression:expr,dateColumn:anyref) => CALCULATE(expression,DATEADD(DATESYTD(dateColumn),-1,YEAR))
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的年初至今值与上年同期值的同比增长率,YOY Pct = (CY-PY)/PY
FUNCTION XF.Analysis._YTD.YOY.Pct = (expression:expr,dateColumn:anyref) =>
VAR CurVal = CALCULATE(expression,DATESYTD(dateColumn))
VAR PreVal = CALCULATE(expression,DATEADD(DATESYTD(dateColumn),-1,YEAR))
RETURN
DIVIDE(CurVal-PreVal,PreVal)
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的年初至今值与上年同期值的同比差值,YOY Gap = CY-PY
FUNCTION XF.Analysis._YTD.YOY.Gap = (expression:expr,dateColumn:anyref) =>
VAR CurVal = CALCULATE(expression,DATESYTD(dateColumn))
VAR PreVal = CALCULATE(expression,DATEADD(DATESYTD(dateColumn),-1,YEAR))
RETURN
CurVal-PreVal
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的季初至今值
FUNCTION XF.Analysis._QTD = (expression:expr,dateColumn:anyref) => CALCULATE(expression,DATESQTD(dateColumn))
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的季初至今值的上年同期值
FUNCTION XF.Analysis._QTD.PY = (expression:expr,dateColumn:anyref) => CALCULATE(expression,DATEADD(DATESQTD(dateColumn),-1,YEAR))
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的季初至今值的上季同期值
FUNCTION XF.Analysis._QTD.PQ = (expression:expr,dateColumn:anyref) => CALCULATE(expression,DATEADD(DATESQTD(dateColumn),-1,QUARTER))
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的季初至今值与上年同期值的同比增长率,YOY Pct = (CY-PY)/PY
FUNCTION XF.Analysis._QTD.YOY.Pct = (expression:expr,dateColumn:anyref) =>
VAR CurVal = CALCULATE(expression,DATESQTD(dateColumn))
VAR PreVal = CALCULATE(expression,DATEADD(DATESQTD(dateColumn),-1,YEAR))
RETURN
DIVIDE(CurVal-PreVal,PreVal)
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的季初至今值与上年同期值的同比差值,YOY Gap = CY-PY
FUNCTION XF.Analysis._QTD.YOY.Gap = (expression:expr,dateColumn:anyref) =>
VAR CurVal = CALCULATE(expression,DATESQTD(dateColumn))
VAR PreVal = CALCULATE(expression,DATEADD(DATESQTD(dateColumn),-1,YEAR))
RETURN
CurVal-PreVal
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的季初至今值与上季同期值的环比增长率,QOQ Pct = (CQ-PQ)/PQ
FUNCTION XF.Analysis._QTD.QOQ.Pct = (expression:expr,dateColumn:anyref) =>
VAR CurVal = CALCULATE(expression,DATESQTD(dateColumn))
VAR PreVal = CALCULATE(expression,DATEADD(DATESQTD(dateColumn),-1,QUARTER))
RETURN
DIVIDE(CurVal-PreVal,PreVal)
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的季初至今值与上季同期值的环比差值,QOQ Gap = CQ-PQ
FUNCTION XF.Analysis._QTD.QOQ.Gap = (expression:expr,dateColumn:anyref) =>
VAR CurVal = CALCULATE(expression,DATESQTD(dateColumn))
VAR PreVal = CALCULATE(expression,DATEADD(DATESQTD(dateColumn),-1,QUARTER))
RETURN
CurVal-PreVal
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的月初至今值
FUNCTION XF.Analysis._MTD = (expression:expr,dateColumn:anyref) => CALCULATE(expression,DATESMTD(dateColumn))
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的月初至今值的上年同期值
FUNCTION XF.Analysis._MTD.PY = (expression:expr,dateColumn:anyref) => CALCULATE(expression,DATEADD(DATESMTD(dateColumn),-1,YEAR))
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的月初至今值的上季同期值
FUNCTION XF.Analysis._MTD.PQ = (expression:expr,dateColumn:anyref) => CALCULATE(expression,DATEADD(DATESMTD(dateColumn),-1,QUARTER))
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的月初至今值的上月同期值
FUNCTION XF.Analysis._MTD.PM = (expression:expr,dateColumn:anyref) => CALCULATE(expression,DATEADD(DATESMTD(dateColumn),-1,MONTH))
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的月初至今值与上年同期值的同比增长率,YOY Pct = (CY-PY)/PY
FUNCTION XF.Analysis._MTD.YOY.Pct = (expression:expr,dateColumn:anyref) =>
VAR CurVal = CALCULATE(expression,DATESMTD(dateColumn))
VAR PreVal = CALCULATE(expression,DATEADD(DATESMTD(dateColumn),-1,YEAR))
RETURN
DIVIDE(CurVal-PreVal,PreVal)
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的月初至今值与上年同期值的同比差值,YOY Gap = CY-PY
FUNCTION XF.Analysis._MTD.YOY.Gap = (expression:expr,dateColumn:anyref) =>
VAR CurVal = CALCULATE(expression,DATESMTD(dateColumn))
VAR PreVal = CALCULATE(expression,DATEADD(DATESMTD(dateColumn),-1,YEAR))
RETURN
CurVal-PreVal
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的月初至今值与上季同期值的环比增长率,QOQ Pct = (CQ-PQ)/PQ
FUNCTION XF.Analysis._MTD.QOQ.Pct = (expression:expr,dateColumn:anyref) =>
VAR CurVal = CALCULATE(expression,DATESMTD(dateColumn))
VAR PreVal = CALCULATE(expression,DATEADD(DATESMTD(dateColumn),-1,QUARTER))
RETURN
DIVIDE(CurVal-PreVal,PreVal)
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的月初至今值与上季同期值的环比差值,QOQ Gap = CQ-PQ
FUNCTION XF.Analysis._MTD.QOQ.Gap = (expression:expr,dateColumn:anyref) =>
VAR CurVal = CALCULATE(expression,DATESMTD(dateColumn))
VAR PreVal = CALCULATE(expression,DATEADD(DATESMTD(dateColumn),-1,QUARTER))
RETURN
CurVal-PreVal
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的月初至今值与上月同期值的环比增长率,MOM Pct = (CM-PM)/PM
FUNCTION XF.Analysis._MTD.MOM.Pct = (expression:expr,dateColumn:anyref) =>
VAR CurVal = CALCULATE(expression,DATESMTD(dateColumn))
VAR PreVal = CALCULATE(expression,DATEADD(DATESMTD(dateColumn),-1,MONTH))
RETURN
DIVIDE(CurVal-PreVal,PreVal)
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的月初至今值与上月同期值的环比差值,MOM Gap = CM-PM
FUNCTION XF.Analysis._MTD.MOM.Gap = (expression:expr,dateColumn:anyref) =>
VAR CurVal = CALCULATE(expression,DATESMTD(dateColumn))
VAR PreVal = CALCULATE(expression,DATEADD(DATESMTD(dateColumn),-1,MONTH))
RETURN
CurVal-PreVal
/// 基于当前计值环境中所筛选的日期范围,返回指定标量表达式的本周至今值,StartDayOfWeek参数用于指定每周的第一天,1:周日,2:周一
FUNCTION XF.Analysis._WTD = (expression:expr,dateColumn:anyref,startDayOfWeek:anyref) =>
VAR MaxDate = LASTDATE(dateColumn)
RETURN
CALCULATE(
expression,
DATESINPERIOD(dateColumn,MaxDate,-WEEKDAY(MaxDate,startDayOfWeek),DAY)
)
方式二:外部工具
还可以使用配套的PowerBI外部工具来导入已发布的所有自定义函数,如下图所示:

该外部工具会自动联网获取最新的DAX自定义函数列表,可搜索或选择要导入的DAX自定义函数,然后选择对应的PowerBI实例后,点击开始导入即可。
另外,该外部工具还支持导入SQLBI的DaxLib平台的函数,并支持本地函数库功能,而且除了下拉选择模式外还支持模糊搜索模式。
该外部工具的获取方式如下:
关于该外部工具的安装与使用方式,可阅读附带的 README.txt 文件,如下图所示:

其他
如果有任何问题或想法,欢迎在评论区提交你的需求与改进建议,一起完善该函数库!







