首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Power BI原生图表自定义填充图案

Power BI原生图表自定义填充图案

作者头像
wujunmin
发布2022-12-13 15:28:33
发布2022-12-13 15:28:33
1.4K0
举报
文章被收录于专栏:wujunminwujunmin

Power BI内置条形图、柱形图一般是这样的:

但其实也可以是这样:

这样:

这样:

以上所有效果不依赖任何第三方视觉对象,完全使用Power BI内置图表生成,交互功能一个不少(比如工具提示),数据标签,条件格式也完全支持。这是怎么办到的?

答案是:矩阵

  1. 原理

下图是常见的一个矩阵样式,总共有10列,每个格子填充了一个数字1。如果填充的内容不是1,而是图案,则可以实现文章开始的各种效果。

如果一个店铺业绩最高,为10万,条形图填充西红柿,可以想到,它需要10个格子都填充,如果是9万,则填充9个西红柿。现实生活不会这么整齐,如果是9.3万呢?可以想到前面9个格子需要完整的西红柿,最后一个格子只需要西红柿的30%。大家可以看到,下方两个店铺,数据仅微差,最后一个西红柿像素级精确切割。

图案的来源可以是emoji库(比如这个https://unicode-table.com/cn/emoji/),Power BI支持直接显示emoji,或者使用UNICHAR函数链接相应编码。

如果是完全的整数,事情将会变得简单,但世界总是有余数,最后一个格子如何按余数切割图案?答案是我也不知道。切割很麻烦,可以逆向思维,把多余的部分覆盖掉。覆盖反而很简单,在度量值使用SVG中的矩形(rect)可以精确覆盖。比如7.6万这个业绩,前面7格完整的西红柿,第8格还是完整的西红柿,只是西红柿的右边40%用矩形进行遮挡。

2. 实现过程


新建一个索引表,这里有两种方式,一种是DAX使用GENERATESERIES函数新建,第二种是Power Query直接={1..9},索引的最大值反映了你想要显示图案的密集程度,越密集最大值设置的越高即可,一般建议10个以内,示例是9个。

新建条形图度量值,如下,度量值标记为图像URL,其中的业绩替换为你的指标进行复用。

代码语言:javascript
复制
矩阵条形图-Emoji = 
VAR MaxValue =
    MAXX ( ALLSELECTED ( '店铺资料'[店铺名称] ), [M.销售业绩] )
VAR N =
    MAXX ( ALL ( '索引表' ), '索引表'[Value] )
VAR Width_ALL = 48 * N * [M.销售业绩] / MaxValue // N个格子 
VAR Width_N =
    INT ( Width_ALL / 48 )
VAR Width_MOD =
    MOD ( Width_ALL, 48 )
VAR Fill_Emoji =
    "<text font-size='35' x='24' y='24' text-anchor='middle' dominant-baseline='middle'>"
        & UNICHAR (127813 ) & "</text>"
VAR Chart =
    "data:image/svg+xml;utf8,
    <svg xmlns='http://www.w3.org/2000/svg' width='48' height='48' viewbox='0 0 48 48'> "
        & IF (
            SELECTEDVALUE ( '索引表'[Value] ) <= Width_N,
            Fill_Emoji,
            IF (
                SELECTEDVALUE ( '索引表'[Value] ) = Width_N + 1,
                Fill_Emoji & "
                <rect x='"
 & Width_MOD & 
"' y='0' height='48' width='"
 & 
48
 - Width_MOD & 
"' fill='white' />"
,
                BLANK ()
            )
        ) & "
    </svg>"
VAR LABEL =
    "data:image/svg+xml;utf8,
    <svg xmlns='http://www.w3.org/2000/svg' width='48' height='48' >
        <text font-size='25' x='24' y='24' text-anchor='middle' dominant-baseline='middle'>"
            & FORMAT ( [M.销售业绩] / 1000, "#,#" ) & "</text>
    </svg>"
RETURN
    IF ( HASONEVALUE ( '索引表'[Value] ), Chart, Label )

拖拽一个矩阵,字段如下设置:

此时,你看到的是如下的样式,本度量值充分利用总计功能充当数据标签,如果你不需要数据标签,关掉矩阵的总计即可。

矩阵上方的索引号可以设置为白色颜色或者使用方框进行遮挡。如果想要替换图案,将度量值中的UNICHAR换为任意表情符号(输入法一般自带,或者使用上方推荐的emoji列表)

以上是条形图的示例,柱形图道理一样,起初你进行翻转时,样式可能如下,数据标签在下方,因为矩阵的总计在下方,这时需要把度量值中text的内容换为维度内容。维度可能存在文字过长的问题,处理起来还需要额外的功夫。

如果emoji表情库那么多图案你都不想用,一定要自定义,那就不得不上SVG中的path了,万物皆path。以下是魔方的例子:

代码语言:javascript
复制
矩阵条形图-Path-魔方 = 
VAR MaxValue =
    MAXX ( ALLSELECTED ( '店铺资料'[店铺名称]), [M.销售业绩] )
VAR N =
    MAXX ( ALL ( '索引表' ), '索引表'[Value] )
VAR Width_ALL = 48 * N * [M.销售业绩] / MaxValue // N个格子 
VAR Width_N =
    INT ( Width_ALL / 48 )
VAR Width_MOD =
    MOD ( Width_ALL, 48 )
VAR Fill_Path=
    "<path d='M15.5 9L7 14V24V34L15.5 39L24 44L32.5001 39L41 34V24V14L32.5001 9L24 4L15.5 9Z' stroke='#333' stroke-width='2' stroke-linecap='round' fill='none' stroke-linejoin='round'/><path d='M41 14L24 24' stroke='#333' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/><path d='M7 14L24 24' stroke='#333' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/><path d='M24 44V24' stroke='#333' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/><path d='M32 19L32 39' stroke='#333' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/><path d='M41 24L24 34' stroke='#333' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/><path d='M24 34L7 24' stroke='#333' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/><path d='M16 39L16 19' stroke='#333' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/><path d='M32 9L16 19' stroke='#333' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/><path d='M32 19L16 9' stroke='#333' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/>"
VAR Chart =
    "data:image/svg+xml;utf8,
    <svg xmlns='http://www.w3.org/2000/svg' width='48' height='48' viewbox='0 0 48 48'> "
        & IF (
            SELECTEDVALUE ( '索引表'[Value] ) <= Width_N,
            Fill_Path,
            IF (
                SELECTEDVALUE ( '索引表'[Value] ) = Width_N + 1,
                Fill_Path & "
                <rect x='" & Width_MOD & "' y='0' height='48' width='" & 48 - Width_MOD & "' fill='white' />",
                BLANK ()
            )
        ) & "
    </svg>"
VAR LABEL =
    "data:image/svg+xml;utf8,
    <svg xmlns='http://www.w3.org/2000/svg' width='48' height='48' >
        <text font-size='25' x='24' y='24' text-anchor='middle' dominant-baseline='middle'>"
            & FORMAT ( [M.销售业绩] / 1000, "#,#" ) & "</text>
    </svg>"
RETURN
    IF ( HASONEVALUE ( '索引表'[Value] ), Chart, Label )

度量值中Fill_Path是自定义的图案内容,图案代码可以在阿里(https://www.iconfont.cn/)或者字节(https://iconpark.oceanengine.com/official)的图标库查询,也可以自己用PPT画一个,另存为SVG,再用记事本打开复制里面的代码到Fill_Path。

以上演示每个条形柱子均相同,如需图案不一样可以使用SWITCH函数切换,如需颜色不一样可以将度量值中的fill(填充色)或者stroke(边框色)设置条件进行变换。

以上讲解的差不多了,因为图表寄生在矩阵上,因此交互能力和原生图表完全一致。有读者最后问了句,这种图能下钻吗?当然能,请对度量值中的最大值进行SWITCH层级切换处理。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-11-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 wujunmin 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档