bruno8500
Goto Top

Wort aus String "herrausschneiden", FileOpenDialog

Ich bin gerade dabei ein CMD Skript zu schreiben für folgende Anwendung:
Wenn man bei DHL eine Online Frankierung kauft und als PDF runterlädt, ist in der PDF Datei nicht nur die Frankierung an sich enthalten, sondern auch noch der Beleg mit den Sendungsinformationen.
Den Beleg möchte ich aber extra ausdrucken da ich die Frankierung auf selbstklebendes Papier ausdrucke.
Die PDF Datei ist so aufgebaut das in der oberen Hälfte die Frankierung ist und in der unteren der Beleg.

Also müsste ich die PDF Datei in der Hälfte "schneiden". Da das aber nicht so einfach geht konvertiere ich die PDF Datei zu einem PNG Bild mit xpdf
xpdf-tools\pdftopng.exe -r 600 input.pdf output
und schneide es dann mit GraphicsMagick zurecht
GraphicsMagick\gm.exe convert temp\output.png -crop 4958x3508 cropped.png
Falls zwei dieser Frankierungen vorhanden sind, füge ich sie ebenfalls mit GraphicsMagick zusammen
GraphicsMagick\gm.exe convert cropped.png cropped2.png -append combined.png

Der Benutzer soll dann nur noch seine Online Frankierungen auswählen und die werden dann automatisch zugeschnitten und in die entsprechenden Ordner gespeichert (Belege in den Belege Ordner, Frankierungen in den Frankierungen Ordner).

Bisher funktioniert das mit den Pfad auswählen zu den PDF Dateien nur per Drag and Drop aber das möchte ich noch umändern sodass man nur noch mit einem Dialog mit den Explorer die Dateien auswählen kann.

Jetzt hab ich noch das Problem mit der Namensgebung.
Die PDF Dateien die man runterlädt sind im Folgenden Format gespeichert:
"DHL_label_YYYY-MM-DD_HH_MM_SS.png"
(DHL_label_Jahr-Monat-Tag_Stunde_Minute_Sekunde.png)
Beispiel:
DHL_label_2019-12-8_21_40_6.pdf

Diese Uhrzeit möchte ich übernehmen, also das "DHL_label" und ".pdf" vorne und hinten raus schneiden
und dann als entsprechenden "Beleg_2019-12-8_21_40_6.png" und "Frankierung_2019-12-8_21_40_6.png" seperat abspeichern.

Leider blick ich dass mit den "for /f" noch nicht durch, mit den wäre das machbar.

Dann wäre da noch das auswählen der Dateien mit den Explorer, da habe ich folgenden Code gefunden:
powershell -Executionpolicy ByPass -Command "[void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms');$dlg = New-Object System.Windows.Forms.OpenFileDialog; if($dlg.ShowDialog() -eq 'OK'){return $dlg.FileNames}"  
Quelle: (Batch) Open File or Folder Dialog
Den Code möchte ich so umändern das der Benutzer nur PDF Dateien auswählen kann (maximal 2 wenn möglich) und dass dann der Pfad als Variable ausgegeben wird sodass ich diese später nutzen kann.

Schönen Abend,
Bruno

Content-Key: 525633

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

Printed on: April 26, 2024 at 18:04 o'clock

Member: SeaStorm
SeaStorm Dec 14, 2019 at 21:24:02 (UTC)
Goto Top
Hi

vergiss Batch bitte und verwende gleich Powershell.
Und da kannst du dann deinen String mit Regex zerlegen wie du lustig bist, z.B

$string = "DHL_label_2019-12-8_21_40_6.pdf"  

$string = $string -replace "DHL_label_(.*)\.pdf",'$1'  

Write-Host Datum: $string
Member: rubberman
Solution rubberman Dec 15, 2019 at 13:14:30 (UTC)
Goto Top
nur PDF Dateien auswählen
Filter Property setzen.
https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.filedia ...
(maximal 2 wenn möglich)
Nicht möglich. Wenn das Multiselect Property auf true gesetzt ist, gibt es keine Beschränkung. Das musst du im Nachgang prüfen.
@echo off &setlocal DisableDelayedExpansion

:loop
set /a "n=0"  
for /f "tokens=1* delims=:" %%i in (  
  'powershell -Executionpolicy ByPass -Command "[void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms');$dlg = New-Object System.Windows.Forms.OpenFileDialog -Property @{CheckFileExists=$true; Filter='Portable Document Format (*.pdf)|*.pdf'; Multiselect=$true}; if($dlg.ShowDialog() -eq 'OK') {$dlg.FileNames}"^|findstr /neic:".pdf"'  
) do (set /a "n=%%i"&set "filename[%%i]=%%j")  
if %n% gtr 2 goto loop

setlocal EnableDelayedExpansion
for /l %%i in (1 1 %n%) do for /f "delims=" %%j in ("!filename[%%i]!") do for /f "tokens=2* delims=_" %%k in ("%%~nj") do (  
  echo %%l - "!filename[%%i]!"  
)

pause
Aus dem ersten Teilcode fliegt ein assoziatives Array (filename[1] .. filename[n]) und die Anzahl der ausgewählten Dateien (n).
Im zweiten Teilcode werden die Dateinamen verarbeitet. Der Unterstrich wird als Trennzeichen angenommen. Anhand deines Beispiels bin ich davon ausgegangen dass immer 2 Unterstriche im Dateiname vorkommen, bevor das Datum folgt.

Den ganzen Kram mit deinen 3rd Party Tools musst du selbst dazu basteln. Kenne ich nicht.

Steffen
Member: TK1987
Solution TK1987 Dec 15, 2019 updated at 15:16:08 (UTC)
Goto Top
Zitat von @Bruno8500:
Diese Uhrzeit möchte ich übernehmen, also das "DHL_label" und ".pdf" vorne und hinten raus schneiden
und dann als entsprechenden "Beleg_2019-12-8_21_40_6.png" und "Frankierung_2019-12-8_21_40_6.png" seperat abspeichern.

Leider blick ich dass mit den "for /f" noch nicht durch, mit den wäre das machbar.
Ist eigentlich ganz einfach:
  • mit Delims bestimmst du das Trennzeichen, dass die Zeichenkette splittet.
  • mit Tokens bestimmst du, welche Teile der Zeichenkette in welche Variable geschrieben werden.

Beispiel für deinen Fall:
@echo off

for /f "Tokens=2,* Delims=_" %%A in ("DHL_label_2019-12-8_21_40_6.pdf") do (  
	echo %%B
	)

pause

Die Zeichenkette wird durch Unterstriche getrennt. Der zweite Teil, also "label" wird in %%A geschrieben, alles was dahinter kommt, also "2019-12-8_21_40_6.pdf" wird in die Variable mit dem nächsten Buchstaben geschrieben, also %%B

Dann wäre da noch das auswählen der Dateien mit den Explorer, da habe ich folgenden Code gefunden:
powershell -Executionpolicy [...]
Wenn du das wirklich über einen File-Dialog lösen willst, also den Powershell-Befehl nutzen möchtest, kann ich @SeaStorm nur beipflichten, dann solltest du lieber gleich Powershell benutzen.

Es gäbe allerdings eine andere Möglichkeit, über den Dateiexplorer Dateien auszuwählen und mit einer Batch zu verarbeiteten, nämlich über SendTo.

Geh in deinen Windows Explorer, drücke Strg+L und tippe dort shell:sendto ein. Du landest im Verzeichnist %APPDATA%\Roaming\Microsoft\Windows\SendTo. Wenn du ein Batchscript (oder eine Verknüpfung zum solchen) in diesen Ordner legst, kannst du später einfach im Explorer mehrere Dateien auswählen und mit Rechtsklick>Senden an> das Batchscript auswählen und die Dateien werden als Argument an das Script übergeben.

Das gestartete Script selbst ist immer über die Variable %0 erreichbar, das 1. übergebene Argument über die Variable %1, das 2. über %2, ...
Zudem kann man alle Argumente über %* erreichen.

Als Beispiel:
@echo off
setlocal EnableDelayedExpansion

for %%A in (%*) do (
	for /f "Tokens=2,* Delims=_" %%B in ("%%~nA") do (  
		set Pfad=%%~dpA
		set Dateiname=Beleg_%%C.png
		echo !Pfad!!Dateiname!
		)
	)

pause 
Zuerst wird eine For-Schleife erstellt, die die übergebenen Argumente enthällt (also deine PDF-Dateien, die du an das Script gesendet hast). Diese werden in die Variable %%A geschrieben.
Dann wird eine zweite For-Schleife erstellt, die nur den Dateinamen ohne Erweiterung enthält, also "DHL_label_2019-12-8_21_40_6". Diese wird, wie oben schon beschrieben gesplittet. Anschließend wird eine Variable für den Dateipfad und eine für den nach deinen wünschen geänderten Dateinamen erstellt. Dieser wird dann ausgegeben.

Wenn du dieses Script also in den SendTo-Ordner legst und anschließend mal mehrere PDF-Dateien auswählst und an das Script sendest, dürfte es dir für jede dieser PDF-Dateien den Pfad mit dem neuen Dateinamen anzeigen.

maximal 2 wenn möglich
Geht damit auch ganz einfach, indem du nur das 1. und das 2. übergebene Argument verarbeitest.
for %%A in (%1 %2) do (
Member: Bruno8500
Bruno8500 Dec 15, 2019 at 17:25:19 (UTC)
Goto Top
Kann ich den Output
echo %%l - "!filename[%%i]!"  
als 2 seperate Variablen für Batch "umwandeln"?
Da die 3rd Party Tools mit Batch laufen brauche ich den Dateipfad und Dateinamen als separate Variablen
Member: rubberman
Solution rubberman Dec 15, 2019 updated at 18:02:53 (UTC)
Goto Top
Ich weiß nicht ganz auf was du hinaus willst. %%l ist eine separate Variable und !filename[%%i]! auch. Ich gehe davon aus dass du deine Tools innerhalb der Schleife aufrufst (also da wo jetzt die zitierte ECHO Ausgabe steht). Somit weiß ich nicht was du noch mehr brauchen solltest, als das was du schon hast face-confused
Ersetze die Zeile doch mal durch ...
  echo "!filename[%%i]!"  
  echo "%%~dpiBeleg_%%l.png"  
  echo "%%~dpiFrankierung_%%l.png"  
  echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
... vielleicht wird es dann klarer.

Steffen
Member: Bruno8500
Bruno8500 Dec 15, 2019 at 18:15:48 (UTC)
Goto Top
Wenn ich zwei PDF Dateien auswähle, sind beide Pfade und Namen in jeweils einer Variable hinterlegt.
Heißt wenn ich die Variable für mein 3rd Party Tool nutze funktioniert das nicht weil ja in der einen Variable zwei Pfade hinterlegt sind
Member: rubberman
Solution rubberman Dec 15, 2019 at 18:19:26 (UTC)
Goto Top
Sorry, ich versteh's nicht. Gib doch mal ein reales Beispiel für deine Kommandozeile für eine Datei und ein Beispiel für 2 Dateien.

Steffen
Member: Bruno8500
Bruno8500 Dec 15, 2019 at 18:31:09 (UTC)
Goto Top
Wenn ich die Variable mit einer ausgewählten Datei nutze, klappt das, das Programm konvertiert die ausgewählte PDF Datei in ein PNG um:
 xpdf-tools\pdftopng.exe "!filename[%%i]!" output.png  

Wenn ich aber zwei PDF Dateien auswähle, wird nur die erste konvertiert und die zweite ignoriert
Member: rubberman
Solution rubberman Dec 15, 2019 at 19:35:33 (UTC)
Goto Top
Ich kann dir immer noch nicht folgen. Du musst alles was für eine Datei zu erledigen ist, in den Schleifenrumpf packen (also incl. der gm.exe Aufrufe). Sonst kann das nicht funktionieren, da deine Ausgabedatei output.png bei jeder Schleifeniteration überschrieben wird. Ich kann aber nicht auf deinen Bildschirm sehen, darum habe ich nach wie vor keine Ahnung wie du den ganze Kram nun verwurstet hast und wo der Fehler liegt ...

Steffen
Member: Bruno8500
Bruno8500 Dec 16, 2019 at 19:12:20 (UTC)
Goto Top
Das ist das Problem: Ich hätte gerne die Pfade ohne Schleife, für jeden Pfad jeweils eine Variable damit ich die Pfade später dann benutzen kann um die PDF Dateien - nachdem sie zu einem PNG konvertiert worden sind - zusammenzufügen.


Dieser Code gilt für den Fall dass der User 2 PDF Dateien ausgewählt hat:
set pfad1=<<Ausgabe des ersten Pfades (Beispiel: "C:\DHL_label_2019-12-8_21_40_6.pdf">>  
set pfad2=<<Ausgabe des zweiten Pfades (Beispiel: "C:\DHL_label_2019-12-9_17_56_55.pdf")>>  
set name1=<<Name aus der ersten Datei (Beispiel: "2019-12-8_21_40_6")>>  
set name 2=<<Name aus der zweiten Datei (Beispiel: "2019-12-9_17_56_55")>>  

xpdf-tools\pdftopng.exe "%pfad1%" "temp\Output_%name1%.png"   
xpdf-tools\pdftopng.exe "%pfad2%" "temp\Output_%name2%.png"  

(xpdf wandelt die PDF in PNG Dateien um (speichert sie in einen temporären Ordner ("temp"):  
 "temp\Output_2019-12-8_21_40_6.png"  
 "temp\Output_2019-12-9_17_56_55.png")  


Da ich nur die obere Hälfte der PDF Datei benötige, schneide ich den unteren Teil mit GraphicsMagick weg und speichere das dann als neue Datei:
GraphicsMagick\gm.exe convert "temp\Output_%name1%.png" -crop 4958x3508 "temp\Cropped_%name1%.png"  
GraphicsMagick\gm.exe convert "temp\Output_%name2%.png" -crop 4958x3508 "temp\Cropped_%name2%.png"  

(GraphicsMagick schneidet die obere Hälfte aus und speichert sie als neue Datei (in den temporären Ordner ("temp"):  
"temp\Cropped_2019-12-8_21_40_6.png"  
"temp\Cropped_2019-12-9_17_56_55.png")  


Das wäre bis jetzt noch in der Schleife möglich gewesen, aber jetzt möchte ich die zwei geschnittenen Bilder zu einem Bild zusammenfügen:
GraphicsMagick\gm.exe convert "temp\Cropped_%name1%.png" "temp\Cropped_%name2%.png" -append "Label1_%name1% und Label2_%name2%.png"  

(Fügt die zwei zuvor geschnittenen Bilder zusammen:
"Label1_2019-12-9_17_56_55 und Label2_2019-12-9_17_56_55.png")  



Ich hoffe man versteht was ich meine.
Dein Code funktioniert bis jetzt richtig gut, ich brauche nur den Output als 2 seperate Variablen damit ich diesen wie beschrieben nutzen kann.
Member: rubberman
Solution rubberman Dec 16, 2019 at 19:29:32 (UTC)
Goto Top
Darum frage ich doch schon die ganze Zeit was bei 2 Dateien anders ist.
@echo off &setlocal DisableDelayedExpansion

:loop
set /a "n=0"  
for /f "tokens=1* delims=:" %%i in (  
  'powershell -Executionpolicy ByPass -Command "[void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms');$dlg = New-Object System.Windows.Forms.OpenFileDialog -Property @{CheckFileExists=$true; Filter='Portable Document Format (*.pdf)|*.pdf'; Multiselect=$true}; if($dlg.ShowDialog() -eq 'OK') {$dlg.FileNames}"^|findstr /neic:".pdf"'  
) do (
  set /a "n=%%i"&set "filename[%%i]=%%j"  
  for /f "tokens=2* delims=_" %%k in ("%%~nj") do set "datetime[%%i]=%%l"  
)
if %n% gtr 2 goto loop

if %n%==1 (
  echo eine Datei:
  echo "%filename[1]%" "%datetime[1]%"  
) else if %n%==2 (
  echo zwei Dateien:
  echo "%filename[1]%" "%datetime[1]%"  
  echo "%filename[2]%" "%datetime[2]%"  
)
:: Nun könnte %n% noch 0 sein, dann passiert halt nix.

pause
Damit sollte es aber nun machbar sein...

Steffen
Member: Bruno8500
Bruno8500 Dec 16, 2019 at 19:37:59 (UTC)
Goto Top
Ah jetzt hab ich die Schleife gecheckt.
Sorry ich wusst nicht wie ich auf den "Counter" zugreifen kann