DAX SVG measure · Progress to target
Power BI progress bar measure (DAX SVG)
By Nawaf Sharaf · Founder & Reliability Engineer · Updated
Use it when
- You have a natural 0–100% ratio: tasks done, budget consumed, quota attained.
- The table needs a status colour without a separate RAG column.
Skip it when
The ratio routinely goes far above 100% (quota attainment of 180%): the bar caps at full. Use the bullet chart, which stretches.
Three looks
The progress bar 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.
- Ratio measure
- DIVIDE ( [Done], [Total] ). Values are clamped to 0–1 for the fill; the label shows the real value.
The full DAX
Swap [% Complete] for your own names.
Progress Bar =
-- VizForge SVG measure: progress bar.
-- Set Measure tools > Data category = Image URL, then size it under Format > Visual > Image size.
-- 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 _Ratio = [% Complete]
VAR _Fill = MAX ( 0, MIN ( 1, _Ratio ) )
RETURN
IF (
ISBLANK ( _Ratio ),
BLANK (),
"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='14' viewBox='0 0 140 14'><rect x='0' y='2' width='102' height='10' rx='5' fill='%23E6E6E6'/><rect x='0' y='2' width='"
& FORMAT ( _Fill * 102, "0.0", "en-US" )
& "' height='10' rx='5' fill='"
& SWITCH ( TRUE (), _Ratio >= 0.8, "%231AAB40", _Ratio >= 0.5, "%23D9B300", "%23D64554" )
& "'/><text x='140' y='7' dy='0.35em' text-anchor='end' font-family='Segoe UI, Helvetica, Arial, sans-serif' font-size='12' font-weight='600' fill='%23252423'>"
& SUBSTITUTE ( FORMAT ( _Ratio, "0%", "en-US" ), "%", "%25" )
& "</text></svg>"
)DAX user-defined function variant (VizForge.SvgProgressBar)
One-line call: Progress Bar = VizForge.SvgProgressBar ( [% Complete] )
-- 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
/// Progress bar as an SVG image URL (VizForge). Optional parameters default to the colours you picked.
FUNCTION VizForge.SvgProgressBar = (
pValue : NUMERIC,
pTrackColor : STRING = "#E6E6E6",
pHighAt : NUMERIC = 0.8,
pHighColor : STRING = "#1AAB40",
pLowAt : NUMERIC = 0.5,
pMidColor : STRING = "#D9B300",
pLowColor : STRING = "#D64554",
pLabelColor : STRING = "#252423"
) =>
VAR _Ratio = pValue
VAR _Fill = MAX ( 0, MIN ( 1, _Ratio ) )
RETURN
IF (
ISBLANK ( _Ratio ),
BLANK (),
"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='14' viewBox='0 0 140 14'><rect x='0' y='2' width='102' height='10' rx='5' fill='"
& SUBSTITUTE ( pTrackColor, "#", "%23" )
& "'/><rect x='0' y='2' width='"
& FORMAT ( _Fill * 102, "0.0", "en-US" )
& "' height='10' rx='5' fill='"
& SWITCH (
TRUE (),
_Ratio >= pHighAt,
SUBSTITUTE ( pHighColor, "#", "%23" ),
_Ratio >= pLowAt,
SUBSTITUTE ( pMidColor, "#", "%23" ),
SUBSTITUTE ( pLowColor, "#", "%23" )
)
& "'/><text x='140' y='7' dy='0.35em' text-anchor='end' font-family='Segoe UI, Helvetica, Arial, sans-serif' font-size='12' font-weight='600' fill='"
& SUBSTITUTE ( pLabelColor, "#", "%23" )
& "'>"
& SUBSTITUTE ( FORMAT ( _Ratio, "0%", "en-US" ), "%", "%25" )
& "</text></svg>"
)
EVALUATE { VizForge.SvgProgressBar ( [% Complete] ) }
-- 2) Then create the measure and set Measure tools > Data category = Image URL:
-- Progress Bar = VizForge.SvgProgressBar ( [% Complete] )
-- 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
One ratio measure such as [% Complete] (0 to 1). Image size 14 × 140 fits a standard table row; for a project list put the project name on rows and the bar next to the status. Remember the Image URL data category. All setup steps.
Gotchas
- The percentage label is FORMAT(…, "0%") with the % sign percent-encoded as %25: an unencoded % breaks the data URI.
- Rounded ends use rx = half the bar height; very short fills (under the height) render as a dot, which is expected.
- With thresholds, amber starts at 'Amber from' and green at 'Green from' as ratios (0.8 = 80%).
- Length. 415 characters whatever the data; no iteration.
- Context. The ratio is clamped to 0–100% for the fill, but the colour thresholds use the raw value, so 115% still shows the 'good' colour. Make sure the ratio is computed in the measure (DIVIDE of two sums), not averaged from a column.
- Tooltip. Hovering shows the SVG text; a blank report-page tooltip hides it.
When an SVG measure isn't enough
A custom visual can show the done and total counts on hover and add a target marker per row. See the KPI card custom visual for what an interactive version can do.
KPI card designs using it
Finished designs built on this pattern, from the KPI card gallery.