← Files Power BI DesktopARCHIVED FILE
scripts/New-PowerBIReportBlueprint.ps1
4.04 KB · Oct 2, 2026 · 00:32 UTC
param(
[string]$Path = ".",
[string]$OutputPath,
[switch]$Json
)
$ErrorActionPreference = 'Stop'
$scriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
$catalogScript = Join-Path $scriptRoot 'New-PowerBIMetricCatalog.ps1'
$catalog = & $catalogScript -Path $Path -Json | ConvertFrom-Json
$metrics = @($catalog.metrics)
$financeMetrics = @($metrics | Where-Object { $_.tags -contains 'finance' })
$timeMetrics = @($metrics | Where-Object { $_.tags -contains 'time-intelligence' })
$reviewMetrics = @($metrics | Where-Object { $_.riskLevel -eq 'review' })
$pages = @(
[pscustomobject]@{
Name = 'Executive Overview'
Purpose = 'Give leadership a fast read on the most important governed metrics.'
Visuals = @(
'KPI row for primary finance metrics',
'Trend line for time-intelligence metrics',
'Variance callout for metrics tagged as ratio or YoY',
'Risk banner if review metrics remain unresolved'
)
Measures = @($financeMetrics | Select-Object -First 6 | ForEach-Object { $_.name })
},
[pscustomobject]@{
Name = 'Metric Diagnostics'
Purpose = 'Expose measure definitions, owners, and validation state for analysts.'
Visuals = @(
'Metric catalog table with owner, business definition, and risk level',
'DAX review queue filtered to riskLevel = review',
'Validation checklist slicer by source file'
)
Measures = @($reviewMetrics | ForEach-Object { $_.name })
},
[pscustomobject]@{
Name = 'Model Governance'
Purpose = 'Track project readiness, source-control posture, and refresh dependencies.'
Visuals = @(
'Finding count by severity',
'Power Query dependency list',
'PBIP/TMDL readiness status',
'Next-action backlog'
)
Measures = @()
}
)
if ($timeMetrics.Count -eq 0) {
$pages[0].Visuals += 'Date slicer with explicit latest refresh date label'
}
$blueprint = [pscustomobject]@{
schema = 'codex.powerbi.reportBlueprint.v1'
root = $catalog.root
generated = (Get-Date).ToString('s')
metricCount = $catalog.metricCount
pageCount = $pages.Count
designPrinciples = @(
'Use dense, scannable executive pages with clear metric ownership.',
'Keep diagnostic and governance content separate from business-consumption pages.',
'Surface unresolved metric risks visibly until owners sign off.',
'Avoid ambiguous KPI titles; use business definitions from the metric catalog.'
)
pages = $pages
}
if ($Json) {
$jsonText = $blueprint | ConvertTo-Json -Depth 8
if ($OutputPath) {
Set-Content -LiteralPath $OutputPath -Value $jsonText -Encoding UTF8
}
$jsonText
return
}
$lines = New-Object System.Collections.Generic.List[string]
$lines.Add('# Power BI Report Blueprint')
$lines.Add('')
$lines.Add(('Schema: `{0}`' -f $blueprint.schema))
$lines.Add(('Root: `{0}`' -f $blueprint.root))
$lines.Add(('Metrics considered: {0}' -f $blueprint.metricCount))
$lines.Add('')
$lines.Add('## Design Principles')
$lines.Add('')
foreach ($principle in $blueprint.designPrinciples) {
$lines.Add(('- {0}' -f $principle))
}
$lines.Add('')
$lines.Add('## Pages')
$lines.Add('')
foreach ($page in $blueprint.pages) {
$lines.Add(('### {0}' -f $page.Name))
$lines.Add('')
$lines.Add(('- Purpose: {0}' -f $page.Purpose))
$lines.Add('- Visuals:')
foreach ($visual in $page.Visuals) {
$lines.Add((' - {0}' -f $visual))
}
if ($page.Measures.Count -gt 0) {
$lines.Add(('- Measures: {0}' -f ($page.Measures -join ', ')))
}
else {
$lines.Add('- Measures: derived from scan and governance outputs')
}
$lines.Add('')
}
$markdown = ($lines -join [Environment]::NewLine) + [Environment]::NewLine
if ($OutputPath) {
Set-Content -LiteralPath $OutputPath -Value $markdown -Encoding UTF8
}
$markdown
SHA-256: 76f97598322f62ecaf9efec9ddf74f5050edcdc96c0c4aa17c5f46873d718ff4