DAX SVG measure · Trend

Power BI sparkline in a table with a DAX SVG measure

A sparkline is a word-sized line chart: no axes, no labels, just the shape of the last few periods next to the number it explains. Power BI's built-in table sparklines cover the basics; a DAX SVG measure gives you control over the dot on the latest point, high/low markers, colours from your theme, and it also works as the image in the new Card visual.

By · Founder & Reliability Engineer · Updated

Sparkline (line) rendered from the DAX below with sample data
Rendered from the measure below with sample data at 2× (120×32 px in Power BI). 405 characters.

Use it when

  • You want trend shape per row (product, region, account) beside the current value.
  • You need the latest-point dot, high/low markers or theme colours the built-in sparkline doesn't offer.
  • You want the same trend picture inside a Card visual image, not just a table.

Skip it when

Readers need exact values for each period or have to compare levels between rows: each sparkline is scaled to its own min and max, so two identical shapes can hide very different numbers.

Three looks

The sparkline (line) in three palettes; click one to edit it.

Data it needs

The builder asks for exactly these fields; type your own measure and column names there.

Value measure
Any additive or non-additive measure, e.g. [Sales] or [Margin %]. It is evaluated once per axis value.
Axis column
A date or numeric column (e.g. 'Date'[Month Start]). It is converted to a number so gaps in time stay gaps.
Row column
Whatever is on the table's rows. It filters the series; it is not referenced in the measure.

The full DAX

Swap [Sales] and 'Date'[Month Start] for your own names.

Sparkline (measure)
Sparkline =
-- VizForge SVG measure: line sparkline.
-- Set Measure tools > Data category = Image URL. Put it in a table or matrix next to a category column.
-- The axis must be a date or number column so points are spaced in time order.
-- Made with the free VizForge SVG measure builder: vizforge.ai/tools/svg-measure-builder
-- Need per-point tooltips, click-to-select inside the chart or Format-pane settings? Generate it as a real custom visual: vizforge.ai/visuals
VAR _Base = FILTER (
    ADDCOLUMNS (
        ALLSELECTED ( 'Date'[Month Start] ),
        "@x", CONVERT ( 'Date'[Month Start], DOUBLE ),
        "@v", [Sales]
    ),
    NOT ISBLANK ( [@v] )
)
VAR _XMin = MINX ( _Base, [@x] )
VAR _XMax = MAXX ( _Base, [@x] )
VAR _VMin = MINX ( _Base, [@v] )
VAR _VMax = MAXX ( _Base, [@v] )
VAR _Points = CONCATENATEX (
    _Base,
    FORMAT ( 3.5 + DIVIDE ( [@x] - _XMin, _XMax - _XMin, 0.5 ) * 113, "0.0", "en-US" )
            & ","
            & FORMAT ( 3.5 + ( 1 - DIVIDE ( [@v] - _VMin, _VMax - _VMin, 0.5 ) ) * 25, "0.0", "en-US" ),
    " ",
    [@x], ASC
)
RETURN
    IF (
        COUNTROWS ( _Base ) < 2,
        BLANK (),
        "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='32' viewBox='0 0 120 32'><polyline fill='none' stroke='%23118DFF' stroke-width='1.5' stroke-linejoin='round' stroke-linecap='round' points='"
            & _Points
            & "'/><circle cx='"
            & MAXX ( TOPN ( 1, _Base, [@x], DESC ), FORMAT ( 3.5 + DIVIDE ( [@x] - _XMin, _XMax - _XMin, 0.5 ) * 113, "0.0", "en-US" ) )
            & "' cy='"
            & MAXX ( TOPN ( 1, _Base, [@x], DESC ), FORMAT ( 3.5 + ( 1 - DIVIDE ( [@v] - _VMin, _VMax - _VMin, 0.5 ) ) * 25, "0.0", "en-US" ) )
            & "' r='2.6' fill='%23118DFF'/></svg>"
    )
DAX user-defined function variant (VizForge.SvgSparkline)

One-line call: Sparkline = VizForge.SvgSparkline ( [Sales], 'Date'[Month Start] )

DAX query view script
-- 1) Paste into DAX query view and choose 'Update model with changes'.
--    Needs DAX user-defined functions (generally available since the June 2026 Power BI release).
DEFINE
    /// Sparkline (line) as an SVG image URL (VizForge). Optional parameters default to the colours you picked.
    FUNCTION VizForge.SvgSparkline = (
            pValue : ANYREF EXPR,
            pAxis : ANYREF EXPR,
            pLineColor : STRING = "#118DFF"
        ) =>
        VAR _Base = FILTER (
            ADDCOLUMNS (
                ALLSELECTED ( pAxis ),
                "@x", CONVERT ( pAxis, DOUBLE ),
                "@v", CALCULATE ( pValue )
            ),
            NOT ISBLANK ( [@v] )
        )
        VAR _XMin = MINX ( _Base, [@x] )
        VAR _XMax = MAXX ( _Base, [@x] )
        VAR _VMin = MINX ( _Base, [@v] )
        VAR _VMax = MAXX ( _Base, [@v] )
        VAR _Points = CONCATENATEX (
            _Base,
            FORMAT ( 3.5 + DIVIDE ( [@x] - _XMin, _XMax - _XMin, 0.5 ) * 113, "0.0", "en-US" )
                    & ","
                    & FORMAT ( 3.5 + ( 1 - DIVIDE ( [@v] - _VMin, _VMax - _VMin, 0.5 ) ) * 25, "0.0", "en-US" ),
            " ",
            [@x], ASC
        )
        RETURN
            IF (
                COUNTROWS ( _Base ) < 2,
                BLANK (),
                "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='32' viewBox='0 0 120 32'><polyline fill='none' stroke='"
                    & SUBSTITUTE ( pLineColor, "#", "%23" )
                    & "' stroke-width='1.5' stroke-linejoin='round' stroke-linecap='round' points='"
                    & _Points
                    & "'/><circle cx='"
                    & MAXX ( TOPN ( 1, _Base, [@x], DESC ), FORMAT ( 3.5 + DIVIDE ( [@x] - _XMin, _XMax - _XMin, 0.5 ) * 113, "0.0", "en-US" ) )
                    & "' cy='"
                    & MAXX ( TOPN ( 1, _Base, [@x], DESC ), FORMAT ( 3.5 + ( 1 - DIVIDE ( [@v] - _VMin, _VMax - _VMin, 0.5 ) ) * 25, "0.0", "en-US" ) )
                    & "' r='2.6' fill='"
                    & SUBSTITUTE ( pLineColor, "#", "%23" )
                    & "'/></svg>"
            )

EVALUATE { VizForge.SvgSparkline ( [Sales], 'Date'[Month Start] ) }

-- 2) Then create the measure and set Measure tools > Data category = Image URL:
-- Sparkline = VizForge.SvgSparkline ( [Sales], 'Date'[Month Start] )
--    Colours and thresholds are optional parameters: pass a value after the fields to override one.
--    Pass colours as plain "#RRGGBB"; the function encodes the # for the data URI.

Placing it in a report

Put Product or Region on the table rows and the measure beside them, never 'Date'[Month Start] itself: a row that is already one month has one point and returns BLANK(). Image size 32 high by 120 wide keeps the line crisp. Remember the Image URL data category. All setup steps.

Gotchas

When an SVG measure isn't enough

An interactive sparkline shows the value of each point on hover and filters the page when a row is clicked. See the KPI card custom visual for what an interactive version can do.