Powershell - Bestimmte Daten aus Excel in neue Excel-Dateien schreiben und speichern
Hallo zusammen,
ich stocke bei folgender Aufgabe.
Ich habe eine Textdatei mit Zahlungsdaten, Aktenzeichen und dem Zahlungsempfänger.
Diese Datei konvertiere ich zuerst als CSV und lese sie dann in Excel ein.
Dort bereite ich dann die Daten auf. bestimmte Spalten löschen die unnötig sind und Spaltenbreite anpassen.
Nun möchte ich die Daten (Zeilen) nach Spalte F (Zahlungsempfänger) in eine eigene Excel Datei speichern, wobei die erste Zeile (Header) mit soll. Sodass ich am Ende beispielsweise 30 Excel Dateien habe wo nur die Buchungen der einzelnen ZEs drin sind.
Folgendes war meine erste Idee, welche nicht optimal ist.
Ich gehe durch jeden Eintrag in Spalte F. Wenn der Name noch nicht im Array vorhanden ist, dann speichere ihn dort ab und erstelle ein neues Worksheet [NOCH NICHT IM CODE => und kopiere den Header rein. Dort kopiere dann die aktuelle Zeile rein (Buchungsdaten).
Gehe zur nächsten Zeile, wenn diese noch nicht im Array ist, dann wie oben ansonsten kopiere Zeile, gehe zu dem Worksheet mit dem $Wert, gehe an letzte Zeile und füge ein.
usw.
Das stelle ich mir aber ziemlich PErformancelastig vor.
Einfacher wäre es wohl, die Tabelle zu Filtern.
D.h. ich hol mir erstmal ein Array mit allen möglichen ZE-Namen. Dann erstelle ich einen Loop der jeden Namen Filtert.
Ich Setze also einen Filter auf Spalte F, filter mit dem aktuellen $Wert aus dem Array und kopiere die ganze Tabelle in ein neues Worksheet und speichere das als neue Datei ab.
Geht es vll noch optimaler oder ist die Filter Variante die beste Option?
ich stocke bei folgender Aufgabe.
Ich habe eine Textdatei mit Zahlungsdaten, Aktenzeichen und dem Zahlungsempfänger.
Diese Datei konvertiere ich zuerst als CSV und lese sie dann in Excel ein.
Dort bereite ich dann die Daten auf. bestimmte Spalten löschen die unnötig sind und Spaltenbreite anpassen.
Nun möchte ich die Daten (Zeilen) nach Spalte F (Zahlungsempfänger) in eine eigene Excel Datei speichern, wobei die erste Zeile (Header) mit soll. Sodass ich am Ende beispielsweise 30 Excel Dateien habe wo nur die Buchungen der einzelnen ZEs drin sind.
$Textdatei = 'C:\Users\pvoelz\Desktop\Zahllisten\Zahlliste.txt'
$CSV = 'C:\Users\pvoelz\Desktop\Zahllisten\Zahlliste_NEU.csv'
((Get-Content $Textdatei) -replace '^\s+','' ) -replace ' *\t *',';' | convertfrom-csv -Delimiter ";" | `
export-csv -path $CSV -delimiter ";" -Encoding utf8 -NoType
$xlo = New-Object -ComObject excel.application
$xlo.visible = $true
$xlo.DisplayAlerts = $false
$xlw = $xlo.Workbooks.Open($CSV)
$xls = $xlw.worksheets.Item(1)
# Vorbereiten der Exceldatei für Aufteilung
$arrCols = @()
$arrCols += $xls.Range("C:C").EntireColumn
$arrCols += $xls.Range("G:G").EntireColumn
$arrCols += $xls.Range("H:H").EntireColumn
$arrCols += $xls.Range("J:J").EntireColumn
$arrCols += $xls.Range("K:K").EntireColumn
$arrCols += $xls.Range("O:O").EntireColumn
$arrCols | %{$_.Delete() | Out-Null}
$xlo.ActiveSheet.Range("A:I").EntireColumn.AutoFit()
[int]$zeile = 2
[int]$spalte = 6
[string]$arrName = @()
$Wert = $xls.Cells.Item($zeile,$spalte).Text
do {
$Wert = $xls.Cells.Item($zeile,$spalte).Text
If (!($arrName -match $Wert)) # Wenn die Einrichtung noch nicht bekannt, dann füge Sie einem Array hinzu
{
$arrName += $Wert
$LastSheet = $xlw.Worksheets|Select -Last 1
$NewSheet = $xlw.worksheets.add($LastSheet)
$NewSheet.Name = $Wert
# Write-Host $Wert
}
$zeile++
}
while ($xls.Cells.Item($zeile,$spalte).Text.Length -gt 0)
write-Host $arrName
# Speichern der Excel Datei
$xlo.ActiveWorkbook.SaveAS( "C:\Users\pvoelz\Desktop\Zahllisten\Neu.xlsx", [Microsoft.Office.Interop.Excel.XlFileFormat]::xlWorkbookDefault)
# Cleanup
$xlo.DisplayAlerts = $true
$xls = $null
$xlw.Close()
$xlo.Quit()
Folgendes war meine erste Idee, welche nicht optimal ist.
Ich gehe durch jeden Eintrag in Spalte F. Wenn der Name noch nicht im Array vorhanden ist, dann speichere ihn dort ab und erstelle ein neues Worksheet [NOCH NICHT IM CODE => und kopiere den Header rein. Dort kopiere dann die aktuelle Zeile rein (Buchungsdaten).
Gehe zur nächsten Zeile, wenn diese noch nicht im Array ist, dann wie oben ansonsten kopiere Zeile, gehe zu dem Worksheet mit dem $Wert, gehe an letzte Zeile und füge ein.
usw.
Das stelle ich mir aber ziemlich PErformancelastig vor.
Einfacher wäre es wohl, die Tabelle zu Filtern.
D.h. ich hol mir erstmal ein Array mit allen möglichen ZE-Namen. Dann erstelle ich einen Loop der jeden Namen Filtert.
Ich Setze also einen Filter auf Spalte F, filter mit dem aktuellen $Wert aus dem Array und kopiere die ganze Tabelle in ein neues Worksheet und speichere das als neue Datei ab.
Geht es vll noch optimaler oder ist die Filter Variante die beste Option?
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 501564
Url: https://administrator.de/forum/powershell-bestimmte-daten-aus-excel-in-neue-excel-dateien-schreiben-und-speichern-501564.html
Ausgedruckt am: 18.05.2025 um 12:05 Uhr
15 Kommentare
Neuester Kommentar

Group-Object ist wie dafür geschaffen
((Get-Content $Textdatei) -replace '^\s+','' ) -replace ' *\t *',';' | convertfrom-csv -Delimiter ";" | group "Zahlungsempfänger" | %{
$empfänger = $_.Name
$_.Group | export-csv "d:\Pfad\${empfänger}.csv" -NoType -Delimiter ":" -Encoding UTF8
}
Moin,
warum so kompliziert?
Warum machst Du das? Naja, warum auch nicht.
Warum liest Du das in Excel ein und nimmst nicht die Powershell-Cmdlets für CSV? So wäre das viel kürzer und schneller:
Und zum Schluss:
Oder auch gleich am Stück:
hth
Erik
warum so kompliziert?
Zitat von @Pat.bat:
$Textdatei = 'C:\Users\pvoelz\Desktop\Zahllisten\Zahlliste.txt'
> $CSV = 'C:\Users\pvoelz\Desktop\Zahllisten\Zahlliste_NEU.csv'
>
> ((Get-Content $Textdatei) -replace '^\s+','' ) -replace ' *\t *',';' | convertfrom-csv -Delimiter ";" | `
> export-csv -path $CSV -delimiter ";" -Encoding utf8 -NoType
>
Warum machst Du das? Naja, warum auch nicht.
$xlo = New-Object -ComObject excel.application
> $xlo.visible = $true
> $xlo.DisplayAlerts = $false
> $xlw = $xlo.Workbooks.Open($CSV)
> $xls = $xlw.worksheets.Item(1)
>
> # Vorbereiten der Exceldatei für Aufteilung
> $arrCols = @()
> $arrCols += $xls.Range("C:C").EntireColumn
> $arrCols += $xls.Range("G:G").EntireColumn
> $arrCols += $xls.Range("H:H").EntireColumn
> $arrCols += $xls.Range("J:J").EntireColumn
> $arrCols += $xls.Range("K:K").EntireColumn
> $arrCols += $xls.Range("O:O").EntireColumn
> $arrCols | %{$_.Delete() | Out-Null}
>
Warum liest Du das in Excel ein und nimmst nicht die Powershell-Cmdlets für CSV? So wäre das viel kürzer und schneller:
import-csv $csv -delimiter ";" | select * -excludeproperty [Liste der zu löschenden Spalten] | export-csv $csv -delimiter ";" -notypeinformation
$xlo.ActiveSheet.Range("A:I").EntireColumn.AutoFit()
>
> [int]$zeile = 2
> [int]$spalte = 6
> [string]$arrName = @()
>
> $Wert = $xls.Cells.Item($zeile,$spalte).Text
> do {
> $Wert = $xls.Cells.Item($zeile,$spalte).Text
> If (!($arrName -match $Wert)) # Wenn die Einrichtung noch nicht bekannt, dann füge Sie einem Array hinzu
> {
> $arrName += $Wert
> $LastSheet = $xlw.Worksheets|Select -Last 1
> $NewSheet = $xlw.worksheets.add($LastSheet)
> $NewSheet.Name = $Wert
> # Write-Host $Wert
> }
> $zeile++
> }
> while ($xls.Cells.Item($zeile,$spalte).Text.Length -gt 0)
>
> write-Host $arrName
>
> # Speichern der Excel Datei
> $xlo.ActiveWorkbook.SaveAS( "C:\Users\pvoelz\Desktop\Zahllisten\Neu.xlsx", [Microsoft.Office.Interop.Excel.XlFileFormat]::xlWorkbookDefault)
>
> # Cleanup
> $xlo.DisplayAlerts = $true
> $xls = $null
> $xlw.Close()
> $xlo.Quit()
Und zum Schluss:
$datasets = import-csv $csv -delimiter ";"
foreach($dataset in $datasets) {
$dataset | export-csv -path "$($dataset.kundenname).csv" -Append -Delimiter ";" -NoTypeInformation
}
Oder auch gleich am Stück:
$datasets = $(import-csv $csv -delimiter ";" | select * -excludeproperty [Liste der zu löschenden Spalten])
foreach($dataset in $datasets) {
$dataset | export-csv -path "$($dataset.kundenname).csv" -Append -Delimiter ";" -NoTypeInformation
}
hth
Erik

S. Code oben, reicht vollkommen für dein Vorhaben ...
Moin,
lies mal https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell. ... Damit kommst Du nicht weiter. Wenn Du das so machen willst, dann musst Du import-csv nehmen. Also erst die Delimiter tauschen (warum auch immer) und dann das manipulierte CSV als CSV einlesen. Dann hast Du die einzelnen Datensätze als CSV-Objekte in dem Array und kannst sie auch als CSV weiterverarbeiten.
Liebe Grüße
Erik
lies mal https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell. ... Damit kommst Du nicht weiter. Wenn Du das so machen willst, dann musst Du import-csv nehmen. Also erst die Delimiter tauschen (warum auch immer) und dann das manipulierte CSV als CSV einlesen. Dann hast Du die einzelnen Datensätze als CSV-Objekte in dem Array und kannst sie auch als CSV weiterverarbeiten.
Liebe Grüße
Erik
Moin,
Dann mit einer Regex am Besten gleich alle verbotenen Zeichen abfangen und durch z. B. Unterstrich ersetzen.
https://docs.microsoft.com/de-de/dotnet/standard/base-types/substitution ...
https://powershellexplained.com/2017-07-31-Powershell-regex-regular-expr ...
Das sollte allerdings ohne Weiteres funktionieren. Tippfehler?
Liebe Grüße
Erik
Zitat von @Pat.bat:
Allerdings gibt es einen ZE-Name, der ein Slash (/) im Namen hat und das führt bei der Anweisung
dazu das er das als anderen Pfad ansieht und so die Fehlermeldung schmeißt, das dieser Pfad unbekannt ist.
Allerdings gibt es einen ZE-Name, der ein Slash (/) im Namen hat und das führt bei der Anweisung
$dataset | export-csv -path "C:\Users\pvoelz\Desktop\Zahllisten\ZL\$($dataset.'ZE-Name').csv" -Append -Delimiter ";" -Encoding UTF8 -NoTypeInformation -Force
dazu das er das als anderen Pfad ansieht und so die Fehlermeldung schmeißt, das dieser Pfad unbekannt ist.
Dann mit einer Regex am Besten gleich alle verbotenen Zeichen abfangen und durch z. B. Unterstrich ersetzen.
https://docs.microsoft.com/de-de/dotnet/standard/base-types/substitution ...
https://powershellexplained.com/2017-07-31-Powershell-regex-regular-expr ...
Auch bekomme ich die Spalte "Betrag [€] auf/von Konto(Doppik)(...)" nicht raus gefiltert, was vermutlich an den Sonderzeichen liegen, die enthalten sind.
Das sollte allerdings ohne Weiteres funktionieren. Tippfehler?
Liebe Grüße
Erik
Moin,
Wenn es denn eine Exceldatei als Ausgabe sein soll, dann guck Dir das mal an. Das macht das Leben mit Exceldateien unter PS sehr viel einfacher.
https://www.powershellgallery.com/packages/ImportExcel/5.4.0
Liebe Grüße
Erik
Zitat von @Pat.bat:
Ich muss da leider nochmal umdenken, sodass xlsx Dateien dabei raus kommen. Grund, es ist eine Formatierung gewünscht, was leider nicht mit csv funktioniert.
Nun überlege ich, die CSV-Dateien trotzdem zu generieren und diese dann formatiert als xlsx abzuspeichern. Im nachhinein werden dann die csv wieder gelöscht.
Ist mit Sicherheit keine schöne Lösung, aber mir fällt da nichts besseres derzeit ein.
Ich muss da leider nochmal umdenken, sodass xlsx Dateien dabei raus kommen. Grund, es ist eine Formatierung gewünscht, was leider nicht mit csv funktioniert.
Nun überlege ich, die CSV-Dateien trotzdem zu generieren und diese dann formatiert als xlsx abzuspeichern. Im nachhinein werden dann die csv wieder gelöscht.
Ist mit Sicherheit keine schöne Lösung, aber mir fällt da nichts besseres derzeit ein.
Wenn es denn eine Exceldatei als Ausgabe sein soll, dann guck Dir das mal an. Das macht das Leben mit Exceldateien unter PS sehr viel einfacher.
https://www.powershellgallery.com/packages/ImportExcel/5.4.0
Liebe Grüße
Erik
Moin,
Klar geht das und es ist auch fast richtig. Guck mal hier:
https://www.windowspro.de/script/vergleichsoperatoren-powershell-eq-lt-g ...
Insbesondere der Abschnitt über -like.
Außerdem fehlt noch die Pipe zwischen dem Ende von where und dem export-csv.
Liebe Grüße
Erik
Zitat von @Pat.bat:
@erikro Noch eine Frage
In deinem Code-Beispiel, ist es dort auch möglich, eine Where-Abfrage einzubauen um zu sagen, welche Strings in Spalte ZE-Name er nur nehmen soll.
[...]
@erikro Noch eine Frage
In deinem Code-Beispiel, ist es dort auch möglich, eine Where-Abfrage einzubauen um zu sagen, welche Strings in Spalte ZE-Name er nur nehmen soll.
[...]
((Get-Content "$PfadText") -replace '^\s+','' ) -replace ' *\t *',';' | convertfrom-csv -Delimiter ";" | select * -excludeproperty $arrCols | where {$_."ZE-Name" -Like "ANKER"} `
> export-csv -path $CSV -delimiter ";" -Encoding utf8 -NoTypeInformation
Klar geht das und es ist auch fast richtig. Guck mal hier:
https://www.windowspro.de/script/vergleichsoperatoren-powershell-eq-lt-g ...
Insbesondere der Abschnitt über -like.
Außerdem fehlt noch die Pipe zwischen dem Ende von where und dem export-csv.
Liebe Grüße
Erik
Moin,
Dochdoch, -like ist schon richtig. Es fehlen bloß die Wildcards.
entfernt diese störenden Kommata am Ende des Strings. Guckst Du hier:
https://blog.stefanrehwald.de/2013/03/03/powershell-03-2-strings-bearbei ...
hth
Erik
Zitat von @Pat.bat:
-Like scheint dann das falsche zu sein, da ich auch ein Array übergeben möchte (Einrichtungsnamen werden in eine xml gespeichert. das Skript soll sich diese ziehen und in ein Array speichern).
-Like scheint dann das falsche zu sein, da ich auch ein Array übergeben möchte (Einrichtungsnamen werden in eine xml gespeichert. das Skript soll sich diese ziehen und in ein Array speichern).
Dochdoch, -like ist schon richtig. Es fehlen bloß die Wildcards.
where-object {$_.ZE-Name -like "*ANKER*"}
Ursache ist, das einige Einträge in der Spalte ZE-Name hinten aus mir unerklärlichen Gründen ein Komma haben. Man in der App, die die xml erstellt aber normalerweise nur den Namen eingibt, ohne Komma.
$_.ZE-Name.trimend(",")
entfernt diese störenden Kommata am Ende des Strings. Guckst Du hier:
https://blog.stefanrehwald.de/2013/03/03/powershell-03-2-strings-bearbei ...
hth
Erik
Moin,
Ja, nämlich dass das so nicht in Deinem Code stand.
Guck mal hier: https://stackoverflow.com/questions/13019218/powershell-like-against-an- ...
So, nun ist Feierabend.
Liebe Grüße
Erik
Ja, nämlich dass das so nicht in Deinem Code stand.
Guck mal hier: https://stackoverflow.com/questions/13019218/powershell-like-against-an- ...
So, nun ist Feierabend.
Liebe Grüße
Erik