Public/Export-BudgetData.ps1

function Export-BudgetData {
    <#
    .SYNOPSIS
        Exports all budgets and workspace data.
 
    .DESCRIPTION
        Exports all budgets from the workspace to a folder or compressed archive.
        Optionally includes workspace preferences.
 
    .PARAMETER OutputPath
        The folder path or .zip file for the export.
 
    .PARAMETER Format
        Output format for entity files: CSV or JSON. Defaults to JSON.
 
    .PARAMETER IncludePreferences
        Include the workspace preferences.json file.
 
    .PARAMETER Compress
        Create a .zip archive instead of a folder.
 
    .PARAMETER WorkspacePath
        Optional custom workspace path.
 
    .EXAMPLE
        Export-BudgetData -OutputPath "C:\Backups\AllBudgets"
 
        Exports all budgets to a folder.
 
    .EXAMPLE
        Export-BudgetData -OutputPath "full-backup.zip" -Compress -IncludePreferences
 
        Exports all budgets with preferences to a compressed archive.
 
    .EXAMPLE
        Export-BudgetData -OutputPath "C:\Backups\AllBudgets" -Format CSV
 
        Exports all budgets in CSV format.
 
    .OUTPUTS
        Path to the exported folder or archive
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$OutputPath,

        [Parameter()]
        [ValidateSet('CSV', 'JSON')]
        [string]$Format = 'JSON',

        [Parameter()]
        [switch]$IncludePreferences,

        [Parameter()]
        [switch]$Compress,

        [Parameter()]
        [string]$WorkspacePath
    )

    # Determine if output is a zip file
    $isZipOutput = $OutputPath -like '*.zip'
    if ($isZipOutput) {
        $Compress = $true
    }

    # Set up export folder
    if ($Compress -and -not $isZipOutput) {
        $zipPath = "$OutputPath.zip"
        $exportFolder = Join-Path $env:TEMP "BudgetDataExport_$(Get-Date -Format 'yyyyMMddHHmmss')"
    }
    elseif ($isZipOutput) {
        $zipPath = $OutputPath
        $exportFolder = Join-Path $env:TEMP "BudgetDataExport_$(Get-Date -Format 'yyyyMMddHHmmss')"
    }
    else {
        $exportFolder = $OutputPath
    }

    # Ensure export folder exists
    if (-not (Test-Path $exportFolder)) {
        New-Item -Path $exportFolder -ItemType Directory -Force | Out-Null
    }

    try {
        # Get all budgets
        $budgets = Get-Budget -WorkspacePath $WorkspacePath

        if (-not $budgets -or $budgets.Count -eq 0) {
            Write-Warning "No budgets found to export."
            return
        }

        # Create budgets subfolder
        $budgetsFolder = Join-Path $exportFolder 'budgets'
        New-Item -Path $budgetsFolder -ItemType Directory -Force | Out-Null

        # Export each budget
        foreach ($budget in $budgets) {
            $budgetName = $budget.Name
            $budgetExportPath = Join-Path $budgetsFolder $budgetName

            Write-Verbose "Exporting budget: $budgetName"

            Export-Budget -OutputPath $budgetExportPath -Budget $budgetName -Format $Format -IncludeMetadata | Out-Null
        }

        Write-Verbose "Exported $($budgets.Count) budget(s)"

        # Export preferences if requested
        if ($IncludePreferences) {
            if (-not $WorkspacePath) {
                $WorkspacePath = Get-WorkspacePath
            }

            $preferencesSource = Join-Path $WorkspacePath 'preferences.json'
            if (Test-Path $preferencesSource) {
                $preferencesDest = Join-Path $exportFolder 'preferences.json'
                Copy-Item -Path $preferencesSource -Destination $preferencesDest
                Write-Verbose "Exported preferences to: $preferencesDest"
            }
            else {
                Write-Warning "Preferences file not found at: $preferencesSource"
            }
        }

        # Add export metadata
        $exportMetadata = [PSCustomObject]@{
            ExportDate = (Get-Date).ToString('o')
            BudgetCount = $budgets.Count
            Format = $Format
            IncludesPreferences = $IncludePreferences.IsPresent
        }
        $exportMetadataPath = Join-Path $exportFolder 'export-info.json'
        $exportMetadata | ConvertTo-Json | Set-Content -Path $exportMetadataPath
        Write-Verbose "Created export metadata: $exportMetadataPath"

        # Compress if requested
        if ($Compress) {
            # Ensure parent directory of zip file exists
            $zipParent = Split-Path -Path $zipPath -Parent
            if ($zipParent -and -not (Test-Path $zipParent)) {
                New-Item -Path $zipParent -ItemType Directory -Force | Out-Null
            }

            Compress-Archive -Path "$exportFolder\*" -DestinationPath $zipPath -Force
            Write-Verbose "Created archive: $zipPath"

            # Clean up temp folder
            Remove-Item -Path $exportFolder -Recurse -Force

            return (Resolve-Path $zipPath).Path
        }
        else {
            return (Resolve-Path $exportFolder).Path
        }
    }
    catch {
        Write-Error "Failed to export budget data: $_"

        # Clean up temp folder on error if compressing
        if ($Compress -and (Test-Path $exportFolder)) {
            Remove-Item -Path $exportFolder -Recurse -Force -ErrorAction SilentlyContinue
        }
    }
}