前言
这些自定义的图表函数使用HTML或SVG等语言进行扩展,每一个函数对应一种图表效果,可以通过函数参数来调整图表样式或效果。只需要传入度量值指标与相关样式参数,并放入HTML Content视觉对象或其他支持图像的视觉对象中,就能绘制出对应的图表。
需要注意,本图表函数库里的函数有两类,使用细节并不一致,具体如下:
1、HTML命名空间中的函数最终输出的是HTML代码,只能在支持显示HTML内容的视觉对象中使用,如HTML Content视觉对象。
2、SVG命名空间中的函数最终输出的是SVG代码,使用时需要先将度量值的数据类别设置成图像URL,然后可在任意能显示图像的视觉对象中使用,如矩阵、新卡片图、按钮切片器、HTML Content等视觉对象。
使用方式
方式一:DAX查询
复制以下DAX查询代码,粘贴到PowerBI的查询视图中运行,即可导入图表函数库。
关于每个函数的具体语法与介绍,请参考左边菜单栏的具体函数页面。
DEFINE
/// 同时展示指标值与同比值的卡片,同比值位于指标值同一行的右下角,将根据指标数值大小自动调整显示位置。MainValue参数:指标主值,MainColor参数:指标主值颜色,YoYValue参数:右下角同比值,YoYColor参数:同比值的颜色。注意:MainValue与YoYValue参数请传入格式化后的文本,该函数将原样展示传递的值。另外,如果同比值需要动态颜色,请在YoYColor参数中使用表达式来动态返回不同颜色
FUNCTION XF.HtmlChart.KPICard = (MainValue:string,MainColor:string,YoYValue:string,YoYColor:string) =>
VAR MainFontSize = "28px" // 主值字号(推荐28-40px,使用px单位保证基准尺寸)
VAR MainFontWeight = "600" // 主值字重(400=正常,600=半粗,700=加粗)
VAR YoYFontSize = "1em" // 同比值字号(推荐0.4-0.6em,基于主值字号的比例)
VAR YoYFontWeight = "600" // 同比值字重(通常比主值小100-200权重)
VAR HorizontalGap = "0.6em" // 水平间距(主值与同比值间距,推荐0.3-1em)
VAR VerticalAdjust = "0.15em" // 垂直微调(正值下移/负值上移,推荐±0.3em内)
RETURN
"<div class='xifeng' style='
display: flex; /* 启用flex布局 */
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
width: 100%; /* 撑满容器宽度 */
height: 100%; /* 撑满容器高度 */
line-height: 1; /* 消除行高影响 */
'>
<div style='
display: flex; /* 嵌套flex布局 */
align-items: baseline; /* 基线对齐 */
gap: " & HorizontalGap & "; /* 元素间距 */
transform: translateY( /* 垂直位置微调 */
" & VerticalAdjust & " /* 微调量(基于em单位) */
);
'>
<!-- 主值 -->
<span style='
font-size: " & MainFontSize & ";
font-weight: " & MainFontWeight & ";
color: " & MainColor & ";
line-height: 1; /* 防止行高影响 */
'>" & MainValue & "</span>
<!-- 同比值 -->
<span style='
font-size: " & YoYFontSize & ";
font-weight: " & YoYFontWeight & ";
color: " & YoYColor & ";
line-height: 1; /* 保持行高一致 */
white-space: nowrap; /* 防止换行 */
'>" & YoYValue & "</span>
</div>
</div>"
/// 根据expression参数的值的正负返回不同的上升或下降Icon,可用在矩阵/表格的条件格式图标中。可选的Icon图标有:1:实心圆,2:空心圆,3,五角星,4:上下斜箭头,5:上下三角。另外,颜色默认为:绿色:expression>0,红色:expression<0,黄色:expression=0
FUNCTION XF.SvgChart.ShapeIcon = (expression:scalar,icon:int64,size:int64) =>
VAR CurVal = expression
VAR Color_Green = "rgb(41, 175, 97)"
VAR Color_Yellow = "rgb(255, 192, 0)"
VAR Color_Red = "rgb(231, 76, 60)"
VAR ShowColor = SWITCH(TRUE(),CurVal>0,Color_Green,CurVal<0,Color_Red,CurVal=0,Color_Yellow)
VAR ShowIcon =
SWITCH(
Icon,
1,"●",
2,"○",
3,"★",
4,SWITCH(TRUE(),CurVal>0,"↗",CurVal<0,"↘",CurVal=0,"-"),
5,SWITCH(TRUE(),CurVal>0,"▲",CurVal<0,"▼",CurVal=0,"-"),
ERROR("Icon图标参数错误,请选择以下图标:1:实心圆,2:空心圆,3,五角星,4:上下斜箭头,5:上下三角")
)
RETURN
IF(NOT ISBLANK(CurVal),
"data:image/svg+xml;utf8,
<svg class='xifeng' xmlns='http://www.w3.org/2000/svg' version='1.1' height='100' width='100'>
<text x='50' y='50' font-size='"&size&"' fill='"&ShowColor&"' text-anchor='middle' dominant-baseline='central'>"&ShowIcon&"</text>
</svg>"
)
/// 在矩阵或表格中返回美化后的文本标签。textContent参数:用分隔符连接的文本标签,delimiter参数:分隔符,textSize参数:文本大小(建议10-14),textColor参数:文本颜色。将按分隔符拆分textContent参数,得到各个标签,然后以胶囊卡片的形式进行美化,可使用在矩阵或表格的值字段中。使用前提:将矩阵或表格的图形尺寸设置为:高20,宽512,并将对应度量值的分类设置为图形URL
FUNCTION XF.SvgChart.TextLabels = (textContent:string,delimiter:string,textSize:int64,textColor:string) =>
VAR CurText = SUBSTITUTE(SUBSTITUTE(textContent,delimiter,"|"),"&","&")
VAR Space = 15
VAR Width_Factor = 7
VAR TextWeight = "Bold"
VAR FillColor = Textcolor
VAR FillColorOpacity = 0.1
VAR TextList_AddIndex =
SELECTCOLUMNS(
GENERATESERIES(1,PATHLENGTH(CurText)),
"Text",PATHITEM(CurText,[Value]),
"Index",[Value]
)
VAR TextList_AddCumLen =
ADDCOLUMNS(
TextList_AddIndex,
"CumLen",
VAR CurIndex = [Index]
RETURN
SUMX(
FILTER(TextList_AddIndex,[Index]<=CurIndex),
LEN([Text])
)
)
VAR TagChart =
ADDCOLUMNS(
TextList_AddCumLen,
"Tag",
VAR CurIndex = [Index]
VAR CurText = [Text]
VAR CurCumLen = [CumLen]
RETURN
"<rect x='"&Width_Factor*(CurCumLen-LEN(CurText))+Space*(3*CurIndex-2)&"' y='0' rx='10' ry='10' width='"&Width_Factor*LEN(CurText)+Space*2&"' height='20'
fill='"&FillColor&"' fill-opacity='"&FillColorOpacity&"'/>
<text x='"&Width_Factor*(CurCumLen-LEN(CurText))+Space*(3*CurIndex-2)+(Width_Factor*LEN(CurText)+Space*2)/2&"' y='15' font-size='"&textSize&"' fill='"&textColor&"' font-weight='"&TextWeight&"' text-anchor='middle' >"&(CurText)&"</text>"
)
RETURN
"data:image/svg+xml;utf8,
<svg class='xifeng' xmlns='http://www.w3.org/2000/svg' version='1.1' height='20' width='512'>"&
IF(CurText<>BLANK(),CONCATENATEX(TagChart,[Tag],""))
&"</svg>"
/// 返回水印背景。textContent:水印文本(如"微信公众号:简说PowerBI");textSize:文本大小(建议20-28);textColor:文本颜色(如"Gray"或"#808080");opacity:透明度0-1(建议0.1-0.3);rotateDegree:旋转角度(建议-30~-45);canvasWidth:画布宽度(建议1280或1920);canvasHeight:画布高度(建议720或1080);xGap:X方向间距(建议220-260);yGap:Y方向间距(建议180-220)
Function XF.SvgChart.WatermarkBackground = (textContent:string,textSize:int64,textColor:string,opacity:double,rotateDegree:int64,canvasWidth:int64,canvasHeight:int64,xGap:int64,yGap:int64) =>
VAR __WatermarkText = textContent
VAR __FontSize = textSize
VAR __FontColor = textColor
VAR __Opacity = opacity
VAR __RotateDegree = rotateDegree
VAR __CanvasWidth = canvasWidth
VAR __CanvasHeight = canvasHeight
VAR __XGap = xGap
VAR __YGap = yGap
VAR __FontFamily = "Segoe UI"
VAR __RepeatXCount = ROUNDUP( DIVIDE( __CanvasWidth, __XGap ), 0 ) + 1
VAR __RepeatYCount = ROUNDUP( DIVIDE( __CanvasHeight, __YGap ), 0 ) + 1
VAR __GridTotalWidth = ( __RepeatXCount - 1 ) * __XGap
VAR __GridTotalHeight = ( __RepeatYCount - 1 ) * __YGap
VAR __StartOffsetX = DIVIDE( __CanvasWidth - __GridTotalWidth, 2 )
VAR __StartOffsetY = DIVIDE( __CanvasHeight - __GridTotalHeight, 2 )
VAR __TextBlocks =
CONCATENATEX (
GENERATESERIES ( 0, __RepeatYCount - 1 ),
VAR RowIndex = [Value]
RETURN
CONCATENATEX (
GENERATESERIES ( 0, __RepeatXCount - 1 ),
VAR ColIndex = [Value]
VAR XPos = __StartOffsetX + ColIndex * __XGap
VAR YPos = __StartOffsetY + RowIndex * __YGap
RETURN
"<text x=""" & XPos & """ y=""" & YPos & """ " &
"fill=""" & __FontColor & """ " &
"fill-opacity=""" & FORMAT ( __Opacity, "0.00" ) & """ " &
"font-family=""" & __FontFamily & """ " &
"font-size=""" & __FontSize & """ " &
"text-anchor=""middle"" " &
"dominant-baseline=""middle"" " &
"transform=""rotate(" & __RotateDegree & " " & XPos & " " & YPos & ")"">" &
__WatermarkText &
"</text>",
"",
""
),
"",
""
)
RETURN
"data:image/svg+xml;utf8," &
"<svg class='xifeng' xmlns=""http://www.w3.org/2000/svg"" " &
"width=""" & __CanvasWidth & """ height=""" & __CanvasHeight & """>" &
"<rect width=""100%"" height=""100%"" fill=""white"" fill-opacity=""0"" />" &
__TextBlocks &
"</svg>"
/// 返回纵向分割线,用于矩阵或表格的条件格式图标中,以进行列或区块的分割。lineColor:线条颜色(如"#3498db");strokeWidth:线条粗细(建议100);lineStyle:样式("solid"实线, "dashed"虚线);position:位置("center"居中, "left"靠左, "right"靠右)
Function XF.SvgChart.MatrixSplitLine = (lineColor:string,strokeWidth:int64,lineStyle:string,position:string) =>
VAR __InputColor = COALESCE( lineColor, "Gray" )
VAR __SafeColor = SUBSTITUTE( __InputColor, "#", "%23" )
VAR __SafeWidth = IF( strokeWidth <= 0, 2, strokeWidth )
VAR __SafeStyle = IF( LOWER( lineStyle ) = "dashed", "dashed", "solid" )
VAR __SafePosition = LOWER( position )
VAR __CanvasWidth = 480
VAR __CanvasHeight = 480
VAR __XPos =
SWITCH(
TRUE(),
__SafePosition = "left", 0,
__SafePosition = "right", __CanvasWidth,
__CanvasWidth / 2
)
VAR __DashAttribute =
IF(
__SafeStyle = "dashed",
"stroke-dasharray='30, 30'",
""
)
RETURN
"data:image/svg+xml;utf8," &
"<svg class='xifeng' xmlns='http://www.w3.org/2000/svg' " &
"width='" & __CanvasWidth & "' height='" & __CanvasHeight & "'>" &
"<line " &
"x1='" & __XPos & "' y1='0' " &
"x2='" & __XPos & "' y2='" & __CanvasHeight & "' " &
"stroke='" & __SafeColor & "' " &
"stroke-width='" & __SafeWidth & "' " &
__DashAttribute &
"/>" &
"</svg>"
方式二:外部工具
还可以使用配套的PowerBI外部工具来导入已发布的所有自定义函数,如下图所示:

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

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







