Powershell und Excel - Tabelle aufteilen

Moin!

Kennt sich hier jemand mit Powershell und (idealerweise in Verbindung mit) der Verarbeitung von Excel-Dateien aus?

Ich habe eine 7-spaltige Tabelle, die ich gern nach eindeutigen Wert-Kombinationen in Spalte C & D in jeweils eine Excel-Datei aufteilen will.

Bsp:

A B C D E F G
1 Bli Bla #1 $1 Blub xyz uvw
2 Bli Bla #1 $2 Blub xyz uvw
3 Bli Bla #2 $1 Blub xyz uvw
4 Bli Bla #2 $2 Blub xyz uvw
5 Blo Blu #2 $2 Blub xyz uvw

Nach der Aufteilung wären das also vier Dateien, benannt nach den Werten in C &D:

#1_$1.xlsx:

A B C D E F G
1 Bli Bla #1 $1 Blub xyz uvw

#1_$2xlsx

A B C D E F G
1 Bli Bla #1 $2 Blub xyz uvw

#2_$1.xlsx

A B C D E F G
1 Bli Bla #2 $1 Blub xyz uvw

#2_$2.xlsx

A B C D E F G
1 Bli Bla #2 $2 Blub xyz uvw
2 Blo Blu #2 $2 Blub xyz uvw

Mit Hilfe von diversen ähnlichen Use-Case-Scripten im Netz (die aber immer nur nach den Werten in einer Spalte aufteilen, nicht zwei) hab ich mir bisher Folgendes zusammengeschustert:

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName Microsoft.Office.Interop.Excel 
$xlFixedFormat = [Microsoft.Office.Interop.Excel.XlFileFormat]::xlWorkbookDefault

Write-Host "Starting ..."

Write-Host "Choose Excel File"

# Show a file dialog to select the input Excel file
$openFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$openFileDialog.Filter = "Excel Files (*.xlsx)|*.xlsx"

if ($openFileDialog.ShowDialog() -eq "OK") {
    $excelFile = $openFileDialog.FileName
	 
} else {
    Write-Host "No File Selected. Done."
    Exit
}

# Create the output subfolder if it doesn't exist
$outputFolder = Join-Path (Split-Path $excelFile) "output" 

Write-Host "Create Output Folder: " $outputFolder

# If subfolder doesn't exist, create it
if (-not (Test-Path $outputFolder)) {
  New-Item -ItemType Directory -Path $outputFolder | Out-Null
}

Write-Host "Load Excel File"

# Load the Excel file
$excel = New-Object -ComObject Excel.Application
$workbook = $excel.Workbooks.Open($excelFile)
$worksheet = $workbook.Worksheets.Item(1)

# Get unique value combinations in columns 3 and 4
$uniqueValues = $worksheet.Range("C1:D" + $worksheet.UsedRange.Rows.Count) | 
                Select-Object -Unique | 
                ForEach-Object { "$($_.Item(1))_$($_.Item(2))" }


Write-Host "Working ..."

# Loop through unique value combinations and create output files
foreach ($value in $uniqueValues) {
    # Filter table based on unique value combination
    $filteredTable = $worksheet.Range("A1:G" + $worksheet.UsedRange.Rows.Count) | 
                     Select-Object -Skip 1 | 
                     Where-Object { "$($_.Item(3))_$($_.Item(4))" -eq $value }

    # Create new workbook and worksheet for output
    $newWorkbook = $excel.Workbooks.Add()
    $newWorksheet = $newWorkbook.Worksheets.Item(1)

    # Copy filtered table to output worksheet
    $filteredTable | ForEach-Object { $newWorksheet.Cells.Item($_.Row, $_.Column).Value2 = $_.Value2 }
	 

Write-Host "Saving File"

    # Save output file and close workbook
    $outputFilePath = Join-Path $outputFolder "$value.xlsx"
	 
Write-Host "Create File: " $outputFilePath

    $newWorkbook.SaveAs($outputFilePath)
    $newWorkbook.Close()
}


Write-Host "Close"

# Close input file and quit Excel
$workbook.Close()
$excel.Quit()


Write-Host "Done"

Allerdings funktioniert das nicht, weil ich bei der Verarbeitung oder Ausgabe irgendeinen Fehler mache. Der Dateiname ist immer nur „System.__ComObject_System.__ComObject.xlsx“

Mit der $value-Variable scheint also etwas nicht so zu funktionieren, wie ich das gerne hätte.

Ich hab leider null Ahnung von Powershell und keine Ahnung, wo ich da ansetzen soll. :beansad:

1 „Gefällt mir“

Musst beim $targetfilename den Pfad vor den Variablen entsprechend angeben wo du es hinspeichern möchtest.

# Pfad zur Quelldatei angeben
$sourceFilePath = "C:\Temp\test.xlsx"

# Excel-Objekt erstellen und Quelldatei öffnen
$excel = New-Object -ComObject Excel.Application
$workbook = $excel.Workbooks.Open($sourceFilePath)

# Für jede Zeile in der Quelldatei die Werte in Spalte 3 und 4 lesen
for ($i = 2; $i -le $workbook.ActiveSheet.UsedRange.Rows.Count; $i++) {
    $value1 = $workbook.ActiveSheet.Cells.Item($i, 3).Value2
    $value2 = $workbook.ActiveSheet.Cells.Item($i, 4).Value2

    # Überprüfen, ob es bereits eine Excel-Datei für diese Werte gibt
    $targetFileName = "C:\Temp\$value1-$value2.xlsx"
    if (-not (Test-Path $targetFileName)) {
        # Wenn es keine Datei gibt, eine neue erstellen und Ãœberschriften schreiben
        $targetWorkbook = $excel.Workbooks.Add()
        $targetSheet = $targetWorkbook.Sheets.Item(1)
        $targetSheet.Cells.Item(1, 1).Value2 = "Spalte 1"
        $targetSheet.Cells.Item(1, 2).Value2 = "Spalte 2"
        $targetSheet.Cells.Item(1, 3).Value2 = "Spalte 3"
        $targetSheet.Cells.Item(1, 4).Value2 = "Spalte 4"
        $targetSheet.Cells.Item(1, 5).Value2 = "Spalte 5"
        $targetSheet.Cells.Item(1, 6).Value2 = "Spalte 6"
        $targetSheet.Cells.Item(1, 7).Value2 = "Spalte 7"
    }
    else {
        # Wenn es bereits eine Datei gibt, diese öffnen
        $targetWorkbook = $excel.Workbooks.Open($targetFileName)
        $targetSheet = $targetWorkbook.Sheets.Item(1)
    }

    # Werte aus der Quelldatei in die Ziel-Excel-Datei schreiben
    $row = $targetSheet.UsedRange.Rows.Count + 1
    $targetSheet.Cells.Item($row, 1).Value2 = $workbook.ActiveSheet.Cells.Item($i, 1).Value2
    $targetSheet.Cells.Item($row, 2).Value2 = $workbook.ActiveSheet.Cells.Item($i, 2).Value2
    $targetSheet.Cells.Item($row, 3).Value2 = $value1
    $targetSheet.Cells.Item($row, 4).Value2 = $value2
    $targetSheet.Cells.Item($row, 5).Value2 = $workbook.ActiveSheet.Cells.Item($i, 5).Value2
    $targetSheet.Cells.Item($row, 6).Value2 = $workbook.ActiveSheet.Cells.Item($i, 6).Value2
    $targetSheet.Cells.Item($row, 7).Value2 = $workbook.ActiveSheet.Cells.Item($i, 7).Value2

    # Ziel-Excel-Datei speichern und schließen
    $targetWorkbook.SaveAs($targetFileName)
    $targetWorkbook.Close()
}

# Quelldatei und Excel-Objekt schließen
$workbook.Close()
$excel.Quit()

Habs getestet und funktioniert. Credits gehen an chatGPT. Für solche, von der Logik her, einfachen Skriptsachen ist das einfach super.

1 „Gefällt mir“

Ja, damit spiele ich dabei auch mit rum. ^^

Ich find das einfach mega gut. Ich kenn mich z.B. halbwegs aus in Powershell und so, aber ich wüsste jetzt z.B. nicht wie man Zellen in einem Excel-Objekt adressiert und hätte auch keine Lust erst zig KBs durchzulesen :smiley:
Und man muss im Grunde nur die „Bedingungen“ mitgeben. Das war meine Anfrage:

Kannst du mir bei einem Powershell skript helfen?
[…]
Quelle ist eine Excel-Datei mit 7 Spalten.
Anhand der Spalte 3 und 4 soll jede Zeile in einer separaten Excel-Datei gespeichert werden.
Hat eine Zeile den selben Wert in Spalte 3 und 4 stehen wie eine andere Zeile, werden diese Zeilen in der selben Excel-Datei gespeichert.
[…]

1 „Gefällt mir“