← Files Power BI DesktopARCHIVED FILE
scripts/New-PowerBIDependencyGraph.ps1
4.16 KB · Oct 2, 2026 · 00:32 UTC
param(
[string]$Path = ".",
[string]$OutputPath,
[switch]$Json,
[switch]$Mermaid
)
$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)
$metricByName = @{}
foreach ($metric in $metrics) {
$metricByName[$metric.name.ToLowerInvariant()] = $metric
}
$edgeList = New-Object System.Collections.Generic.List[object]
$edgeKeys = @{}
foreach ($metric in $metrics) {
foreach ($match in [regex]::Matches($metric.expression, '\[(?<name>[^\]]+)\]')) {
$targetName = $match.Groups['name'].Value.Trim()
if ($targetName -and $targetName -ne $metric.name -and $metricByName.ContainsKey($targetName.ToLowerInvariant())) {
$edgeKey = ('{0}->{1}' -f $metric.name.ToLowerInvariant(), $targetName.ToLowerInvariant())
if ($edgeKeys.ContainsKey($edgeKey)) {
continue
}
$edgeKeys[$edgeKey] = $true
$edgeList.Add([pscustomobject]@{
from = $metric.name
to = $targetName
fromId = $metric.id
toId = $metricByName[$targetName.ToLowerInvariant()].id
source = $metric.source
})
}
}
}
$graphEdges = @($edgeList.ToArray())
$nodes = @(foreach ($metric in $metrics) {
$incoming = @($graphEdges | Where-Object { $_.to -eq $metric.name }).Count
$outgoing = @($graphEdges | Where-Object { $_.from -eq $metric.name }).Count
[pscustomobject]@{
id = $metric.id
name = $metric.name
table = $metric.table
source = $metric.source
riskLevel = $metric.riskLevel
incoming = $incoming
outgoing = $outgoing
hubScore = $incoming + $outgoing
}
})
$hubMetrics = @($nodes | Sort-Object -Property hubScore -Descending | Select-Object -First 10)
$graph = [pscustomobject]@{
schema = 'codex.powerbi.dependencyGraph.v1'
root = $catalog.root
generated = (Get-Date).ToString('s')
nodeCount = @($nodes).Count
edgeCount = @($graphEdges).Count
hubMetrics = @($hubMetrics)
nodes = @($nodes)
edges = @($graphEdges)
}
if ($Json) {
$jsonText = $graph | ConvertTo-Json -Depth 8
if ($OutputPath) {
Set-Content -LiteralPath $OutputPath -Value $jsonText -Encoding UTF8
}
$jsonText
return
}
if ($Mermaid) {
$lines = New-Object System.Collections.Generic.List[string]
$lines.Add('flowchart LR')
foreach ($node in $nodes) {
$safeId = $node.id -replace '[^A-Za-z0-9_]', '_'
$label = $node.name.Replace('"', "'")
$lines.Add((' {0}["{1}"]' -f $safeId, $label))
}
foreach ($edge in $graphEdges) {
$from = $edge.fromId -replace '[^A-Za-z0-9_]', '_'
$to = $edge.toId -replace '[^A-Za-z0-9_]', '_'
$lines.Add((' {0} --> {1}' -f $from, $to))
}
$content = ($lines -join [Environment]::NewLine) + [Environment]::NewLine
if ($OutputPath) {
Set-Content -LiteralPath $OutputPath -Value $content -Encoding UTF8
}
$content
return
}
$md = New-Object System.Collections.Generic.List[string]
$md.Add('# Power BI DAX Dependency Graph')
$md.Add('')
$md.Add(('Schema: `{0}`' -f $graph.schema))
$md.Add(('Metrics: {0}' -f $graph.nodeCount))
$md.Add(('Dependencies: {0}' -f $graph.edgeCount))
$md.Add('')
$md.Add('## Hub Metrics')
$md.Add('')
foreach ($node in $graph.hubMetrics) {
$md.Add(('- `{0}`: incoming {1}, outgoing {2}, risk {3}' -f $node.name, $node.incoming, $node.outgoing, $node.riskLevel))
}
$md.Add('')
$md.Add('## Dependencies')
$md.Add('')
if ($graphEdges.Count -eq 0) {
$md.Add('No metric-to-metric dependencies detected.')
}
else {
foreach ($edge in $graphEdges) {
$md.Add(('- `{0}` depends on `{1}`' -f $edge.from, $edge.to))
}
}
$content = ($md -join [Environment]::NewLine) + [Environment]::NewLine
if ($OutputPath) {
Set-Content -LiteralPath $OutputPath -Value $content -Encoding UTF8
}
$content
SHA-256: f008104dc18ea323f2ddc7cffd070dcc3bd5fc3ff539c79a67a1d98521b2e0ef