Forum Discussion

majid154a's avatar
majid154a
Helper II
5 months ago
Solved

Waterfall by HTML Help

Hello Experts, I would like to build a Custom Visual using HTML, but I do not have enough experience in this area. I would appreciate your support with the following requirements: Requirement: Cre...
  • NoosaInsight's avatar
    5 months ago

    Hi majid154a,

     

    I thought I'd give you a hand to get started with this.

     

    I've managed to get a component working in HTML:

     

    Here is the HTML for it, you may test it in your browser and play around with the scale, prev-value, and curr-movement/curr-label variables. Notice positive values will turn green, negative will turn red.

    <style>
    
            :root {
                --scale: 5455;
                --prev-value: 5000;
                --curr-movement: -1505;
                --curr-label: "-1505";
                --movement: calc(var(--curr-movement) / abs(var(--curr-movement)));
                --multiplier: calc((var(--movement) + 1) / 2);
                --color: calc(var(--multiplier) * 122);
                --height: calc(abs(var(--curr-movement)) / var(--scale) * 100%);
                --top: calc((var(--scale) - var(--prev-value)) / var(--scale) * 100% - (var(--multiplier) * var(--height)));
    
    
            .p-outer {
                text-align: center;
                padding-top: 1.5em;
            }
    
            .p-area {
                height: 90vh;
                width: 90vw;
                margin-left: auto;
                margin-right: auto;
            }
    
            .p-block::after {
                content: var(--curr-label);
                top: -1.5em;
                position: relative;
                color: black;
            }
            .p-block {
                height: var(--height);
                background-color: hsl(var(--color),70%,50%);
                top: var(--top);
                width: 100%;
                position: relative;
            }
    
            .category {
                text-align: center;
                color: hsl(0,0%,50%);
            }
    
            body {
                font-family: sans-serif;
            }
        </style>
    <div>
        <div class="p-outer">
            <div class="p-area">
                <div class="p-block"></div>
            </div>
            <div class="category">Category name</div>
        </div>
    </div>

     

    We can then turn this into a parameterised DAX measure:

    HTML Waterfall Bar = 
    
    VAR Scale          = [Scale]          // Replace with your max absolute value or dynamic max scale measure
    VAR PrevValue      = [Previous Cumulative Value]   // Your measure for the running total BEFORE this step
    VAR CurrMovement   = [Variance / Delta]            // Your measure for this step's change (positive or negative)
    VAR CategoryName   = SELECTEDVALUE('Category'[Category Name])  // or whatever your category field is
    VAR CurrLabel      = FORMAT(CurrMovement, "#,##0")    // or use FIXED/ROUND as preferred
    
    RETURN
    
    "<html>
    <head>
        <style>
            :root {
                --scale: " & Scale & ";
                --prev-value: " & PrevValue & ";
                --curr-movement: " & CurrMovement & ";
                --curr-label: """ & CurrLabel & """;
                --movement: calc(var(--curr-movement) / abs(var(--curr-movement)));
                --multiplier: calc((var(--movement) + 1) / 2);
                --color: calc(var(--multiplier) * 122);
                --height: calc(abs(var(--curr-movement)) / var(--scale) * 100%);
                --top: calc((var(--scale) - var(--prev-value)) / var(--scale) * 100% - (var(--multiplier) * var(--height)));
            }
            .p-outer {
                text-align: center;
                padding-top: 1.5em;
            }
    
            .p-area {
                height: 90vh;
                width: 90vw;
                margin-left: auto;
                margin-right: auto;
            }
    
            .p-block::after {
                content: var(--curr-label);
                top: -1.5em;
                position: relative;
                color: black;
            }
            .p-block {
                height: var(--height);
                background-color: hsl(var(--color),70%,50%);
                top: var(--top);
                width: 100%;
                position: relative;
            }
    
            .category {
                text-align: center;
                color: hsl(0,0%,50%);
            }
    
            body {
                font-family: sans-serif;
            }
        </style>
    </head>
    <body>
        <div class='p-outer'>
            <div class='p-area'>
                <div class='p-block'></div>
            </div>
            <div class='category'>" & CategoryName & "</div>
        </div>
    </body>
    </html>"

     

    To get this working, you will need to create the following DAX measures:

    1. Scale (Can be either set to one of the NPAT values, or calculated with logic)
    2. Previous Cumulative Value
    3. Variance / Delta (already exists in your dataset)

     

    You will also need to introduce logic for the Budget NPAT and Actual NPAT colors.

     

    Granularity will need to be set to Category Name. Then sort by Category ID.

     

    I hope this helps.

  • v-saisrao-msft's avatar
    5 months ago

    Hi majid154a,

    Thank you Ashish_Mathur, for your insights.

    With a sample dataset, I replicated your requirement in Power BI. On Page 1, I used the HTML Content visual to build the custom layout, and on Page 2, I utilized the standard Waterfall visual. I've attached the PBIX file for your review and included a Microsoft documentation link below for further details on the Waterfall visual.

    Waterfall Charts in Power BI - Power BI | Microsoft Learn

     

    Thank you.