c0r32quad
Goto Top

Zusammenfügen von csv mit max 150 Zeilen oder aus 4 Dateien

Moin zusammen,

ich bräuchte mal einen gedankenanstoß:

Ich verarbeite jede Woche ca 80-100 .csv Dateien, welche an eine Maschine zum Abarbeiten geschickt werden.
Diese Dateien haben mal 1 Zeile, mal 20 oder mal 100. Immer unterschiedlich.
Diese Dateien lasse ich durch ein Batch Skript Datei für Datei abarbeiten (in ein Programm importieren, verarbeiten und zur Maschine senden) Es muss leider Batch sein, da das Programm welches es aufruft nur Batch unterstützt.

Jetzt sollen diese Daten zusammengefasst werden.

Die Dateien sehen so aus (anonymisiert)

Text 1 mit Leerzeichen;Text 2 mit Leerzeichen;1234;123;1;;0;Text 3 mit Leerzeichen;Text 4 mit Leerzeichen;;;1;1234;123;;;000:000::;;Text 5 mit Leerzeichen;Text 6 mit Leerzeichen;5;Text 7 mit Leerzeichen;Text 8 mit Leerzeichen;Text 9 mit Leerzeichen;Text 10 mit Leerzeichen;Text 11 mit Leerzeichen;Text 12 mit Leerzeichen;;;;;123456789;;1,123456789,Text 13 mit Leerzeichen;TEXT;TEXT;TEXT;TEXT;Text 14 mit Leerzeichen;;Text 15 mit Leerzeichen;Text 16 mit Leerzeichen;;;;;;;;;;;;;;;;;;;;;;;;;;;X;X;;;Text 16 mit Leerzeichen

Aus den Original Dateien sollen Dateien entstehen die Max 150 Zeilen haben. Es sollen aber nie mehr als 4 Dateien zusammengefasst werden. Hat also Datei 1 + 2 + 3 insgesamt 140 Zeilen und die 4 Datei 11 Zeilen, dann sollen nur 3 Dateinen zusammengefasst werden.
Die Reihenfolge der Dateien kann aus einer .txt entnommen werden, diese lasse ich im vorherigem skript schreiben:

dir "%IMPORT_PATH%\*.csv" /b /o:d > Importinhalt.txt  

Aus dieser Datei sollten dann die erste 4 Dateinamen zusammengefasst werden.

Wie bekommt man sowas am Besten hin?

Content-Key: 6179179984

Url: https://administrator.de/contentid/6179179984

Printed on: May 17, 2024 at 06:05 o'clock

Member: Doskias
Doskias Mar 02, 2023 updated at 07:27:22 (UTC)
Goto Top
Moin,

ich bräuchte mal einen gedankenanstoß:
mein Denkanstoß. Mach es via PowerShell via import-csv und export-csv.

Zitat von @c0r32quad:
Es muss leider Batch sein, da das Programm welches es aufruft nur Batch unterstützt.
Schreib in die Batch-Datei:
powershell.exe -command "[Pfad]\[Dateiname].ps1"  
Die Batch-Datei startet dann eine PowerShell-Instanz und dir stehen alle Möglichkeiten offen.

Gruß
Doskias
Member: c0r32quad
c0r32quad Mar 02, 2023 at 08:44:21 (UTC)
Goto Top
Moin,

das ich doch schon mal eine super Idee.
Leider sind keine Powershell kenntnisse vorhanden, ich kann mir aber viel anlesen und ausprobieren.
Wie würde so etwas in etwa aussehen?

Mfg
Mitglied: 6017814589
6017814589 Mar 02, 2023 updated at 10:12:36 (UTC)
Goto Top
Plain Batch würde auch gehen, obwohl ich auch für Powershell plädieren würde ....
Hier mal plain Batch
@echo off &setlocal enabledelayedexpansion
set "quelle=D:\quelle"  
set "ziel=D:\ziel"  
set max=150
set maxfilecnt=4
:: ============
set sum=0
set filenum=1
set filecnt=0
for /f "delims=" %%a in ('dir /b /a-d /od "%quelle%"') do (  
	for /f "delims=:" %%b in ('findstr /rn "^" "%quelle%\%%a"') do set linecnt=%%b  
	set /a "calc=!sum!+!linecnt!"  
	if !calc! GEQ %max% (
		set /a filenum+=1
		set sum=!linecnt!
		set filecnt=0
	) else (
		if !filecnt! GEQ %maxfilecnt% (
			set /a filenum+=1
			set sum=!linecnt!
			set filecnt=0
		) else (
			set /a sum+=!linecnt!
			set /a filecnt+=1
		)
	)
	>>"%ziel%\file_!filenum!.txt" type "%quelle%\%%a"  
)

Mit Powershell etwa so
$quelle = "D:\quelle"  
$ziel = "D:\ziel"  
$max = 150
$maxfilecnt = 4
# -----------------
$sum = 0
$filenum = 0
$filecnt = 0
foreach($file in Get-ChildItem -LiteralPath $quelle -File | sort LastWriteTime){
    $txt = [io.file]::ReadAllLines($file.Fullname)
    if (($sum+$txt.Count) -gt $max -or $filecnt -ge $maxfilecnt){
        $filenum++
        $filecnt = 0
        $sum = $txt.Count
    }else{
        $sum += $txt.Count
        $filecnt++
    }
    Add-Content -Path "$ziel\file_$filenum$($file.Extension)" -Value $txt  
}
h.
Member: Doskias
Doskias Mar 02, 2023 at 09:17:39 (UTC)
Goto Top
Zitat von @c0r32quad:
Leider sind keine Powershell kenntnisse vorhanden, ich kann mir aber viel anlesen und ausprobieren.
Das ist gut

Wie würde so etwas in etwa aussehen?
Was erwartest du jetzt? Den kompletten Code. Den gibt es bei mir nur selten. Macht das Lernen kaputt.

Einige Tipps zum Anfang gibt es aber:
import-csv mit -delimiter ';'
export-csv mit -NoTypeInformation -append
.count gibt dir die Anzahl der Elemente an.

Einige kurze Beispiele
$variable=import-csv [Pfad zur CSV] -delimiter ';'   
Dieser Code setzt in $variable den Inhalt deiner CSV-Datei inkl. Überschrift, gentrennt nach ;

$variable+=import-csv [Pfad zur CSV] -delimiter ';'   
Erweitert deine Variable um den Inhalt der CSV. Es wird angefügt

$variable.count
Sagt dir wie viele Elemente enthalten sind

$varibale | export-csv [Pfad zur CSV] -delimiter ';' -NoTypeInformation -append  
Fügt den Inhalt der Varibale deiner CSV-Datei an. lass -append weg und du erstellst eine neue CSV-Datei

Das ganze baust du in eine Schleife pro CSV-Datei und versiehst das ganze mit einer IF-Abfrage, mit der du prüfst, dass die Datei nicht größer als 150 Zeilen wird.

Gruß
Doskias
Member: c0r32quad
c0r32quad Mar 04, 2023 at 22:14:18 (UTC)
Goto Top
Moin zusammen,

euch beiden erstmal vielen Dank.


Zitat von @Doskias:

Zitat von @c0r32quad:
Wie würde so etwas in etwa aussehen?
Was erwartest du jetzt? Den kompletten Code. Den gibt es bei mir nur selten. Macht das Lernen kaputt.

Nein auf keinen Fall, das macht mir auch keinen Spaß face-smile
Ich glaube auch das die Leute die sowas können, keine Langeweile haben und sofort einfach mal so, den Code posten.
Falls doch, hilft es mir natührlich auch sehr.

@6017814589:

Ich habe die Batch Version ausprobiert und das klappe auch fast problemlos, nur ist das unglaublich langsam.
Dann habe ich den Rat von @Doskias befolgt und den Powershell commad in den Batch eingebaut und siehe da, gefühlt 10x so schnell.

Nur so am rande,ich musste den Code wie folgt anpassen:

$filenum = 0
sonst hat nur die erste Datei immer 4 und danach dann alle 5.

Beim einfügen des Powershell command in cmd gab es dann noch Benutzergruppenrichtlinien die mich behindert haben.
Wie folgt gelöst:
cmd /c powershell.exe -executionpolicy bypass -file "%~dp0\meineDatei.ps1"  

Soweit klappt das.
Woran ich jetzt verzweifle ist das ich den Ziel Dateinamen aus den Quell Dateien zusammenstelle (Nur aus den jeweils ersten 9, sonst wird es zu lang).
Geht das überhaupt in der foreach Schleife? Oder muss ich vorher die Namen in eine Datei (oder Variable) schreiben und wieder Zeilenweise auslesen?

Ich hab's mal so versucht,
aber das haut nicht hin:

foreach($file in Get-ChildItem -LiteralPath $quelle -File | sort LastWriteTime){
    $txt = [io.file]::ReadAllLines($file.Fullname)
	$filename = $file.Name.Substring(0,9)
    if (($sum+$txt.Count) -gt $max -or $filecnt -ge $maxfilecnt){
        $filenum++
        $filecnt = 0
        $sum = $txt.Count
		$filenamemerged += $filename
    }else{
        $sum += $txt.Count
        $filecnt++
    }
    Add-Content -Path "$ziel\$filenum$_$trennzeichen$_$filenamemerged$($file.Extension)" -Value $txt  
    Write-Host $file.basename
    Write-Host ...
}
Mitglied: 6017814589
6017814589 Mar 05, 2023 updated at 06:41:01 (UTC)
Goto Top
Add-Content -Path "$ziel\$($file.Basename[0..8] -join '')_$filenum$($file.Extension)" -Value $txt  
Ich habe die Batch Version ausprobiert und das klappe auch fast problemlos, nur ist das unglaublich langsam.
Klar, ist eben Batch, da muss man mit vielen Unzulänglichkeiten leben weil man oft auf Workarounds angewiesen ist die dann eben sehr ineffizient laufen (schon für die Zeilenanzahl muss man sich sehr ineffizient einen abwürgen) , deswegen auch die Empfehlung endlich umzusteigen.