AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Pbir Filters

skill-wardawgmalvicious-claude-config-pbir-filters · by wardawgmalvicious

Use when authoring filter bodies in a Power BI PBIR report at report.json, page.json, or visual.json filterConfig.filters. Covers scopes (Report, Page, Visual — visual filter is sibling of `visual` NOT nested), filter types (Categorical, Advanced, TopN, VisualTopN, RelativeDate, RelativeTime, Tuple), filter body shape (Version 2, From[] aliases, Where[] using SourceRef.Source NEVER Entity), Categ…

No reviews yet
0 installs
16 views
0.0% view→install

Install

$ agentstack add skill-wardawgmalvicious-claude-config-pbir-filters

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No 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.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-wardawgmalvicious-claude-config-pbir-filters)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
26d ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

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 →
Are you the author of Pbir Filters? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

PBIR Filters Reference

Filter Scopes

| Scope | Location | Applies To | |---|---|---| | Report | report.jsonfilterConfig.filters[] | All pages and visuals | | Page | page.jsonfilterConfig.filters[] | All visuals on the page | | Visual | visual.jsonfilterConfig.filters[] | That visual only (sibling of visual, not nested) |

Filter Types

| type | Description | Use Case | |---|---|---| | Categorical | In / NotIn list | Year, category, brand (most common) | | Advanced | Comparison on measures or columns | Measure > threshold, ranges | | TopN | Top/bottom N by measure | Top 10 customers | | VisualTopN | Visual-level TopN | Auto-applied by some visuals | | RelativeDate | Rolling date window | Last N days/months/years | | RelativeTime | Rolling time window | Last N hours/minutes | | Tuple | Multi-column composite | Rare |

Filter Object Properties

| Property | Type | Notes | |---|---|---| | name | string | 20-char hex unique ID | | displayName | string | Optional pane label | | field | object | Column or Measure reference (query projection syntax) | | type | string | See table above | | filter | object | Where clause — optional when no defaults | | isHiddenInViewMode | boolean | Hide from pane in reading view | | isLockedInViewMode | boolean | Visible but not editable | | howCreated | string | "User" for user-created | | ordinal | integer | Display order (optional) | | objects | object | requireSingleSelect, isInvertedSelectionMode |

filter Body Shape

"filter": {
  "Version": 2,
  "From": [{"Name": "e", "Entity": "Exchange Rate", "Type": 0}],
  "Where": [{"Condition": {...}}]
}

Where clause rules:

  • From[] defines aliases
  • Conditions reference alias via "SourceRef": {"Source": "e"} — NOT Entity
  • String values: inner single quotes, doubled for escape: "'O''Brien'"
  • Integer values: L suffix ("2022L"); datetimes: "datetime'2024-01-01T00:00:00.0000000'"
  • Each value is wrapped in its own array: [[{val1}], [{val2}]]

Categorical — In (Multi-Select Default)

{
  "name": "d3f20cea05c37b47123a",
  "field": {"Column": {"Expression": {"SourceRef": {"Entity": "Exchange Rate"}}, "Property": "From Currency"}},
  "type": "Categorical",
  "filter": {
    "Version": 2,
    "From": [{"Name": "e", "Entity": "Exchange Rate", "Type": 0}],
    "Where": [{"Condition": {"In": {
      "Expressions": [{"Column": {"Expression": {"SourceRef": {"Source": "e"}}, "Property": "From Currency"}}],
      "Values": [
        [{"Literal": {"Value": "'EUR'"}}],
        [{"Literal": {"Value": "'USD'"}}]
      ]
    }}}]
  }
}

Categorical — Inverted (Not In)

Wrap In with Not AND set isInvertedSelectionMode: true.

"Where": [{"Condition": {"Not": {"Expression": {"In": {
  "Expressions": [{"Column": {"Expression": {"SourceRef": {"Source": "b"}}, "Property": "Brand"}}],
  "Values": [[{"Literal": {"Value": "'ASAN'"}}]]
}}}}}],
"objects": {"general": [{"properties": {
  "isInvertedSelectionMode": {"expr": {"Literal": {"Value": "true"}}}
}}]}

No Default (Empty Filter)

Omit filter entirely, OR include with empty Where:

"filter": {"Version": 2, "From": [{"Name": "d", "Entity": "Date", "Type": 0}], "Where": []}

Advanced — Comparison

{
  "name": "1c9a23490ebe5441b781",
  "field": {"Measure": {"Expression": {"SourceRef": {"Entity": "Budget"}}, "Property": "Budget vs. Turnover (%)"}},
  "type": "Advanced",
  "filter": {
    "Version": 2,
    "From": [{"Name": "d", "Entity": "Budget", "Type": 0}],
    "Where": [{"Condition": {"Comparison": {
      "ComparisonKind": 1,
      "Left": {"Measure": {"Expression": {"SourceRef": {"Source": "d"}}, "Property": "Budget vs. Turnover (%)"}},
      "Right": {"Literal": {"Value": "0D"}}
    }}}]
  }
}

ComparisonKind Codes

0=Equal, 1=GreaterThan, 2=GreaterThanOrEqual, 3=LessThanOrEqual, 4=LessThan.

Between (Range, Inclusive)

"Where": [{"Condition": {"Between": {
  "Expression": {"Column": {"Expression": {"SourceRef": {"Source": "d"}}, "Property": "Date"}},
  "LowerBound": {"Literal": {"Value": "datetime'2024-01-01T00:00:00.0000000'"}},
  "UpperBound": {"Literal": {"Value": "datetime'2024-12-31T00:00:00.0000000'"}}
}}}]

RelativeDate — DateSpan / DateAdd

TimeUnit codes: 0=Day, 1=Week, 2=Month, 3=Year, 4=Decade, 5=Second, 6=Minute, 7=Hour.

Current period start:

"Right": {"DateSpan": {"Expression": {"Now": {}}, "TimeUnit": 2}}

3 months ago from start of current month:

"Right": {"DateAdd": {
  "Expression": {"DateSpan": {"Expression": {"Now": {}}, "TimeUnit": 2}},
  "TimeUnit": 2,
  "Amount": -3
}}

RelativeTime uses the same shape with TimeUnit 5/6/7.

TopN

"type": "TopN",
"filter": {
  "Version": 2,
  "From": [{"Name": "c", "Entity": "Customers", "Type": 0}],
  "Where": [{"Condition": {"VisualTopN": {
    "Expression": {"Column": {"Expression": {"SourceRef": {"Source": "c"}}, "Property": "Customer Name"}},
    "Count": {"Literal": {"Value": "10L"}},
    "OrderBy": {"Measure": {"Expression": {"SourceRef": {"Entity": "Sales"}}, "Property": "Revenue"}},
    "IsAscending": false
  }}}]
}

IsAscending: false = Top N. true = Bottom N.

Compound — And / Or

"Condition": {"And": {
  "Left":  {"Comparison": {"ComparisonKind": 2, "Left": {...}, "Right": {...}}},
  "Right": {"Comparison": {"ComparisonKind": 3, "Left": {...}, "Right": {...}}}
}}

Condition Reference

| Condition | Description | |---|---| | In | Value in list | | NotIn | Value NOT in list | | Comparison | Single comparison | | Between | Inclusive range | | And / Or | Compound | | Not | Negation wrapper | | Contains | String contains | | StartsWith | String prefix | | DateSpan | Relative period | | DateAdd | Offset date expression | | VisualTopN | Top/bottom N | | Now | Current datetime — inside DateSpan/DateAdd |

Contains / StartsWith — Minimal Shape

"Where": [{"Condition": {"Contains": {
  "Left":  {"Column": {"Expression": {"SourceRef": {"Source": "c"}}, "Property": "Customer Name"}},
  "Right": {"Literal": {"Value": "'Acme'"}}
}}}]

StartsWith uses the same shape — swap Contains for StartsWith.

Hide / Lock / Single-Select

| Option | Effect | |---|---| | isHiddenInViewMode: true | Hidden from filter pane in reading view | | isLockedInViewMode: true | Visible but not editable | | objects.general.properties.requireSingleSelect | Force exactly one value |

Common combinations:

| Use Case | Hidden | Locked | SingleSelect | |---|---|---|---| | Hidden background filter | true | true | – | | Locked parameter | false | true | true | | Normal multi-select | false | false | false | | Visible single-select | false | false | true |

Never hide visual-level filters — confuses users. Only hide report/page filters with justification.

Filter Pane Visibility — outspacePane on report.json (owned here)

Only visible and expanded live at report.json → objects.outspacePane. All styling (colors, text, backgrounds, input box, width) belongs in the theme — see pbir-themes.

"objects": {"outspacePane": [{"properties": {
  "visible":  {"expr": {"Literal": {"Value": "true"}}},
  "expanded": {"expr": {"Literal": {"Value": "false"}}}
}}]}

Discovering Filter Values

pbir model "Report.Report" -d                                                   # dump model
pbir model "Report.Report" -d -t Date                                           # single table
pbir model "Report.Report" -q "EVALUATE DISTINCT('Date'[Calendar Year (ie 2021)])"

Gotchas

| Issue | Cause | Fix | |---|---|---| | Filter silently ignored | SourceRef.Entity in Where instead of SourceRef.Source | Reference alias defined in From[] | | Filter values not selected | Values not double-wrapped | Each value is its own array: [[{v1}], [{v2}]] | | Deploy error on report filter pane styling | Styling in report.json outspacePane | Move to theme visualStyles["*"]["*"].outspacePane | | Inverted filter still shows selected values | Missing isInvertedSelectionMode: true | Set it alongside the NotIn Where | | RelativeDate rolling window off by one | Missing DateAdd offset | Wrap DateSpan in DateAdd with negative Amount | | String literal with apostrophe fails | Unescaped single quote | Double it: "'O''Brien'" | | Integer filter value rejected | Used D suffix | Integers use L | | DateTime filter rejected | Missing trailing ' | "datetime'YYYY-MM-DDTHH:MM:SS.0000000'" | | filterConfig in wrong place on visual | Nested inside visual | Sibling of visual at root of visual.json | | Empty-filter default values appear | Previous Where clause present | Use "Where": [] or omit filter entirely | | Visual filter hidden causes UX confusion | isHiddenInViewMode on visual scope | Don't hide visual-level filters |

Reference

See also

  • pbir-visual-json — visual.json filterConfig placement (sibling of visual)
  • pbir-themes — filter pane and filter card styling
  • pbir-bookmarksbyExpr filter snapshots (same SQExpr shape)

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.