Export

23 views
Skip to first unread message

Alfred Mühlleitner

unread,
Mar 1, 2025, 7:08:21 PMMar 1
to jGnash-User
I have created a powerscript that exports all transactions from jGnash to a csv-file

You may be interested and use it without any warrenty:

# Setze den Pfad zur XML-Datei automatisch auf den Skript-Ordner
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$transactionsXmlFile = "$scriptDir\test.xml"
$outputCsvTransactionsBase = "$scriptDir\transact"
$outputCsvAccounts = "$scriptDir\accounts.csv"
$outputCsvUnknownAccounts = "$scriptDir\unknown_accounts_transactions.csv"

# Prüfe, ob die Datei existiert
if (-Not (Test-Path $transactionsXmlFile)) {
    Write-Host "Fehler: Die Datei test.xml wurde nicht gefunden!" -ForegroundColor Red
    exit
}

# XML-Datei einlesen
[xml]$transactionsXmlData = Get-Content $transactionsXmlFile

# Alle Accounts aus test.xml sammeln, um Namen anhand der ID nachschlagen zu können
$accountMap = @{}
$transactionsXmlData.SelectNodes("//Account | //creditAccount | //debitAccount | //parentAccount") | ForEach-Object {
    if ($_.id -and $_.name) {
        $accountMap[$_.id] = $_.name
    }
}

# Funktion zum Nachschlagen von Account-Namen
function Get-AccountName {
    param (
        [string]$accountId,
        [System.Xml.XmlElement]$accountNode
    )
    if ($accountId) {
        if ($accountMap.ContainsKey($accountId)) {
            return $accountMap[$accountId]
        } else {
            Write-Host "Warnung: Account-ID $accountId nicht in der Account-Map gefunden." -ForegroundColor Yellow
            return "Unbekannt"  # Gebe "Unbekannt" zurück, falls der Name nicht gefunden wird
        }
    } elseif ($accountNode -and $accountNode.name) {
        return $accountNode.name
    }
    Write-Host "Warnung: Leere Account-ID und kein Account-Node gefunden." -ForegroundColor Yellow
    return "Unbekannt"
}

# Funktion zum Formatieren des Datums
function Format-Date {
    param (
        [string]$date
    )
    if ($date) {
        try {
            $dateTime = [datetime]::ParseExact($date, "yyyy-MM-dd", $null)
            return $dateTime.ToString("dd.MM.yyyy")
        } catch {
            Write-Host "Warnung: Konnte Datum '$date' nicht formatieren." -ForegroundColor Yellow
            return $date
        }
    }
    return $date
}

# Funktion zum Formatieren des Betrags
function Format-Amount {
    param (
        [string]$amount
    )
    if ($amount) {
        # Ersetze Punkt durch Komma und formatiere als Währung ohne Tausendertrennzeichen
        $formattedAmount = $amount -replace '\.', ','
        return "{0:0.00}" -f ([decimal]::Parse($formattedAmount))
    }
    return "0,00"
}

# Alle Transaktionen finden
$transactions = $transactionsXmlData.SelectNodes("//Transaction")

# Prüfen, ob Transaktionen vorhanden sind
if ($transactions.Count -eq 0) {
    exit
}

# Array für CSV-Daten (Transaktionen)
$transactionList = @()
$unknownTransactionList = @()
$counter = 0
$fileIndex = 1

foreach ($t in $transactions) {
    # Extrahiere das Datum und den Payee der Transaktion
    $date = Format-Date -date $t.date
    $payee = $t.payee
    $memo = $t.memo

    # Gehe durch alle TransactionEntries, um Split-Transaktionen zu berücksichtigen
    foreach ($transactionEntry in $t.transactionEntries.TransactionEntry) {
        # Prüfe, ob `debitAccount` und `creditAccount` als Referenzen oder direkte Knoten vorliegen
        $debitAccountRef = $transactionEntry.debitAccount.reference
        $debitAccountNode = $transactionEntry.debitAccount
        $creditAccountRef = $transactionEntry.creditAccount.reference
        $creditAccountNode = $transactionEntry.creditAccount

        # Namen der Accounts nachschlagen, falls vorhanden
        $debitAccount = Get-AccountName -accountId $debitAccountRef -accountNode $debitAccountNode
        $creditAccount = Get-AccountName -accountId $creditAccountRef -accountNode $creditAccountNode

        # Prüfe, ob Beträge existieren und formatiere die Werte als Währung
        $creditAmount = if ($transactionEntry.creditAmount) { Format-Amount -amount $transactionEntry.creditAmount } else { "0,00" }
        $debitAmount = if ($transactionEntry.debitAmount) { Format-Amount -amount $transactionEntry.debitAmount } else { "0,00" }

        # Erstelle das Objekt für CSV (Transaktionen)
        $entry = [PSCustomObject]@{
            Date             = $date
            Payee            = $payee
            Memo             = $memo
            Amount           = $creditAmount
            DebitAmount      = $debitAmount
            DebitAccount     = $debitAccount
            CreditAccount    = $creditAccount
        }

        if ($debitAccount -eq "Unbekannt" -or $creditAccount -eq "Unbekannt") {
            $unknownTransactionList += $entry
        } else {
            $transactionList += $entry
        }

        # Erhöhe den Zähler und zeige alle 5.000 Zeilen eine Meldung an
        $counter++
        if ($counter % 50000 -eq 0) {
            $outputCsvTransactions = "${outputCsvTransactionsBase}_${fileIndex}.csv"
            $csvStringTransactions = $transactionList | ConvertTo-Csv -NoTypeInformation -Delimiter ';' | Out-String
            [System.IO.File]::WriteAllText($outputCsvTransactions, $csvStringTransactions, [System.Text.Encoding]::Default)
            Write-Host "$counter Transaktionen verarbeitet und in $outputCsvTransactions gespeichert..." -ForegroundColor Yellow
            $transactionList = @()
            $fileIndex++
        }
    }
}

# Exportiere verbleibende Transaktionen
if ($transactionList.Count -gt 0) {
    $outputCsvTransactions = "${outputCsvTransactionsBase}_${fileIndex}.csv"
    $csvStringTransactions = $transactionList | ConvertTo-Csv -NoTypeInformation -Delimiter ';' | Out-String
    [System.IO.File]::WriteAllText($outputCsvTransactions, $csvStringTransactions, [System.Text.Encoding]::Default)
}

# Exportiere Transaktionen mit unbekannten Accounts
if ($unknownTransactionList.Count -gt 0) {
    $csvStringUnknownTransactions = $unknownTransactionList | ConvertTo-Csv -NoTypeInformation -Delimiter ';' | Out-String
    [System.IO.File]::WriteAllText($outputCsvUnknownAccounts, $csvStringUnknownTransactions, [System.Text.Encoding]::Default)
}

# Array für CSV-Daten (Konten)
$accountList = @()
foreach ($id in $accountMap.Keys) {
    $account = [PSCustomObject]@{
        AccountID = $id
        AccountName = $accountMap[$id]
    }
    $accountList += $account
}

# In eine Zwischenstring-Variable für Konten exportieren
$csvStringAccounts = $accountList | ConvertTo-Csv -NoTypeInformation -Delimiter ';' | Out-String

# Die Zwischenstring-Variable manuell in Datei mit ANSI-Kodierung schreiben
[System.IO.File]::WriteAllText($outputCsvAccounts, $csvStringAccounts, [System.Text.Encoding]::Default)

# Erfolgsmeldung ausgeben
Write-Host "Export abgeschlossen: $outputCsvAccounts, ${outputCsvTransactionsBase}_*.csv und $outputCsvUnknownAccounts" -ForegroundColor Green
Reply all
Reply to author
Forward
0 new messages