faitza.com
faitza.com
> blog_tech

Exports Excel depuis PowerShell avec ImportExcel

Calcul... powershell excel automation reporting
Export Excel PowerShell ImportExcel

Introduction

Export-Faitza_Export_Excel encapsule le module ImportExcel pour produire des fichiers .xlsx directement depuis PowerShell — sans Excel installé. La fonction gère deux modes : export simple (une table, un onglet) et export multi-onglets via un tableau de configurations -liste. Une fonction interne Get-Sanitize_ExcelData nettoie automatiquement les données avant l'écriture : suppression de caractères invisibles, échappement des formules injection et troncature à 32 700 caractères.

Prérequis

Le module ImportExcel doit être installé :

Install-Module -Name ImportExcel -Scope CurrentUser

Export-Faitza_Export_Excel

Génère un fichier .xlsx depuis un objet PowerShell ou une liste d'onglets. Supporte la désactivation de la date dans le nom de fichier (-nodate), la conservation d'un fichier existant (-keep) et le nommage personnalisé de la table Excel (-nametable).

function Export-Faitza_Export_Excel {
    [CmdletBinding()]
    param(
        [switch]$nodate,
        [bool]$keep,
        [string]$name,
        $data,
        [string]$nametable,
        $liste
    )

    try {
        Write-Host "$($PSStyle.Background.Red)>>> Export-Faitza_Export_Excel <<<$($PSStyle.Reset)"

        if (-not $name) { throw "Il manque le nom du fichier (-name)." }
        if (-not $data -and -not $liste) { throw "Il manque les donnees a exporter (-data ou -liste)." }

        Import-Module ImportExcel

        if ($nametable) {
            $nametable = $nametable.Replace("-", "_")
        } else {
            $nametable = "Table_$($name.Replace("-", "_"))"
        }

        if ($nodate) {
            $file_xlsx = "$env:TEMP\$name.xlsx"
        } else {
            $file_xlsx = "$env:TEMP\$((Get-Date).tostring('yyyyMMdd'))-$name.xlsx"
        }

        # ... Get-Sanitize_ExcelData définie ici (voir ci-dessous)

        if ((Test-Path -Path $file_xlsx -PathType Leaf) -and -not $keep) {
            Remove-Item -Path $file_xlsx -Force -ErrorAction SilentlyContinue
        }

        if ($liste) {
            $liste | ForEach-Object {
                Write-Host "Export_Excel : $($_.nametable)"
                Get-Sanitize_ExcelData -InputData $_.data
                $_.data | Export-Excel -Path $file_xlsx -Worksheetname $_.nametable -Tablename $_.nametable -AutoFilter -AutoSize -TableStyle Medium1 -Append
            }
        } else {
            Write-Host "Export_Excel : $($file_xlsx.split('\')[-1]) $nametable"
            Get-Sanitize_ExcelData -InputData $data
            $data | Export-Excel -Path $file_xlsx -Worksheetname $nametable -Tablename $nametable -AutoFilter -AutoSize -TableStyle Medium1 -Append
        }

        return $file_xlsx
    } catch {
        $ErrorMessage = $_.Exception.Message
        $InnerError = if ($null -ne $_.Exception.InnerException) { $_.Exception.InnerException.Message } else { "Aucune" }
        Write-Host "CRASH EXPORT EXCEL" -ForegroundColor Red
        Write-Host "Fichier cible : $(if ($file_xlsx) { $file_xlsx.split('\')[-1] } else { 'Non defini' })" -ForegroundColor Yellow
        Write-Host "Onglet cible  : $(if ($nametable) { $nametable } else { 'Non defini' })" -ForegroundColor Yellow
        Write-Host "Erreur brute  : $ErrorMessage" -ForegroundColor Yellow
        Write-Host "Cause reelle  : $InnerError" -ForegroundColor Cyan
        throw "Erreur fatale lors de l'export Excel vers '$($name)' : $ErrorMessage | Cause Profonde: $InnerError"
    } finally {
        Write-Host "$($PSStyle.Background.Red)<<< Export-Faitza_Export_Excel >>>$($PSStyle.Reset)"
    }
}

Get-Sanitize_ExcelData (imbriquée)

Fonction interne définie à l'intérieur de Export-Faitza_Export_Excel. Elle parcourt chaque ligne de données et applique trois corrections automatiques sur les valeurs de type [string] :

  • Suppression des caractères de contrôle invisibles (\x00–\x08, \x0B–\x1F)
  • Échappement des débuts de formule (=, -, +) par un apostrophe
  • Troncature à 32 700 caractères (limite cellule Excel)
        function Get-Sanitize_ExcelData {
            param($InputData)
            if ($null -eq $InputData) { return }

            $RowIndex = 1
            foreach ($row in $InputData) {
                if ($null -eq $row -or $row -isnot [psobject]) { continue }

                foreach ($prop in $row.psobject.properties) {
                    $val = $prop.value
                    if ($null -ne $val -and $val -is [string]) {
                        $isModified = $false

                        if ($val -match '[\x00-\x08\x0B\x0C\x0E-\x1F]') {
                            Write-Host "[AUTO-FIX] Ligne $RowIndex, Col '$($prop.name)' : caracteres invisibles supprimes." -ForegroundColor Yellow
                            $val = $val -replace '[\x00-\x08\x0B\x0C\x0E-\x1F]', ''
                            $isModified = $true
                        }

                        if ($val -match "^[=\-\+]") {
                            Write-Host "[AUTO-FIX] Ligne $RowIndex, Col '$($prop.name)' : signe '$($val.Substring(0,1))' echappe." -ForegroundColor Yellow
                            $val = "'" + $val
                            $isModified = $true
                        }

                        if ($val.Length -gt 32700) {
                            Write-Host "[AUTO-FIX] Ligne $RowIndex, Col '$($prop.name)' : texte tronque."
                            $val = $val.Substring(0, 32700) + "... [TRONQUE]"
                            $isModified = $true
                        }

                        if ($isModified) { $prop.value = $val }
                    }
                }
                $RowIndex++
            }
        }

Exemples d'utilisation

Export simple — un onglet

$data = Get-ADUser -Filter * -Properties DisplayName, EmailAddress, Enabled |
    Select-Object DisplayName, EmailAddress, Enabled

$file = Export-Faitza_Export_Excel -name "Utilisateurs-AD" -data $data
Write-Host "Fichier genere : $file"

Export multi-onglets — liste de tables

$liste = @(
    @{ nametable = "Utilisateurs"; data = $data_users },
    @{ nametable = "Groupes";      data = $data_groups },
    @{ nametable = "Licences";     data = $data_licences }
)

$file = Export-Faitza_Export_Excel -name "Rapport-Mensuel" -liste $liste
Write-Host "Export multi-onglets : $file"

Sans date dans le nom de fichier

# Nom fixe sans préfixe de date
$file = Export-Faitza_Export_Excel -name "Inventaire" -data $data -nodate

# Conserver un fichier existant au lieu de le supprimer
$file = Export-Faitza_Export_Excel -name "Log" -data $data -keep $true

// Commentaires

Aucun commentaire pour l'instant.