Install
$ agentstack add skill-wardawgmalvicious-claude-config-pbir-conditional-formatting ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
PBIR Conditional Formatting Reference
Three approaches: measure-based (flexible), FillRule gradients (no DAX), and rule-based Conditional (UI-generated).
Approach Matrix
| Approach | Best For | Pros | Cons | |---|---|---|---| | Measure-based | Custom logic, theme colors | Full DAX, readable | Requires extension measure | | linearGradient2 / linearGradient3 | Color scales | No DAX | Gradients only | | Conditional.Cases | UI-portable rules | Power BI UI round-trips | Verbose |
Supported Properties
Not every property accepts measure expressions. These do:
fill, borderColor, defaultColor, fontColor, color, backgroundColor, lineColor, markerColor, strokeColor, text, titleText, fontSize, strokeWidth, weight, transparency, radius, url, good, bad, neutral, target, icon
Everything else is literal-only or ThemeDataColor.
dataViewWildcard Selector
The key to per-point formatting.
| matchingOption | Behavior | |---|---| | 0 | Identities + totals (series-level) | | 1 | Per data point (most common for CF) | | 2 | Totals only |
"selector": {"data": [{"dataViewWildcard": {"matchingOption": 1}}]}
Wrong for per-point: "selector": {"metadata": "Sales.Revenue"} — evaluates once per series.
Two-Entry Array Pattern (Required)
dataPoint, lineStyles, error require a two-entry array: base entry + conditional entry.
"dataPoint": [
{"properties": {}},
{
"properties": {
"fill": {"solid": {"color": {"expr": {"Measure": {
"Expression": {"SourceRef": {"Schema": "extension", "Entity": "_Formatting"}},
"Property": "Bar Color"
}}}}}
},
"selector": {"data": [{"dataViewWildcard": {"matchingOption": 1}}]}
}
]
Extension Measure (for color CF)
Defined in Report.Report/definition/reportExtensions.json. dataType MUST be "Text" for color measures. Must attach to an EXISTING entity from the model.
{
"name": "extension",
"entities": [{
"name": "_Formatting",
"measures": [{
"name": "Bar Color",
"dataType": "Text",
"expression": "SWITCH(TRUE(), [Value]<10, \"bad\", [Value]<50, \"neutral\", \"good\")"
}]
}]
}
Theme color names returned by measures: "bad", "good", "neutral", "minColor", "midColor", "maxColor".
Measure Reference in CF Expressions
{"expr": {"Measure": {
"Expression": {"SourceRef": {"Schema": "extension", "Entity": "_Formatting"}},
"Property": "Bar Color"
}}}
"Schema": "extension" is required for report-level extension measures. Omit for model measures.
Pattern — Bar / Column Fill
"dataPoint": [
{"properties": {}},
{
"properties": {
"fill": {"solid": {"color": {"expr": {"Measure": {
"Expression": {"SourceRef": {"Schema": "extension", "Entity": "_Formatting"}},
"Property": "Bar Color"
}}}}}
},
"selector": {"data": [{"dataViewWildcard": {"matchingOption": 1}}]}
}
]
Pattern — linearGradient2 (Two-Color)
Data-driven (scale to observed range):
{"FillRule": {"linearGradient2": {
"min": {"color": {"Literal": {"Value": "'minColor'"}}},
"max": {"color": {"Literal": {"Value": "'maxColor'"}}},
"nullColoringStrategy": {"strategy": {"Literal": {"Value": "'asZero'"}}}
}}}
Explicit bounds (fixed thresholds):
{"FillRule": {"linearGradient2": {
"min": {"color": {"Literal": {"Value": "'minColor'"}}, "value": {"Literal": {"Value": "0D"}}},
"max": {"color": {"Literal": {"Value": "'maxColor'"}}, "value": {"Literal": {"Value": "1D"}}},
"nullColoringStrategy": {"strategy": {"Literal": {"Value": "'asZero'"}}, "color": {"Literal": {"Value": "'#FFFFFF'"}}}
}}}
Pattern — linearGradient3 (Diverging)
{"FillRule": {"linearGradient3": {
"min": {"color": {"Literal": {"Value": "'minColor'"}}, "value": {"Literal": {"Value": "-1D"}}},
"mid": {"color": {"Literal": {"Value": "'neutral'"}}, "value": {"Literal": {"Value": "0D"}}},
"max": {"color": {"Literal": {"Value": "'maxColor'"}}, "value": {"Literal": {"Value": "1D"}}},
"nullColoringStrategy": {"strategy": {"Literal": {"Value": "'asZero'"}}}
}}}
Pattern — Line Segment Colors (Single-Series Only)
Multi-series line charts cannot use segment coloring. Measure must return hex.
"lineStyles": [
{"properties": {"segmentGradient": {"expr": {"Literal": {"Value": "true"}}}}},
{
"properties": {
"strokeColor": {"solid": {"color": {"expr": {"Measure": {
"Expression": {"SourceRef": {"Schema": "extension", "Entity": "_Formatting"}},
"Property": "Line Color"
}}}}}
},
"selector": {"data": [{"dataViewWildcard": {"matchingOption": 1}}]}
}
]
segmentGradient only affects strokeColor. It does NOT work with lineStyle, strokeWidth, or markerFill.
Pattern — Axis Label Colors
No selector needed.
"categoryAxis": [{
"properties": {
"labelColor": {"solid": {"color": {"expr": {"Measure": {
"Expression": {"SourceRef": {"Schema": "extension", "Entity": "_Formatting"}},
"Property": "Axis Color"
}}}}}
}
}]
Pattern — Marker Transparency (0-100)
Marker color / shape / size do NOT support CF. Transparency does.
"markers": [
{"properties": {"borderShow": {"expr": {"Literal": {"Value": "false"}}}}},
{
"properties": {
"transparency": {"expr": {"Measure": {
"Expression": {"SourceRef": {"Schema": "extension", "Entity": "_Measures"}},
"Property": "Marker Opacity"
}}}
},
"selector": {"data": [{"dataViewWildcard": {"matchingOption": 1}}]}
}
]
Pattern — Rule-Based Conditional
{"expr": {"Conditional": {"Cases": [
{"Condition": {...}, "Value": {"Literal": {"Value": "'#FF0000'"}}},
{"Condition": {...}, "Value": {"Literal": {"Value": "'#00FF00'"}}}
]}}}
Cases evaluated in order; first match wins.
ComparisonKind Codes
| Value | Operator | |---|---| | 0 | Equal | | 1 | Greater than | | 2 | Greater than or equal | | 3 | Less than or equal | | 4 | Less than |
Logical Wrappers
{"And": {"Left": {...}, "Right": {...}}}
{"Or": {"Left": {...}, "Right": {...}}}
{"Not": {"Expression": {...}}}
ScopedEval + AllRolesRef (Global Context)
Removes filter context for global min/max:
{"ScopedEval": {"Expression": {"Measure": {...}}, "Scope": [{"AllRolesRef": {}}]}}
Data Bars (table/matrix columns)
"dataBars": {
"positiveColor": {"solid": {"color": {"expr": {"Literal": {"Value": "'#E1EBF2'"}}}}},
"negativeColor": {"solid": {"color": {"expr": {"Literal": {"Value": "'#E5B97D'"}}}}},
"axisColor": {"solid": {"color": {"expr": {"Literal": {"Value": "'#FFFFFF'"}}}}},
"reverseDirection": {"expr": {"Literal": {"Value": "false"}}},
"hideText": {"expr": {"Literal": {"Value": "false"}}}
}
Conditional Icons
"icon": {
"kind": "Icon",
"layout": {"expr": {"Literal": {"Value": "'IconOnly'"}}},
"value": {"expr": {"Conditional": {"Cases": [
{"Condition": {"Comparison": {"ComparisonKind": 4, "Left": {"Measure": {...}}, "Right": {"Literal": {"Value": "0D"}}}},
"Value": {"Literal": {"Value": "'SymbolMedium'"}}}
]}}}
}
Gotchas
| Issue | Cause | Fix | |---|---|---| | All points get same color | metadata selector used | Switch to dataViewWildcard with matchingOption: 1 | | CF works intermittently | Single-entry array with selector | Use two-entry array pattern | | Measure rejected as color | dataType not "Text" in reportExtensions.json | Set "dataType": "Text" | | Extension measure not found | Created new entity in reportExtensions.json | Entities must already exist in the semantic model | | Line segment colors don't work | Chart has multiple series in Y/Y2 | Segment coloring requires a single series | | Marker color CF ignored | Marker fill/shape/size don't support CF | Use transparency instead | | segmentGradient + strokeWidth silently fails | Only strokeColor is supported | Don't combine | | reportExtensions.json deserialization fails | Empty entities: [] | Delete the file entirely when no extension measures exist | | title / legend selector ignored | These objects don't accept selectors | Apply globally (no selector) | | Gradient midpoint shifts unexpectedly | Data-driven bounds when fixed needed | Switch to explicit bounds form with value on min/mid/max | | AllRolesRef scope wrong place | Nested incorrectly | ScopedEval.Scope: [{"AllRolesRef": {}}] at the outer wrapper |
Reference
- Microsoft Learn: Apply conditional table formatting in Power BI
- Microsoft Learn: Format by field value (color expression measures)
- Microsoft Learn: Tips and tricks for color formatting
- Comprehensive MS Learn link bundle (CF user concept / measure pattern / gradient scales / theme tokens / PBIR file format): [references/REFERENCE.md](references/REFERENCE.md)
See also
pbir-visual-json— selectors, expressions, literal suffixespbir-themes—ThemeDataColorand theme token resolution
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: wardawgmalvicious
- Source: wardawgmalvicious/claude-config
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.