# Report Visuals

> Creates Power BI reports and visuals in PBIR format. Use for pages, charts, tables, slicers, and visual configuration.

- **Type:** Skill
- **Install:** `agentstack add skill-kpbray-power-bi-agent-skills-report-visuals`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [kpbray](https://agentstack.voostack.com/s/kpbray)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [kpbray](https://github.com/kpbray)
- **Source:** https://github.com/kpbray/power-bi-agent-skills/tree/master/.github/skills/report-visuals

## Install

```sh
agentstack add skill-kpbray-power-bi-agent-skills-report-visuals
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Report Visuals Skill

This skill helps create Power BI reports and visuals in PBIR (Power BI Report) format.

## When to Use This Skill

- Creating report pages with dimensions and layout
- Adding visuals (charts, tables, cards, slicers)
- Configuring visual queries (binding data to visuals)
- Setting up filters, bookmarks, drill-through
- Creating mobile layouts

## PBIR Structure Overview

```
.Report/
├── definition.pbir              # Report pointer file
├── report.json                  # Report configuration
├── StaticResources/            # Images and resources
│   └── RegisteredResources/
└── definition/
    ├── pages/
    │   ├── ReportSection1/
    │   │   └── page.json
    │   └── ReportSection2/
    │       └── page.json
    ├── bookmarks/
    └── ...
```

## Report Configuration

### report.json

```json
{
  "$schema": "https://developer.microsoft.com/json-schemas/fabric/item/report/definition/report/1.0.0/schema.json",
  "themeCollection": {
    "baseTheme": {
      "name": "CY24SU06",
      "reportVersionAtImport": "5.55",
      "type": "SharedResources"
    }
  },
  "config": {
    "version": 5,
    "defaultDrillFilterOtherVisuals": true
  },
  "objects": {}
}
```

## Page Structure

### Basic Page

```json
{
  "$schema": "https://developer.microsoft.com/json-schemas/fabric/item/report/definition/page/1.0.0/schema.json",
  "name": "ReportSection1a2b3c4d",
  "displayName": "Sales Overview",
  "displayOption": "FitToPage",
  "height": 720,
  "width": 1280,
  "visuals": [],
  "filters": [],
  "ordinal": 0
}
```

### Page Properties

| Property | Description | Values |
|----------|-------------|--------|
| `name` | Unique identifier | `ReportSection` + GUID |
| `displayName` | User-visible name | Any string |
| `displayOption` | Sizing mode | `FitToPage`, `FitToWidth`, `ActualSize` |
| `height` | Page height in pixels | 720 (standard), 1080 (tall) |
| `width` | Page width in pixels | 1280 (standard), 1920 (wide) |
| `ordinal` | Page order | 0, 1, 2, ... |

### Page Sizes

| Size | Width | Height | Use Case |
|------|-------|--------|----------|
| 16:9 | 1280 | 720 | Standard dashboard |
| 4:3 | 1280 | 960 | Traditional reports |
| Letter | 816 | 1056 | Print reports |
| Custom | Any | Any | Special layouts |

## Visual Structure

### Common Visual Properties

Every visual has this structure:

```json
{
  "name": "visual_unique_id",
  "position": {
    "x": 0,
    "y": 0,
    "width": 400,
    "height": 300,
    "z": 0,
    "tabOrder": 0
  },
  "visual": {
    "visualType": "columnChart",
    "query": { ... },
    "objects": { ... },
    "visualContainerObjects": { ... }
  }
}
```

### Position Object

| Property | Description |
|----------|-------------|
| `x` | Left position in pixels |
| `y` | Top position in pixels |
| `width` | Visual width in pixels |
| `height` | Visual height in pixels |
| `z` | Layer order (higher = on top) |
| `tabOrder` | Keyboard navigation order |

## Visual Types

### Column Chart

```json
{
  "name": "columnChart1",
  "position": {
    "x": 20,
    "y": 20,
    "width": 600,
    "height": 400,
    "z": 0,
    "tabOrder": 0
  },
  "visual": {
    "visualType": "columnChart",
    "query": {
      "queryState": {
        "Category": {
          "projections": [
            {
              "field": {
                "Column": {
                  "Expression": {
                    "SourceRef": { "Entity": "Products" }
                  },
                  "Property": "Category"
                }
              },
              "queryRef": "Products.Category",
              "active": true
            }
          ]
        },
        "Y": {
          "projections": [
            {
              "field": {
                "Measure": {
                  "Expression": {
                    "SourceRef": { "Entity": "Sales" }
                  },
                  "Property": "Total Sales"
                }
              },
              "queryRef": "Sales.Total Sales",
              "active": true
            }
          ]
        }
      }
    },
    "objects": {
      "categoryAxis": [{
        "properties": {
          "show": { "expr": { "Literal": { "Value": "true" } } }
        }
      }],
      "valueAxis": [{
        "properties": {
          "show": { "expr": { "Literal": { "Value": "true" } } }
        }
      }]
    }
  }
}
```

### Bar Chart

```json
{
  "name": "barChart1",
  "position": { "x": 20, "y": 20, "width": 500, "height": 350, "z": 0, "tabOrder": 0 },
  "visual": {
    "visualType": "barChart",
    "query": {
      "queryState": {
        "Category": {
          "projections": [{
            "field": {
              "Column": {
                "Expression": { "SourceRef": { "Entity": "Products" } },
                "Property": "Product Name"
              }
            },
            "queryRef": "Products.Product Name",
            "active": true
          }]
        },
        "Y": {
          "projections": [{
            "field": {
              "Measure": {
                "Expression": { "SourceRef": { "Entity": "Sales" } },
                "Property": "Total Sales"
              }
            },
            "queryRef": "Sales.Total Sales",
            "active": true
          }]
        }
      }
    }
  }
}
```

### Line Chart

```json
{
  "name": "lineChart1",
  "position": { "x": 20, "y": 20, "width": 600, "height": 400, "z": 0, "tabOrder": 0 },
  "visual": {
    "visualType": "lineChart",
    "query": {
      "queryState": {
        "Category": {
          "projections": [{
            "field": {
              "Column": {
                "Expression": { "SourceRef": { "Entity": "Date" } },
                "Property": "Month"
              }
            },
            "queryRef": "Date.Month",
            "active": true
          }]
        },
        "Y": {
          "projections": [{
            "field": {
              "Measure": {
                "Expression": { "SourceRef": { "Entity": "Sales" } },
                "Property": "Total Sales"
              }
            },
            "queryRef": "Sales.Total Sales",
            "active": true
          }]
        }
      }
    }
  }
}
```

### Card (Single Value)

```json
{
  "name": "card1",
  "position": { "x": 20, "y": 20, "width": 200, "height": 100, "z": 0, "tabOrder": 0 },
  "visual": {
    "visualType": "card",
    "query": {
      "queryState": {
        "Values": {
          "projections": [{
            "field": {
              "Measure": {
                "Expression": { "SourceRef": { "Entity": "Sales" } },
                "Property": "Total Sales"
              }
            },
            "queryRef": "Sales.Total Sales",
            "active": true
          }]
        }
      }
    },
    "objects": {
      "labels": [{
        "properties": {
          "fontSize": { "expr": { "Literal": { "Value": "28D" } } }
        }
      }]
    }
  }
}
```

### Table

```json
{
  "name": "table1",
  "position": { "x": 20, "y": 20, "width": 500, "height": 400, "z": 0, "tabOrder": 0 },
  "visual": {
    "visualType": "tableEx",
    "query": {
      "queryState": {
        "Values": {
          "projections": [
            {
              "field": {
                "Column": {
                  "Expression": { "SourceRef": { "Entity": "Products" } },
                  "Property": "Product Name"
                }
              },
              "queryRef": "Products.Product Name",
              "active": true
            },
            {
              "field": {
                "Measure": {
                  "Expression": { "SourceRef": { "Entity": "Sales" } },
                  "Property": "Total Sales"
                }
              },
              "queryRef": "Sales.Total Sales",
              "active": true
            },
            {
              "field": {
                "Measure": {
                  "Expression": { "SourceRef": { "Entity": "Sales" } },
                  "Property": "Total Quantity"
                }
              },
              "queryRef": "Sales.Total Quantity",
              "active": true
            }
          ]
        }
      }
    }
  }
}
```

### Matrix

```json
{
  "name": "matrix1",
  "position": { "x": 20, "y": 20, "width": 600, "height": 400, "z": 0, "tabOrder": 0 },
  "visual": {
    "visualType": "pivotTable",
    "query": {
      "queryState": {
        "Rows": {
          "projections": [{
            "field": {
              "Column": {
                "Expression": { "SourceRef": { "Entity": "Products" } },
                "Property": "Category"
              }
            },
            "queryRef": "Products.Category",
            "active": true
          }]
        },
        "Columns": {
          "projections": [{
            "field": {
              "Column": {
                "Expression": { "SourceRef": { "Entity": "Date" } },
                "Property": "Year"
              }
            },
            "queryRef": "Date.Year",
            "active": true
          }]
        },
        "Values": {
          "projections": [{
            "field": {
              "Measure": {
                "Expression": { "SourceRef": { "Entity": "Sales" } },
                "Property": "Total Sales"
              }
            },
            "queryRef": "Sales.Total Sales",
            "active": true
          }]
        }
      }
    }
  }
}
```

### Slicer

```json
{
  "name": "slicer1",
  "position": { "x": 20, "y": 20, "width": 200, "height": 300, "z": 0, "tabOrder": 0 },
  "visual": {
    "visualType": "slicer",
    "query": {
      "queryState": {
        "Values": {
          "projections": [{
            "field": {
              "Column": {
                "Expression": { "SourceRef": { "Entity": "Products" } },
                "Property": "Category"
              }
            },
            "queryRef": "Products.Category",
            "active": true
          }]
        }
      }
    },
    "objects": {
      "general": [{
        "properties": {
          "orientation": { "expr": { "Literal": { "Value": "'Vertical'" } } }
        }
      }],
      "selection": [{
        "properties": {
          "selectAllCheckboxEnabled": { "expr": { "Literal": { "Value": "true" } } },
          "singleSelect": { "expr": { "Literal": { "Value": "false" } } }
        }
      }]
    }
  }
}
```

### Date Slicer

```json
{
  "name": "dateSlicer1",
  "position": { "x": 20, "y": 20, "width": 300, "height": 80, "z": 0, "tabOrder": 0 },
  "visual": {
    "visualType": "slicer",
    "query": {
      "queryState": {
        "Values": {
          "projections": [{
            "field": {
              "Column": {
                "Expression": { "SourceRef": { "Entity": "Date" } },
                "Property": "Date"
              }
            },
            "queryRef": "Date.Date",
            "active": true
          }]
        }
      }
    },
    "objects": {
      "general": [{
        "properties": {
          "orientation": { "expr": { "Literal": { "Value": "'Horizontal'" } } }
        }
      }],
      "data": [{
        "properties": {
          "mode": { "expr": { "Literal": { "Value": "'Between'" } } }
        }
      }]
    }
  }
}
```

## Semantic Query Format

The `query` object binds visuals to data. Key concepts:

### Field Reference

```json
{
  "field": {
    "Column": {
      "Expression": { "SourceRef": { "Entity": "TableName" } },
      "Property": "ColumnName"
    }
  }
}
```

### Measure Reference

```json
{
  "field": {
    "Measure": {
      "Expression": { "SourceRef": { "Entity": "TableName" } },
      "Property": "MeasureName"
    }
  }
}
```

### Query Buckets

| Bucket | Used By | Purpose |
|--------|---------|---------|
| `Category` | Charts | X-axis grouping |
| `Y` | Charts | Y-axis values |
| `Series` | Charts | Legend grouping |
| `Values` | Cards, Tables | Data fields |
| `Rows` | Matrix | Row headers |
| `Columns` | Matrix | Column headers |
| `Tooltips` | All | Hover information |

## Filters

### Visual-Level Filter

```json
{
  "name": "Filter123",
  "expression": {
    "Column": {
      "Expression": { "SourceRef": { "Entity": "Products" } },
      "Property": "Category"
    }
  },
  "type": "Categorical",
  "filter": {
    "Version": 2,
    "From": [{"Name": "p", "Entity": "Products", "Type": 0}],
    "Where": [{
      "Condition": {
        "In": {
          "Expressions": [{"Column": {"Expression": {"SourceRef": {"Source": "p"}}, "Property": "Category"}}],
          "Values": [[{"Literal": {"Value": "'Electronics'"}}]]
        }
      }
    }]
  }
}
```

### Page-Level Filter

Add to the page's `filters` array using the same structure.

## Conditional Formatting

### Data Bars

```json
{
  "objects": {
    "values": [{
      "properties": {
        "backColor": {
          "solid": { "color": { "expr": { "Literal": { "Value": "'#E8E8E8'" } } } }
        }
      }
    }]
  }
}
```

### Color by Rules

```json
{
  "properties": {
    "fontColor": {
      "expr": {
        "Conditional": {
          "Cases": [
            {
              "Condition": { "Comparison": { "Left": { "Measure": "..." }, "Right": { "Literal": { "Value": "0" } } } },
              "Value": { "Literal": { "Value": "'#FF0000'" } }
            }
          ],
          "Else": { "Literal": { "Value": "'#00FF00'" } }
        }
      }
    }
  }
}
```

## Boundaries and Constraints

### DO
- Always validate JSON syntax before saving
- Use unique `name` values for all visuals
- Reference only existing tables and measures
- Test visuals after creating page files
- Keep visual positions within page bounds
- Use `z` ordering for overlapping visuals

### DO NOT
- Never hardcode data values in visuals
- Never reference non-existent measures
- Never use duplicate visual names
- Never exceed page width/height bounds
- Never modify auto-generated IDs without testing

## Workflow Integration

After creating visuals:
1. **Open in Power BI Desktop** - Validate the report loads
2. **Check data binding** - Verify visuals show correct data
3. **Test interactions** - Confirm cross-filtering works
4. **Validate** - Use the `best-practices` skill for quality checks

## Common Issues

### "Visual won't render"
- Check JSON syntax (use JSON validator)
- Verify all table/measure references exist
- Ensure position is within page bounds

### "No data displayed"
- Verify `queryRef` matches the field path
- Check that measures are defined in semantic model
- Confirm table relationships exist

### "Page won't load"
- Validate page.json has required properties
- Check `$schema` reference is correct
- Ensure `name` follows expected format

## Source & license

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

- **Author:** [kpbray](https://github.com/kpbray)
- **Source:** [kpbray/power-bi-agent-skills](https://github.com/kpbray/power-bi-agent-skills)
- **License:** MIT

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

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-kpbray-power-bi-agent-skills-report-visuals
- Seller: https://agentstack.voostack.com/s/kpbray
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
