← Files Power BI DesktopARCHIVED FILE

scripts/New-PowerBIVisualMeasureImpactMap.ps1

4.45 KB · Oct 2, 2026 · 00:32 UTC

↓ Download file

param([string]$Path = ".", [string]$OutputPath, [switch]$Json)
$ErrorActionPreference = 'Stop'

function Get-RelativePath {
    param([string]$BasePath, [string]$TargetPath)
    if ([System.IO.Path].GetMethod('GetRelativePath', [type[]]@([string], [string]))) {
        return [System.IO.Path]::GetRelativePath($BasePath, $TargetPath)
    }
    $baseUri = [Uri]((Join-Path $BasePath '.') + [System.IO.Path]::DirectorySeparatorChar)
    $targetUri = [Uri]$TargetPath
    [Uri]::UnescapeDataString($baseUri.MakeRelativeUri($targetUri).ToString()).Replace('/', [System.IO.Path]::DirectorySeparatorChar)
}

function Get-JsonFiles {
    param([string]$Root)
    Get-ChildItem -LiteralPath $Root -Recurse -File -Include *.json -ErrorAction SilentlyContinue |
        Where-Object { $_.FullName -match '(?i)(Report|report|definition|pages|visual)' } |
        Sort-Object FullName
}

function Get-VisualRecords {
    param([string]$Root)
    foreach ($file in Get-JsonFiles -Root $Root) {
        $relative = Get-RelativePath -BasePath $Root -TargetPath $file.FullName
        $text = Get-Content -Raw -LiteralPath $file.FullName
        $json = $null
        try { $json = $text | ConvertFrom-Json -ErrorAction Stop } catch { $json = $null }
        $visualType = $null
        $visualName = [System.IO.Path]::GetFileNameWithoutExtension($file.Name)
        if ($json) {
            if ($json.visualType) { $visualType = [string]$json.visualType }
            elseif ($json.singleVisual.visualType) { $visualType = [string]$json.singleVisual.visualType }
            elseif ($json.config) {
                try {
                    $config = $json.config | ConvertFrom-Json -ErrorAction Stop
                    if ($config.singleVisual.visualType) { $visualType = [string]$config.singleVisual.visualType }
                    if ($config.name) { $visualName = [string]$config.name }
                }
                catch {}
            }
            if ($json.name) { $visualName = [string]$json.name }
        }
        [pscustomobject]@{
            name = $visualName
            visualType = if ($visualType) { $visualType } else { 'Unknown' }
            source = $relative
            text = $text
        }
    }
}

$scriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
$catalog = & (Join-Path $scriptRoot 'New-PowerBIMetricCatalog.ps1') -Path $Path -Json | ConvertFrom-Json
$resolved = (Resolve-Path -LiteralPath $Path).Path
$visualRecords = @(Get-VisualRecords -Root $resolved)
$reportText = ($visualRecords | ForEach-Object { $_.text }) -join [Environment]::NewLine
$items = foreach ($metric in @($catalog.metrics)) {
    $hits = if ($reportText) { ([regex]::Matches($reportText, [regex]::Escape($metric.name))).Count } else { 0 }
    $affected = @($visualRecords | Where-Object { $_.text -match [regex]::Escape($metric.name) } | ForEach-Object {
        [pscustomobject]@{ visual = $_.name; visualType = $_.visualType; source = $_.source }
    })
    [pscustomobject]@{
        measure = $metric.name
        table = $metric.table
        detectedVisualReferences = $hits
        affectedVisuals = @($affected)
        affectedPages = $(if ($hits -gt 0) { @($affected | Select-Object -ExpandProperty source -Unique) } else { @() })
        lineageConfidence = if ($hits -gt 0) { 'MetadataMatch' } else { 'NotDetected' }
        impactGuidance = $(if ($hits -gt 0) { 'Validate affected visuals, tooltips, drillthrough paths, and filter interactions before publishing.' } else { 'No visual metadata reference detected; validate manually or export PBIP report metadata.' })
    }
}
$result = [pscustomobject]@{
    schema = 'codex.powerbi.visualMeasureImpactMap.v1'
    root = $catalog.root
    generated = (Get-Date).ToString('s')
    reportMetadataStatus = if ($visualRecords.Count -gt 0) { 'Available' } else { 'NotAvailable' }
    visualCount = $visualRecords.Count
    measureCount = @($items).Count
    impacts = @($items)
}
if ($Json) { $text = $result | ConvertTo-Json -Depth 8; if ($OutputPath) { Set-Content -LiteralPath $OutputPath -Value $text -Encoding UTF8 }; $text; return }
$md = @('# Power BI Visual-to-Measure Impact Map', '') + @($result.impacts | ForEach-Object { "- `$($_.measure)`: $($_.detectedVisualReferences) visual metadata references. $($_.impactGuidance)" })
$content = ($md -join [Environment]::NewLine) + [Environment]::NewLine
if ($OutputPath) { Set-Content -LiteralPath $OutputPath -Value $content -Encoding UTF8 }
$content

SHA-256: 66b961bba7e677103f04d4ec6edc7c2d0b02e3b5a64feb99c8051e0b8ba02edf