VBScript: Einzelne Zeile in einer Datei ersetzen (restlicher Inhalt bleibt unangetastet)
Hallo zusammen,
ich versuche seit 3 Tagen für einen speziellen Anwendungsfall in unserem Unternehmen ein Script zu erstellen. Ich habe mit VBScript selbst keine Praxis, kann aber bestehende Scripte halbwegs verstehen und auch anpassen.
Die Aufgabenstellung ist folgende:
Für eine unserer Druckmaschinen müssen Dateien die Informationen zum Druckauftrag enthalten von Umlauten oder Sonderzeichen befreit werden. Sowohl im Dateinamen als auch in der Datei selbst und zwar genau in Zeile 6. Problem dabei ist nur, die Datei darf sich vom Inhalt und Formatierung selbst nicht verändern sondern es soll nur Zeile 6 bearbeitet werden.
Ich habe ein Script nun soweit erstellt was im Grunde auch das gewünschte Ergebnis bringt allerdings nicht fehlerfrei. Die Ursprungsdatei ist 18.623 KB groß und lt. Notepad++ umfasst diese 55.275 Zeilen. Die nach dem Script gespeicherte Datei ist allerdings 37.294 KB und 58.179 Zeilen groß. Kann zwar von der Maschine eingelesen werden, allerdings kommt nur eine schwarze Fläche raus und kein gewünschtes Druckbild.
So sieht der Inhalt der Datei aus:
Und das wäre mein aktuelles Script dafür (selbst zusammengebastelt aus div. Beispielen im Netz
Hat hier jemand Tipps und Ideen wie man das Script adaptieren kann oder viell. eine komplett andere Idee wie man dies bewerkstelligen kann ?
Das VBS kann ich dem "Workflow" der diese Datei erzeugt am Ende anhängen damit dies dann auch automatisiert abläuft - daher VBS. Also der Workflow erzeugt die Datei dann muss ich sie mit dem Script überarbeiten und danach wird sie an die Druckmaschine gesendet.
Danke !
lG
Roland
ich versuche seit 3 Tagen für einen speziellen Anwendungsfall in unserem Unternehmen ein Script zu erstellen. Ich habe mit VBScript selbst keine Praxis, kann aber bestehende Scripte halbwegs verstehen und auch anpassen.
Die Aufgabenstellung ist folgende:
Für eine unserer Druckmaschinen müssen Dateien die Informationen zum Druckauftrag enthalten von Umlauten oder Sonderzeichen befreit werden. Sowohl im Dateinamen als auch in der Datei selbst und zwar genau in Zeile 6. Problem dabei ist nur, die Datei darf sich vom Inhalt und Formatierung selbst nicht verändern sondern es soll nur Zeile 6 bearbeitet werden.
Ich habe ein Script nun soweit erstellt was im Grunde auch das gewünschte Ergebnis bringt allerdings nicht fehlerfrei. Die Ursprungsdatei ist 18.623 KB groß und lt. Notepad++ umfasst diese 55.275 Zeilen. Die nach dem Script gespeicherte Datei ist allerdings 37.294 KB und 58.179 Zeilen groß. Kann zwar von der Maschine eingelesen werden, allerdings kommt nur eine schwarze Fläche raus und kein gewünschtes Druckbild.
So sieht der Inhalt der Datei aus:
Und das wäre mein aktuelles Script dafür (selbst zusammengebastelt aus div. Beispielen im Netz
sOrdner = "C:\Test\"
'sOrdner = "E:\XShare\GenericPressRoot\M600D\"
' Funktion zum Ersetzen von Sonderzeichen und Umlaute
Function normalize_str(strRemove)
Dim arrWrapper(1)
Dim arrReplace(18)
Dim arrReplaceWith(18)
arrWrapper(0) = arrReplace
arrWrapper(1) = arrReplace
' Replace
arrWrapper(0)(0) = "Ä"
arrWrapper(0)(1) = "Ö"
arrWrapper(0)(2) = "Ü"
arrWrapper(0)(3) = "ß"
arrWrapper(0)(4) = "ä"
arrWrapper(0)(5) = "ö"
arrWrapper(0)(6) = "ü"
arrWrapper(0)(7) = "~"
arrWrapper(0)(8) = "’"
arrWrapper(0)(9) = "'"
arrWrapper(0)(10) = "/"
arrWrapper(0)(11) = "|"
arrWrapper(0)(12) = "&"
arrWrapper(0)(13) = "!"
arrWrapper(0)(14) = "?"
arrWrapper(0)(15) = "§"
arrWrapper(0)(16) = "$"
arrWrapper(0)(17) = "="
arrWrapper(0)(18) = "#"
' With
arrWrapper(1)(0) = "AE"
arrWrapper(1)(1) = "OE"
arrWrapper(1)(2) = "UE"
arrWrapper(1)(3) = "ss"
arrWrapper(1)(4) = "ae"
arrWrapper(1)(5) = "oe"
arrWrapper(1)(6) = "ue"
arrWrapper(1)(7) = "_"
arrWrapper(1)(8) = "_"
arrWrapper(1)(9) = "_"
arrWrapper(1)(10) = "_"
arrWrapper(1)(11) = "_"
arrWrapper(1)(12) = "_"
arrWrapper(1)(13) = "_"
arrWrapper(1)(14) = "_"
arrWrapper(1)(15) = "_"
arrWrapper(1)(16) = "_"
arrWrapper(1)(17) = "_"
arrWrapper(1)(18) = "_"
For N = 0 To 18
' 1: Start find from 1st character
' -1: Find until string does not End
' 0: binary comparision. Respect uppercase from lowercase.
strRemove = Replace(strRemove, arrWrapper(0)(N), arrWrapper(1)(N), 1, -1, 0)
Next
normalize_str = strRemove
End Function
Const ForReading = 1
Const ForWriting = 2
Const TristateUseDefault = -2
intMaxZeile = 6
Set fso = CreateObject("Scripting.FileSystemObject")
Set objRegEx = CreateObject("VBScript.RegExp")
' Wir suchen nach dem Wort CIP3AdmJobName
objRegEx.Pattern = "CIP3AdmJobName"
ProcessFolder fso.GetFolder(sOrdner)
Sub ProcessFolder(ThisFolder)
sPath = ThisFolder.Path
If InStr(sPath, "System Volume Information") = 0 Then
For Each File In ThisFolder.Files
sOld = File.Name
sNew = normalize_str(sOld)
' sOld ist der alte originale Dateiname
' sNew ist der Dateiname ohne Sonderzeichen oder Umlaute aus der Tabelle oben
If (sNew <> File.Name) then
File.Move (File.ParentFolder & "\" & sNew)
' wenn sNew unterschiedlich zum alten File.Name ist dann wird die Datei umbenannt
end if
Set objFile = fso.OpenTextFile(File.ParentFolder & "\" & sNew, ForReading, False, TriStateUseDefault)
' wir oeffnen die oben umbenannte Datei um daraus zu lesen
count = 0
' Treffer standardmaessig auf null
Do Until objFile.AtEndOfStream
' lauf die Schleife bis zum Ende des Datei-Stream
If count = 1 Then
Exit Do
' wenn die Schleife einen Treffer hat dann stoppt sie - da es sonst bei 60000 Zeilen zu lange dauert
End If
strSearchString = Mid(objFile.ReadLine,2)
' wir beschneiden den gefunden String um das erste Zeichen / damit es nicht von der Funktion in ein _ verwandelt wird
Set colMatches = objRegEx.Execute(strSearchString)
' wir ermitteln die Ergebnisse indem wir jede Zeile mit dem Suchmuster abgleichen
If colMatches.Count > 0 Then
' gibt es mehr als null Treffe dann mache
For Each strMatch in colMatches
' fuer jeden gefundenen Eintrag
sOldJob = "/" & strSearchString
' speicher den Inhalt der originalen Zeile CIP3AdmJobName in die Variable sOldJob und geben wieder in / an den Anfang
sJobNew = normalize_str(strSearchString)
' schicke das ermittelte Ergebnis durch unseren Konverter um Umlaute und Sonderzeichen umzuwandeln
sJobNew = "/" & sJobNew
' wir speichern den umgewandelten Wert in eine Variable sJobNew und geben wieder ein / an den Anfang
Wscript.Echo sJobNew
count = count + 1
' Zaehler wird hochgesetzt bei jedem Treffer (sollte nur einen geben)
Next
End If
Loop
objFile.Close
WScript.Echo sOldJob
intZeile = 1
Set objFile = fso.OpenTextFile(File.ParentFolder & "\" & sNew, ForReading, False, TriStateUseDefault)
Set objDateiSchreiben = fso.CreateTextFile(File.ParentFolder & "\_N_" & sNew, True, True)
Do Until objFile.AtEndOfStream 'So lange lesen bis zum Schluss
strZeile = objFile.ReadLine
If intZeile <= intMaxZeile And InStr(strZeile, sOldJob) Then 'Falls das Wort suchwort in den erst intMaxZeilen Zeilen vorkommt, dann ersetze diese Zeile
objDateiSchreiben.WriteLine sJobNew
Else 'sonst Schreibe einfach die Zeile
objDateiSchreiben.WriteLine strZeile
End If
intZeile = intZeile + 1
Loop
objFile.Close
objDateiSchreiben.Close
Next
End If
End Sub
Hat hier jemand Tipps und Ideen wie man das Script adaptieren kann oder viell. eine komplett andere Idee wie man dies bewerkstelligen kann ?
Das VBS kann ich dem "Workflow" der diese Datei erzeugt am Ende anhängen damit dies dann auch automatisiert abläuft - daher VBS. Also der Workflow erzeugt die Datei dann muss ich sie mit dem Script überarbeiten und danach wird sie an die Druckmaschine gesendet.
Danke !
lG
Roland
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 516601
Url: https://administrator.de/forum/vbscript-einzelne-zeile-in-einer-datei-ersetzen-restlicher-inhalt-bleibt-unangetastet-516601.html
Ausgedruckt am: 25.12.2024 um 07:12 Uhr
36 Kommentare
Neuester Kommentar
Hi,
wenn ich das richtig sehe, dann ist das keine reine Text-Datei, sondern enthält auch Binär-Code. Also darfst Du diese auch nur binär bearbeiten. Also nicht Zeichen ersetzen, sondern Bytes.
Bsp. wie man mit Binärdateien arbeitet: https://www.motobit.com/tips/detpg_read-write-binary-files/
Byte für Byte einlesen und in eine neue Datei schreiben. Dabei ggf. betreffede Bytes ersetzen.
E.
wenn ich das richtig sehe, dann ist das keine reine Text-Datei, sondern enthält auch Binär-Code. Also darfst Du diese auch nur binär bearbeiten. Also nicht Zeichen ersetzen, sondern Bytes.
Bsp. wie man mit Binärdateien arbeitet: https://www.motobit.com/tips/detpg_read-write-binary-files/
Byte für Byte einlesen und in eine neue Datei schreiben. Dabei ggf. betreffede Bytes ersetzen.
E.
In VBA gibt es OPEN file FOR BINARY as #1 um Binar-Dateien zu öffnen. Aber VBA ist recht alt und die Unterstützung von utf-8 ist schlecht. Ist es möglich eine Datei hochzuladen? (http://www.office-loesung.de/p/viewforum.php?f=166). Mit VBS habe ich keine Erfahrung, aber meistens kann VBA in VBS umgeschrieben werden. Käme auch Powershell in betracht?
Noch eine kulturelle Frage: Wäre ein 5-Zeiler akzeptabel oder müssen es unbedingt 50 Zeilen sein?
Noch eine kulturelle Frage: Wäre ein 5-Zeiler akzeptabel oder müssen es unbedingt 50 Zeilen sein?
sorry, ich lade keine Dateien aus der drop-box.
Hier ein Ansatz mit Powershell:
Hier ein Ansatz mit Powershell:
$fin = 'C:\Users\xxx\Desktop\test.txt'
$fout = 'C:\Users\xxx\Desktop\test1.txt'
$Tx = get-content $fin
$DD = New-Object system.collections.hashtable
$DD.add('ä', 'ae')
$DD.add('ö', 'oe')
$DD.add('ü', 'ue')
$DD.add('ß', 'ss')
$DD.add('Ä', 'Ae')
$DD.add('Ö', 'Oe')
$DD.add('Ü', 'Ue')
foreach ($k in $DD.Keys) {
$Tx = $tx.replace($k, $DD[$k])}
Set-Content $fout -Value $Tx
Bis Du sicher, dass Get-Content so einfach mit Binär-Daten klar kommt? Ich denke, da fehlt zum Einen "-Encoding Byte" und zum Anderen dürfte das bei größeren Dateien recht langsam sein. Da wäre es besser, direkt über .NET zu gehen.
Einen Code "blind" zu schreiben ist immer ein Risiko:
$fin = 'C:\Users\xxxx\Desktop\test.txt' # <<<< anpassen >>>>
$fout = 'C:\Users\xxxx\Desktop\test1.txt' # <<<< anpassen >>>>
$TT = 100 # Anzahl der Zeichen in ersten 10 Zeilen
$Ta = get-content $fin -Raw # <<<<<<<<<<<<<< Raw auch binary >>>>>>>>
$Tx = $Ta.Substring(0, $TT)
$DD = New-Object system.collections.hashtable
$DD.add('ä', 'ae')
$DD.add('ö', 'oe')
$DD.add('ü', 'ue')
$DD.add('ß', 'ss')
$DD.add('Ä', 'Ae')
$DD.add('Ö', 'Oe')
$DD.add('Ü', 'Ue')
foreach ($k in $DD.Keys) {$Tx = $Tx.replace($k, $DD[$k])}
$Tx = $Tx -replace "['~´\/|&!\?§$=#]", '_'
Write-Host "--------------------- `n "
$Tx
$Tx = $Tx + $Ta.Substring($TT+1)
Set-Content $fout -Value $Tx
Get-ChildItem 'E:\GizmoTronix' -Filter *.ppf -File | %{
[regex]::Replace((Get-Content $_.FullName -Raw),'(?im)(?<=/CIP3AdmJobName\s*\()([^\)]+)(?=.*)',{
param($m)
return [regex]::Replace($m.Value,'(?i)^com[1-9]|^lpt[1-9]|^con|^nul|^prn|[\\/:?<>|"*äöüß]',{param($m2) switch -CaseSensitive ($m2){'ä'{'ae'};'ü'{'ue'};'ö'{'oe'};'ß'{'ss'};'Ä'{'Ae'};'Ü'{'Ue'};'Ö'{'Oe'};default{'_'}}})
}) | Set-Content $_.FullName -Force
}
Zitat von @GizmotroniX:
OK dann fällt wohl Powershell generell raus weil ich hab hier ein Windows 10 1809 und wenn das "veraltet" ist dann ist das auf dem Server 2012 wo es tatsächlich laufen soll wohl noch problematischer.
Nö wende es richtig dann klappt das auch . Läuft hier auch auf einem 2012R2 ohne Probleme. Ich habe ja deine Originaldatei verwendet, also läuft bei deiner Anwendung was falsch ...OK dann fällt wohl Powershell generell raus weil ich hab hier ein Windows 10 1809 und wenn das "veraltet" ist dann ist das auf dem Server 2012 wo es tatsächlich laufen soll wohl noch problematischer.
Wieso ihr das nicht im Quellprozess gleich ausmerzt versteht wohl nur ihr.
Setz mal das Encoding bei Get-Content passend dann sollte es auch bei dir laufen...
Alternativ kann man es nat. auch direkt auf Bitebene modifizieren (aufwendiger).
Get-ChildItem 'E:\GizmoTronix' -Filter *.ppf -File | %{
[regex]::Replace((Get-Content $_.FullName -Raw -Encoding Default),'(?im)(?<=/CIP3AdmJobName\s*\()([^\)]+)(?=.*)',{
param($m)
return [regex]::Replace($m.Value,'(?i)^com[1-9]|^lpt[1-9]|^con|^nul|^prn|[\\/:?<>|"*äöüß]',{param($m2) switch -CaseSensitive ($m2){'ä'{'ae'};'ü'{'ue'};'ö'{'oe'};'ß'{'ss'};'Ä'{'Ae'};'Ü'{'Ue'};'Ö'{'Oe'};default{'_'}}})
}) | Set-Content $_.FullName -Force
}
Dann pass das Encoding mal an (UTF8, Unicode usw.), geht hier wie gesagt einwandfrei auf allen Kisten, ansonsten hast du uns nicht das von dir verwendete File zur Verfügung gestellt. Wenn du darin natürlich schon vorher rumpfuschst und erneut anspeicherst führt das ganze hier zu nichts.
Ich bin raus, läuft.
Case solved.
Ich bin raus, läuft.
Case solved.
Damit du siehst das ich hier keine Märchen erzähle, Videobeweis mit Originaldatei (SHA1 Hash: 935b2ba0c9e09ee0e7a98cb5087be826bc3f8e8f):
https://we.tl/t-M7H9oxafOg
Datei hat ein völlig normales Encoding für den Umlaut (ü = 0xFC) auch im Hexeditor geprüft
File Compare nach Skriptdurchlauf, links Original, rechts nach Skriptanwendung.
https://we.tl/t-M7H9oxafOg
Datei hat ein völlig normales Encoding für den Umlaut (ü = 0xFC) auch im Hexeditor geprüft
File Compare nach Skriptdurchlauf, links Original, rechts nach Skriptanwendung.
Oh, good old VBScript.
Problem ist, dass alles was irgendwie als Zeilenumbruch verstanden wird, für ReadLine als Abbruchkriterium herangezogen wird. WriteLine macht dann daraus einen Windows Zeilenumbruch bestehend aus den 2 Zeichen Carriage Return und Line Feed. Aber selbst die Plaintextzeilen am Anfang sind nur durch ein einfaches Line Feed Zeichen abgeschlossen.
Ich hab mal deine normalize_str Funktion übernommen, wobei man die auch etwas vereinfachen könnte. Ist aber egal für die 2 Strings die du drüber jagst. Rest ist mehr oder weniger neu. ADO Streams sind hier der Schlüssel, um Binärdaten in einem VBScript zu verarbeiten.
Steffen
Problem ist, dass alles was irgendwie als Zeilenumbruch verstanden wird, für ReadLine als Abbruchkriterium herangezogen wird. WriteLine macht dann daraus einen Windows Zeilenumbruch bestehend aus den 2 Zeichen Carriage Return und Line Feed. Aber selbst die Plaintextzeilen am Anfang sind nur durch ein einfaches Line Feed Zeichen abgeschlossen.
Ich hab mal deine normalize_str Funktion übernommen, wobei man die auch etwas vereinfachen könnte. Ist aber egal für die 2 Strings die du drüber jagst. Rest ist mehr oder weniger neu. ADO Streams sind hier der Schlüssel, um Binärdaten in einem VBScript zu verarbeiten.
Steffen
Option Explicit
Const sFolder = "C:\Test\"
Const sFileExt = "ppf"
Function normalize_str(strRemove)
Dim arrWrapper(2)
Dim arrReplace(19)
Dim arrReplaceWith(19)
Dim N
arrWrapper(0) = arrReplace
arrWrapper(1) = arrReplaceWith
' Replace
arrWrapper(0)(0) = "Ä"
arrWrapper(0)(1) = "Ö"
arrWrapper(0)(2) = "Ü"
arrWrapper(0)(3) = "ß"
arrWrapper(0)(4) = "ä"
arrWrapper(0)(5) = "ö"
arrWrapper(0)(6) = "ü"
arrWrapper(0)(7) = "~"
arrWrapper(0)(8) = "’"
arrWrapper(0)(9) = "'"
arrWrapper(0)(10) = "/"
arrWrapper(0)(11) = "|"
arrWrapper(0)(12) = "&"
arrWrapper(0)(13) = "!"
arrWrapper(0)(14) = "?"
arrWrapper(0)(15) = "§"
arrWrapper(0)(16) = "$"
arrWrapper(0)(17) = "="
arrWrapper(0)(18) = "#"
' With
arrWrapper(1)(0) = "AE"
arrWrapper(1)(1) = "OE"
arrWrapper(1)(2) = "UE"
arrWrapper(1)(3) = "ss"
arrWrapper(1)(4) = "ae"
arrWrapper(1)(5) = "oe"
arrWrapper(1)(6) = "ue"
arrWrapper(1)(7) = "_"
arrWrapper(1)(8) = "_"
arrWrapper(1)(9) = "_"
arrWrapper(1)(10) = "_"
arrWrapper(1)(11) = "_"
arrWrapper(1)(12) = "_"
arrWrapper(1)(13) = "_"
arrWrapper(1)(14) = "_"
arrWrapper(1)(15) = "_"
arrWrapper(1)(16) = "_"
arrWrapper(1)(17) = "_"
arrWrapper(1)(18) = "_"
For N = 0 To 18
' 1: Start find from 1st character
' -1: Find until string does not End
' 0: binary comparision. Respect uppercase from lowercase.
strRemove = Replace(strRemove, arrWrapper(0)(N), arrWrapper(1)(N), 1, -1, 0)
Next
normalize_str = strRemove
End Function
Dim objFSO, objFolder, objFile, sFile, sLine
Dim objADOStreamIn1, objADOStreamIn2, objADOStreamOut, objFileStream
Dim newLine, byteCount, lineCount
Const adTypeText = 2
Const adTypeBinary = 1
Const adSaveCreateOverWrite = 2
Const ForReading = 1
Const ForWriting = 2
Const TristateUseDefault = -2
Const sObj = "/CIP3AdmJobName"
Const iMaxLines = 6
newLine = vbLf
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder(sFolder)
For Each objFile In objFolder.Files
sFile = objFile.Name
' Wenn Dateiendung passt
If StrComp(objFSO.GetExtensionName(sFile), sFileExt, vbTextCompare) = 0 Then
' Sonderzeichen ersetzen und umbenennen
sFile = normalize_str(sFile)
objFile.Move(objFile.ParentFolder & "\" & sFile)
Set objADOStreamIn1 = CreateObject("ADODB.Stream") ' original Dateiinhalt
objADOStreamIn1.Type = adTypeBinary
objADOStreamIn1.Open
Set objADOStreamIn2 = CreateObject("ADODB.Stream") ' geänderter Text
objADOStreamIn2.Type = adTypeText
objADOStreamIn2.Charset = "us-ascii"
objADOStreamIn2.Open
Set objADOStreamOut = CreateObject("ADODB.Stream") ' Ausgabe
objADOStreamOut.Type = adTypeBinary
objADOStreamOut.Open
' Komplette Datei binär einlesen
objADOStreamIn1.LoadFromFile objFile.Path
' Dateistream öffnen
Set objFileStream = objFile.OpenAsTextStream(ForReading, TriStateUseDefault)
byteCount = 0
lineCount = 0
Do Until objFileStream.AtEndOfStream
' raus wenn mehr als 6 Zeilen gelesen wurden aber die Objektkennung nicht gefunden wurde
If lineCount > iMaxLines Then Exit Do
sLine = objFileStream.ReadLine
' gelesene Bytes
byteCount = byteCount + Len(sLine) + Len(newLine)
' gelesene Zeilen
lineCount = lineCount + 1
' wenn Objektkennung gefunden wurde
If InStr(1, sLine, sObj, vbBinaryCompare) = 1 Then
' Sonderzeichen entfernen und in den Stream schreiben
sLine = normalize_str(sLine)
objADOStreamIn2.WriteText "/" & Mid(sLine, 2)
objADOStreamIn2.WriteText newLine
' Raus hier
Exit Do
End If
' sonst Zeile in den Stream schreiben
objADOStreamIn2.WriteText sLine
objADOStreamIn2.WriteText newLine
Loop
objFileStream.Close
' Position in den Originaldaten ändern (Anzahl zu überspringende Zeichen)
objADOStreamIn1.Position = byteCount
' Textstream zu Binärstream ändern
objADOStreamIn2.Position = 0
objADOStreamIn2.Type = adTypeBinary
' Ausgabestream aus geändertem Text und restlichen Binärdaten aufbauen
objADOStreamOut.Write objADOStreamIn2.Read
objADOStreamOut.Write objADOStreamIn1.Read
' Datei überschreiben
objADOStreamOut.SaveToFile objFile.Path, adSaveCreateOverWrite
objADOStreamOut.Close
objADOStreamIn2.Close
objADOStreamIn1.Close
End If
Next
Kann ich nicht nachvollziehen, genauso wenig wie @141965 in seiner PS Lösung. Sollte deine Testdatei nicht dem entsprechen was du in die Dropbox geladen hast, werde ich nicht helfen können. Ich habe mir die Detailfragen, wie Zeichencodierung und verwendeter Zeilenumbruch, mit dem HEX Editor aus dieser Datei selbst beantwortet. Sollte die Realität anders aussehen, geht's in die Hose. Lade dir doch die Datei mal selbst aus der Dropbox und schau dir an ob/wo die Unterschiede liegen. Könnte sein dass dort etwas nicht mehr dem Original entspricht, weil du die Datei nicht in ein ZIP Archiv gepackt hast bevor du sie hochgeladen hast.
Der Effekt den du gerade siehst, hat wahrscheinlich damit zu tun, dass deine Ersetzungsfunktion in deinem Test gar nicht bei Umlauten wirksam wird. Ggf. weil die Zeichencodierung bei dir UTF-8 oder eine völlig andere ist. Dann kommt nur die Charset Eigenschaft des ADO Streams zum tragen, die hier vermutlich aus Umlauten die ASCII Zeichen macht, die denen am nächsten kommen.
Also, nein, ohne reale Datei, die den Fehler reproduzieren kann, ist das nur im Trüben fischen. Keine Ahnung wie ich dir da helfen könnte. Sorry.
Steffen
PS: Ach ja, sollte die Datei OK sein, du aber dein Script nicht ANSI (Windows-1252) codiert haben, sondern ggf. UTF-8, geht es natürlich auch in die Hose.
Der Effekt den du gerade siehst, hat wahrscheinlich damit zu tun, dass deine Ersetzungsfunktion in deinem Test gar nicht bei Umlauten wirksam wird. Ggf. weil die Zeichencodierung bei dir UTF-8 oder eine völlig andere ist. Dann kommt nur die Charset Eigenschaft des ADO Streams zum tragen, die hier vermutlich aus Umlauten die ASCII Zeichen macht, die denen am nächsten kommen.
Also, nein, ohne reale Datei, die den Fehler reproduzieren kann, ist das nur im Trüben fischen. Keine Ahnung wie ich dir da helfen könnte. Sorry.
Steffen
PS: Ach ja, sollte die Datei OK sein, du aber dein Script nicht ANSI (Windows-1252) codiert haben, sondern ggf. UTF-8, geht es natürlich auch in die Hose.
Zitat von @GizmotroniX:
Somit wäre das Ding mit den Umlauten durch, muss ich nur noch schaffen das die Datei entsprechend ohne Umlaute im Namen gespeichert wird.
Das wäre dann sicher der komplizierteste Teil ... Somit wäre das Ding mit den Umlauten durch, muss ich nur noch schaffen das die Datei entsprechend ohne Umlaute im Namen gespeichert wird.
Zitat von @GizmotroniX:
muss ich nur noch schaffen das die Datei entsprechend ohne Umlaute im Namen gespeichert wird.
Der Teil mit dem Umbenennen der Datei ist aber nach wie vor im Script und hat bei mir funktioniert.muss ich nur noch schaffen das die Datei entsprechend ohne Umlaute im Namen gespeichert wird.
Steffen
Nach allem was ich gesehen habe, könntest du Glück haben. Anders als bei PDF, sehe ich bei deinem Postscript basierten Format keine Offsets zu den Objekten. Die einzige angegebene Größe ist die des CIP3PreviewImage Objekts (also die der Binärdaten). Dort ändert sich aber nichts.
Steffen
Na super Wie du gesehen hast, habe ich anhand deiner Datei den Zeilenumbruch als Line Feed Zeichen angenommen und hart im Code stehen. Sollte das bei anderen Dateien mal zu Problemen führen, kannst du ein Stück in die Datei hinein lesen und prüfen was du vorfindest.
Nur so als Ergänzung. Keine Ahnung ob das jemals der Fall sein könnte.
Steffen
Option Explicit
Const sFolder = "C:\Test\"
Const sFileExt = "ppf"
Function GetNewLine(ByRef objFile)
Dim objFileStream, sChar, sCharBefore
GetNewLine = ""
Set objFileStream = objFile.OpenAsTextStream()
If objFileStream Is Nothing Then Exit Function
sCharBefore = ""
Do While Not objFileStream.AtEndOfStream
sChar = objFileStream.Read(1)
If sChar = vbLf Then
If sCharBefore = vbCr Then GetNewLine = vbCrLf Else GetNewLine = vbLf
Exit Do
End If
sCharBefore = sChar
Loop
objFileStream.Close
End Function
Function normalize_str(strRemove)
Dim arrWrapper(2)
Dim arrReplace(19)
Dim arrReplaceWith(19)
Dim N
arrWrapper(0) = arrReplace
arrWrapper(1) = arrReplaceWith
' Replace
arrWrapper(0)(0) = "Ä"
arrWrapper(0)(1) = "Ö"
arrWrapper(0)(2) = "Ü"
arrWrapper(0)(3) = "ß"
arrWrapper(0)(4) = "ä"
arrWrapper(0)(5) = "ö"
arrWrapper(0)(6) = "ü"
arrWrapper(0)(7) = "~"
arrWrapper(0)(8) = "’"
arrWrapper(0)(9) = "'"
arrWrapper(0)(10) = "/"
arrWrapper(0)(11) = "|"
arrWrapper(0)(12) = "&"
arrWrapper(0)(13) = "!"
arrWrapper(0)(14) = "?"
arrWrapper(0)(15) = "§"
arrWrapper(0)(16) = "$"
arrWrapper(0)(17) = "="
arrWrapper(0)(18) = "#"
' With
arrWrapper(1)(0) = "AE"
arrWrapper(1)(1) = "OE"
arrWrapper(1)(2) = "UE"
arrWrapper(1)(3) = "ss"
arrWrapper(1)(4) = "ae"
arrWrapper(1)(5) = "oe"
arrWrapper(1)(6) = "ue"
arrWrapper(1)(7) = "_"
arrWrapper(1)(8) = "_"
arrWrapper(1)(9) = "_"
arrWrapper(1)(10) = "_"
arrWrapper(1)(11) = "_"
arrWrapper(1)(12) = "_"
arrWrapper(1)(13) = "_"
arrWrapper(1)(14) = "_"
arrWrapper(1)(15) = "_"
arrWrapper(1)(16) = "_"
arrWrapper(1)(17) = "_"
arrWrapper(1)(18) = "_"
For N = 0 To 18
' 1: Start find from 1st character
' -1: Find until string does not End
' 0: binary comparision. Respect uppercase from lowercase.
strRemove = Replace(strRemove, arrWrapper(0)(N), arrWrapper(1)(N), 1, -1, 0)
Next
normalize_str = strRemove
End Function
Dim objFSO, objFolder, objFile, sFile, sLine
Dim objADOStreamIn1, objADOStreamIn2, objADOStreamOut, objFileStream
Dim newLine, byteCount, lineCount
Const adTypeText = 2
Const adTypeBinary = 1
Const adSaveCreateOverWrite = 2
Const sObj = "/CIP3AdmJobName"
Const iMaxLines = 6
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder(sFolder)
For Each objFile In objFolder.Files
sFile = objFile.Name
' Wenn Dateiendung passt
If StrComp(objFSO.GetExtensionName(sFile), sFileExt, vbTextCompare) = 0 Then
' ermitteln, welcher Zeilenumbruch verwendet wurde
newLine = GetNewLine(objFile)
If newLine <> "" Then
' Sonderzeichen ersetzen und umbenennen
sFile = normalize_str(sFile)
objFile.Move(objFile.ParentFolder & "\" & sFile)
Set objADOStreamIn1 = CreateObject("ADODB.Stream") ' original Dateiinhalt
objADOStreamIn1.Type = adTypeBinary
objADOStreamIn1.Open
Set objADOStreamIn2 = CreateObject("ADODB.Stream") ' geänderter Text
objADOStreamIn2.Type = adTypeText
objADOStreamIn2.Charset = "us-ascii"
objADOStreamIn2.Open
Set objADOStreamOut = CreateObject("ADODB.Stream") ' Ausgabe
objADOStreamOut.Type = adTypeBinary
objADOStreamOut.Open
' Komplette Datei binär einlesen
objADOStreamIn1.LoadFromFile objFile.Path
' Dateistream öffnen
Set objFileStream = objFile.OpenAsTextStream()
byteCount = 0
lineCount = 0
Do Until objFileStream.AtEndOfStream
' raus wenn mehr als 6 Zeilen gelesen wurden aber die Objektkennung nicht gefunden wurde
If lineCount > iMaxLines Then Exit Do
sLine = objFileStream.ReadLine
' gelesene Bytes
byteCount = byteCount + Len(sLine) + Len(newLine)
' gelesene Zeilen
lineCount = lineCount + 1
' wenn Objektkennung gefunden wurde
If InStr(1, sLine, sObj, vbBinaryCompare) = 1 Then
' Sonderzeichen entfernen und in den Stream schreiben
sLine = normalize_str(sLine)
objADOStreamIn2.WriteText "/" & Mid(sLine, 2)
objADOStreamIn2.WriteText newLine
' Raus hier
Exit Do
End If
' sonst Zeile in den Stream schreiben
objADOStreamIn2.WriteText sLine
objADOStreamIn2.WriteText newLine
Loop
objFileStream.Close
' Position in den Originaldaten ändern (Anzahl zu überspringende Zeichen)
objADOStreamIn1.Position = byteCount
' Textstream zu Binärstream ändern
objADOStreamIn2.Position = 0
objADOStreamIn2.Type = adTypeBinary
' Ausgabestream aus geändertem Text und restlichen Binärdaten aufbauen
objADOStreamOut.Write objADOStreamIn2.Read
objADOStreamOut.Write objADOStreamIn1.Read
' Datei überschreiben
objADOStreamOut.SaveToFile objFile.Path, adSaveCreateOverWrite
objADOStreamOut.Close
objADOStreamIn2.Close
objADOStreamIn1.Close
End If
End If
Next
Steffen