Per BAT CSV bestimmte Spalten und Zeilen auslesen und übertragen
Hallo Community,
bei der Suche nach einer Antwort für mein Problem bin ich
auf dieses Forum gestoßen und hoffe hier Hilfe zu finden.
Leider glaube ich, um mein Problem zu erläutern. sehr weit ausholen
zu müssen also könnte diese Frage etwas länger formuliert sein.
Ich betreibe, nebenberuflich, einen kleinen Onlinehandel
auf bekannten großen Plattformen.
Ich muss momentan aus kostengründen auf die verwendung
von Warenwirtschaftssoftware etc. verzichten.
Daher lade ich mir gegen nachmittag von den Portalen
jeweils eine CSV Datei herunter in der unter anderem
die Adressen der Käufer zu finden sind. Aber eben auch ein paar
mehr Informationen die ich hier nicht weiter benötige.
Diese Adressen muss ich wiederum allerdings in einer anderen Anordnung in
eine weitere CSV kopieren um dann einen Onlinefrankierungsservice
mit dieser füttern zu können.
Das Endergebniss sind frankierte Etiketten mit Adressen mit denen ich
dann weiter arbeiten kann.
Klingt kompliziert. Ist es im täglich Ablauf aber eigentlich nicht.
Ich hoffe dass ich nicht der einzige bin der verstanden hat was ich
geschrieben habe..
Ich verkaufe Waren im Niedrigpreisegment.
Die Verkaufszahlen steigen allmählich an und ich
muss so langsam zu sehen dass ich den Arbeitsaufwand
möglichst minimal halte..
Ich denke dass überall wo Arbeitsabläufe am PC immer
sehr ähnlich verlaufen kommt eine Automatisierung in Frage.
Jetzt die konkrete Frage:
Ist es möglich einer BAT Datei zu sagen:
- Lese SPALTE 1,3,5 und 6 Ab Zeile 2 aus Datei EB.csv
- Schreibe Spalte 1 aus EB.csv in Spalte 2 DPAG.csv beachte dabei in die erste freie Zeile zu schreiben (sprich: bestehende Zeilen bestehen lassen)
- Schreibe Spalte 3 aus EB.csv in Spalte 4 DPAG.csv beachte dabei in die erste freie Zeile zu schreiben (sprich: bestehende Zeilen bestehen lassen)
..usw.
DANN
- Lese SPALTE 1,3,5 und 6 Ab Zeile 2 aus Datei AM.csv
- Schreibe Spalte 6 aus AM.csv in Spalte 2 DPAG.csv beachte dabei in die erste freie Zeile zu schreiben (sprich: bestehende Zeilen bestehen lassen)
- Schreibe Spalte 8 aus AM.csv in Spalte 4 DPAG.csv beachte dabei in die erste freie Zeile zu schreiben (sprich: bestehende Zeilen bestehen lassen)
..usw.
In den Spalten befinden sich je nach Auftragslage natürlich immer mal mehr und mal weniger Zeilen.
Schön wäre wenn es der BAT völlig egal ist ib es 3 oder 50 Zeilen pro Spalte sind die er lesen muss.
Ich muss gestehen sogar beim Verfassen der Frage Probleme zu haben verständlich zu erklären
wie die Abläufe sind.
Ich bin aber für jeden Tipp dankbar und experimentierfreudig.
Ich hoffe das man verstehen konnte was ich meine.
Wenn es überhaupt nicht umsetzbar sein sollte oder
ein zu komplexes Unterfangen wäre, würde ich mich auch hier
über feedback freuen.
Ich bin jetzt schon dankbar
mfg
Knut
bei der Suche nach einer Antwort für mein Problem bin ich
auf dieses Forum gestoßen und hoffe hier Hilfe zu finden.
Leider glaube ich, um mein Problem zu erläutern. sehr weit ausholen
zu müssen also könnte diese Frage etwas länger formuliert sein.
Ich betreibe, nebenberuflich, einen kleinen Onlinehandel
auf bekannten großen Plattformen.
Ich muss momentan aus kostengründen auf die verwendung
von Warenwirtschaftssoftware etc. verzichten.
Daher lade ich mir gegen nachmittag von den Portalen
jeweils eine CSV Datei herunter in der unter anderem
die Adressen der Käufer zu finden sind. Aber eben auch ein paar
mehr Informationen die ich hier nicht weiter benötige.
Diese Adressen muss ich wiederum allerdings in einer anderen Anordnung in
eine weitere CSV kopieren um dann einen Onlinefrankierungsservice
mit dieser füttern zu können.
Das Endergebniss sind frankierte Etiketten mit Adressen mit denen ich
dann weiter arbeiten kann.
Klingt kompliziert. Ist es im täglich Ablauf aber eigentlich nicht.
Ich hoffe dass ich nicht der einzige bin der verstanden hat was ich
geschrieben habe..
Ich verkaufe Waren im Niedrigpreisegment.
Die Verkaufszahlen steigen allmählich an und ich
muss so langsam zu sehen dass ich den Arbeitsaufwand
möglichst minimal halte..
Ich denke dass überall wo Arbeitsabläufe am PC immer
sehr ähnlich verlaufen kommt eine Automatisierung in Frage.
Jetzt die konkrete Frage:
Ist es möglich einer BAT Datei zu sagen:
- Lese SPALTE 1,3,5 und 6 Ab Zeile 2 aus Datei EB.csv
- Schreibe Spalte 1 aus EB.csv in Spalte 2 DPAG.csv beachte dabei in die erste freie Zeile zu schreiben (sprich: bestehende Zeilen bestehen lassen)
- Schreibe Spalte 3 aus EB.csv in Spalte 4 DPAG.csv beachte dabei in die erste freie Zeile zu schreiben (sprich: bestehende Zeilen bestehen lassen)
..usw.
DANN
- Lese SPALTE 1,3,5 und 6 Ab Zeile 2 aus Datei AM.csv
- Schreibe Spalte 6 aus AM.csv in Spalte 2 DPAG.csv beachte dabei in die erste freie Zeile zu schreiben (sprich: bestehende Zeilen bestehen lassen)
- Schreibe Spalte 8 aus AM.csv in Spalte 4 DPAG.csv beachte dabei in die erste freie Zeile zu schreiben (sprich: bestehende Zeilen bestehen lassen)
..usw.
In den Spalten befinden sich je nach Auftragslage natürlich immer mal mehr und mal weniger Zeilen.
Schön wäre wenn es der BAT völlig egal ist ib es 3 oder 50 Zeilen pro Spalte sind die er lesen muss.
Ich muss gestehen sogar beim Verfassen der Frage Probleme zu haben verständlich zu erklären
wie die Abläufe sind.
Ich bin aber für jeden Tipp dankbar und experimentierfreudig.
Ich hoffe das man verstehen konnte was ich meine.
Wenn es überhaupt nicht umsetzbar sein sollte oder
ein zu komplexes Unterfangen wäre, würde ich mich auch hier
über feedback freuen.
Ich bin jetzt schon dankbar
mfg
Knut
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 228480
Url: https://administrator.de/contentid/228480
Ausgedruckt am: 23.11.2024 um 19:11 Uhr
30 Kommentare
Neuester Kommentar
Hallo knotenknut und willkommen im Forum!
Dein Vorhaben wäre leichter nachvollziehbar, wenn Du die Beschreibung durch Beispiel-Daten (natürlich gerne anonymisiert) ergänzt - dann wüssten wir etwa auch, welche Trennzeichen in den Dateien verwendet werden, ob tatsächlich jeweils 2 Zeilen in der DPAG.csv entstehen sollen und ob/wozu die Spalten 5 und 6 der Dateien EB.csv und AM.csv benötigt werden.
Poste daher bitte jeweils etwa 5 (möglichst charakteristische - Stichwort Sonderzeichen oder leere Spalten) Datensätze (unter Verwendung der "Code"-Formatierung) der einzelnen Dateien ...
Grüße
bastla
P.S.: Hättest Du Einwände gegen die Verwendung von zB VBScript?
Dein Vorhaben wäre leichter nachvollziehbar, wenn Du die Beschreibung durch Beispiel-Daten (natürlich gerne anonymisiert) ergänzt - dann wüssten wir etwa auch, welche Trennzeichen in den Dateien verwendet werden, ob tatsächlich jeweils 2 Zeilen in der DPAG.csv entstehen sollen und ob/wozu die Spalten 5 und 6 der Dateien EB.csv und AM.csv benötigt werden.
Poste daher bitte jeweils etwa 5 (möglichst charakteristische - Stichwort Sonderzeichen oder leere Spalten) Datensätze (unter Verwendung der "Code"-Formatierung) der einzelnen Dateien ...
Grüße
bastla
P.S.: Hättest Du Einwände gegen die Verwendung von zB VBScript?
Hallo Knut,
Batchscript hat Probleme beim Verarbeiten des Inhalts von Dateien, wenn darin bestimmte Sonderzeichen enthalten sind (z.B. &<>). Deshalb hier ein Vorschlag von mir in VBScript:
Die Zeilen 13 bis 16 bilden zusammen die Initialisierung des Arrays arrMappings1, entsprechend sind die Zeilen 25 bis 28 für das Array arrMappings2 zuständig. Syntaktisch handelt es sich bei jedem der genannten Blöcke um eine einzige Zeile. VBScript lässt die Aufteilung eines Befehls auf mehrere Zeilen zu, wenn man die einzelnen Zeilen mit dem Zeichen
In Zeile 14 werden die Nummern der Quellspalten für die erste Eingabedatei angegeben, in Zeile 15 die Nummern der Zielspalten. Die Reihenfolge der Spaltennummern muss miteinander korrespondieren. Im Beispiel wird also Spalte 6 der Quelldatei auf Spalte 8 der Zieldatei gemappt.
Wichtig ist dabei, das die zweite Zeile der Array-Initialisierung (also Zeile 15 bzw. Zeile 27) immer aufsteigend sortiert ist. Somit würde bei der zweiten Eingabedatei Spalte 8 in Spalte 4 der Ausgabedatei geschrieben.
Gruß
Friemler
Batchscript hat Probleme beim Verarbeiten des Inhalts von Dateien, wenn darin bestimmte Sonderzeichen enthalten sind (z.B. &<>). Deshalb hier ein Vorschlag von mir in VBScript:
Das Script
Const ForReading = 1
Const ForWriting = 2
'********** Konfiguration ****************
'Eingabedatei #1
strInFile1 = "EB.csv"
'Spalten-Trennzeichen
strInDelimiter1 = ";"
'Startzeile
intStartLine1 = 2
'Spalten-Mappings
arrMappings1 = Array(_
Array(1,3,5,6),_
Array(2,4,6,8)_
)
'Eingabedatei #2
strInFile2 = "AM.csv"
'Spalten-Trennzeichen
strInDelimiter2 = ";"
'Startzeile
intStartLine2 = 2
'Spalten-Mappings
arrMappings2 = Array(_
Array(6,8,5,7),_
Array(2,4,6,8)_
)
'Ausgabedatei
strOutFile = "DPAG.csv"
'Spalten-Trennzeichen
strOutDelimiter = ";"
'Gesamtzahl der Spalten
intOutCols = 10
'*****************************************
Set objFSO = CreateObject("Scripting.FileSystemObject")
'Ausgabedatei öffnen
Set objOutStream = objFSO.OpenTextFile(strOutFile, ForWriting, true)
'Erste Eingabedatei verarbeiten
Call ProcessFile(objOutStream, strOutDelimiter, intOutCols,_
strInFile1, strInDelimiter1, intStartLine1,_
arrMappings1)
'Zweite Eingabedatei verarbeiten
Call ProcessFile(objOutStream, strOutDelimiter, intOutCols,_
strInFile2, strInDelimiter2, intStartLine2,_
arrMappings2)
'Ausgabedatei schließen
objOutStream.Close
Sub ProcessFile(objOutStream, strOutDelim, intOutCols,_
strInFile, strInDelim, intStartLine,_
arrMappings)
Dim intCnt, intMapCnt, intColCnt, arrLine, strOutLine, intSrcCol, intDstCol
Dim objInStream
If objFSO.FileExists(strInFile) Then
Set objInStream = objFSO.OpenTextFile(strInFile, ForReading, false)
For intCnt = 1 To intStartLine - 1
objInStream.SkipLine
Next
Do While Not objInStream.AtEndOfStream
arrLine = Split(objInStream.ReadLine, strInDelim)
strOutLine = ""
intColCnt = 1
For intMapCnt = 0 To UBound(arrMappings(0))
intSrcCol = arrMappings(0)(intMapCnt) - 1
intDstCol = arrMappings(1)(intMapCnt) - 1
For intCnt = intColCnt To intDstCol
strOutLine = strOutLine & strOutDelim
Next
strOutLine = strOutLine & arrLine(intSrcCol)
intColCnt = intDstCol + 1
Next
For intCnt = intColCnt To intOutCols - 1
strOutLine = strOutLine & strOutDelim
Next
objOutStream.WriteLine(strOutLine)
Erase arrLine
Loop
objInStream.Close
End If
End Sub
Aufruf
Das Script z.B. als GenAdressen.vbs speichern. Dann kannst Du ein Batchfile mit folgendem Inhalt erstellen und per Doppelklick starten:cscript /nologo GenAdressen.vbs
Anwendung
Die Parameter des Scripts werden in den Zeilen 6 bis 35 konfiguriert (siehe Kommentare). Erklärungsbedürftig sollten eigentlich nur die beiden Arrays arrMappings1 und arrMappings2 sein.Die Zeilen 13 bis 16 bilden zusammen die Initialisierung des Arrays arrMappings1, entsprechend sind die Zeilen 25 bis 28 für das Array arrMappings2 zuständig. Syntaktisch handelt es sich bei jedem der genannten Blöcke um eine einzige Zeile. VBScript lässt die Aufteilung eines Befehls auf mehrere Zeilen zu, wenn man die einzelnen Zeilen mit dem Zeichen
_
(Tiefstrich) abschließt.In Zeile 14 werden die Nummern der Quellspalten für die erste Eingabedatei angegeben, in Zeile 15 die Nummern der Zielspalten. Die Reihenfolge der Spaltennummern muss miteinander korrespondieren. Im Beispiel wird also Spalte 6 der Quelldatei auf Spalte 8 der Zieldatei gemappt.
Wichtig ist dabei, das die zweite Zeile der Array-Initialisierung (also Zeile 15 bzw. Zeile 27) immer aufsteigend sortiert ist. Somit würde bei der zweiten Eingabedatei Spalte 8 in Spalte 4 der Ausgabedatei geschrieben.
Gruß
Friemler
Hey,
das kann gebatcht werden, aber leider artet das in Arbeit aus. Erschwerend kommt hinzu, dass colinardo scheints heut sein gewonnenes Surface feiert
Versteh mich nicht falsch, ich will mich nicht vorm Scripten drücken, aber warum nimmst du nicht ein Excel/OpenOffice her und erledigst das mit Makros? Das wär einfacher, effizienter und wartbarer als uns hier die Semi-Colons zählen zu lassen
Gruss!
das kann gebatcht werden, aber leider artet das in Arbeit aus. Erschwerend kommt hinzu, dass colinardo scheints heut sein gewonnenes Surface feiert
Versteh mich nicht falsch, ich will mich nicht vorm Scripten drücken, aber warum nimmst du nicht ein Excel/OpenOffice her und erledigst das mit Makros? Das wär einfacher, effizienter und wartbarer als uns hier die Semi-Colons zählen zu lassen
Gruss!
Hallo Knut,
Ich habe das Script aus meinem ersten Posting etwas erweitert, sodass folgende zusätzliche Anforderungen erfüllt werden:
Ich habe auch die Konfiguration so angepasst, dass die von Dir formulierten Anforderungen aus Deinem letzten Posting erfüllt werden.
BTW: Diese Konfigurationsänderungen hättest Du auch selbst vornehmen können, genau deshalb habe ich das Script so flexibel entworfen. Du musst nur die Nummern der von Dir genannten Spalten durch Abzählen ermitteln und die Arrays in den Zeilen 14 u. 15 bzw. 26 u. 27 damit füllen. Und nicht vergessen, die Gesamtanzahl der Spalten in der DPAG.csv in Zeile 39 und die Nummer der Spalte mit der Strasse in Zeile 35 eintragen.
Ich habe durch meinen Job wenig Zeit, hier im Forum aktiv zu sein, es kann deshalb sein, dass ich mich auch mal ein paar Tage nicht melde. Wenn jemand anderes übernehmen möchte, kann er das gerne tun.
Hier jetzt das aktualisierte Script:
Gestartet wird es, wie schon oben erwähnt, mit dem Befehl
Du musst es nur mit der Dateierweiterung
Gruß
Friemler
[EDIT]
Kleine Fehlerkorrektur ergänzt
[/EDIT]
[EDIT2]
Anpassungen an Wünsche des TO
[/EDIT2]
Die Anzahl der Spalten in den CSV Dateien ist nicht variabel.
Mein Script kann mit einer beliebigen Anzahl von Spalten arbeiten, sowohl in der/den Quelldatei(en) als auch in der Zieldatei.Die Anzahl der Zeilen jedoch schon. Daher sollte es, wenn möglich dem Script völlig Schnuppe
sein wie viele Zeilen in den jeweiligen Dateien zu lesen sind.
Meinem Script ist das auch schnuppe.sein wie viele Zeilen in den jeweiligen Dateien zu lesen sind.
Desweiteren beinhaltet die DPAG.CSV wie man sieht schon Informationen in Zeile 1 und 2
Die quasi die Vorlage darstellen und erhaloten bleiben müssen.
Die zusätzlich gelesenen Informationen sollten also immer an den bestehenden Inhalt angehängt werden.
Davon hast Du in Deinem Eröffnungsposting nichts erwähnt, lässt sich aber leicht nachrüsten.Die quasi die Vorlage darstellen und erhaloten bleiben müssen.
Die zusätzlich gelesenen Informationen sollten also immer an den bestehenden Inhalt angehängt werden.
Auch wenn das Script mit dem lesen der EB.CSV fertig ist, sollten die Informationen der
AM.CSV an die Informationen der EB.CSV angehängt werden. Ganz gleich wie viel hier schon steht.
Genau das macht mein Script sowieso schon.AM.CSV an die Informationen der EB.CSV angehängt werden. Ganz gleich wie viel hier schon steht.
Weil die Zahl der Zeilen immer variable ist, kann ich nicht sagen schreibe den Inhalt
der AM.CSV ab Zeile 4 in die DPAG oder so.
Das ist auch nicht nötig.der AM.CSV ab Zeile 4 in die DPAG oder so.
Ich habe das Script aus meinem ersten Posting etwas erweitert, sodass folgende zusätzliche Anforderungen erfüllt werden:
- Die DPAG.csv wird nicht mehr überschrieben wird. Stattdessen werden alle aus den Eingabedateien gelesenen Daten an die Datei angehängt.
- Die Eingabedateien werden nur noch so lange eingelesen, bis eine leere Zeile auftaucht, dann wird abgebrochen. Dadurch werden die überflüssigen Zeilen in der EB.csv nicht verarbeitet.
- Wenn in eine Spalte der Ausgabedatei mehrere Werte eingetragen werden, wird zwischen die beiden Werte ein Leerzeichen eingefügt. Dadurch können die Spalten ship-adresse-2 und ship-adresse-3 aus der AM.csv in eine Spalte der Ausgabedatei geschrieben werden.
- Wenn die Spalte 3 der Ausgabedatei beschrieben wird, wird eine ggf. vorhandene Hausnummer extrahiert und in die Spalte 4 geschrieben. Die Hausnummer kann auch Buchstaben enthalten, also z.B. so etwas wie 46a oder 34 b.
Ich habe auch die Konfiguration so angepasst, dass die von Dir formulierten Anforderungen aus Deinem letzten Posting erfüllt werden.
BTW: Diese Konfigurationsänderungen hättest Du auch selbst vornehmen können, genau deshalb habe ich das Script so flexibel entworfen. Du musst nur die Nummern der von Dir genannten Spalten durch Abzählen ermitteln und die Arrays in den Zeilen 14 u. 15 bzw. 26 u. 27 damit füllen. Und nicht vergessen, die Gesamtanzahl der Spalten in der DPAG.csv in Zeile 39 und die Nummer der Spalte mit der Strasse in Zeile 35 eintragen.
Ich habe durch meinen Job wenig Zeit, hier im Forum aktiv zu sein, es kann deshalb sein, dass ich mich auch mal ein paar Tage nicht melde. Wenn jemand anderes übernehmen möchte, kann er das gerne tun.
Hier jetzt das aktualisierte Script:
Const ForReading = 1
Const ForAppending = 8
'********** Konfiguration ****************
'Eingabedatei #1
strInFile1 = "EB.csv"
'Spalten-Trennzeichen
strInDelimiter1 = ";"
'Startzeile
intStartLine1 = 3
'Spalten-Mappings
arrMappings1 = Array(_
Array(3,7,6,10,8),_
Array(1,2,3, 5,6)_
)
'Eingabedatei #2
strInFile2 = "AM.csv"
'Spalten-Trennzeichen
strInDelimiter2 = ";"
'Startzeile
intStartLine2 = 2
'Spalten-Mappings
arrMappings2 = Array(_
Array(17,19,20,18,23,21),_
Array( 1, 2, 2, 3, 5, 6)_
)
'Ausgabedatei
strOutFile = "DPAG.csv"
'Spalten-Trennzeichen
strOutDelimiter = ";"
'Nummer der Spalte mit der Strasse
intOutStreetCol = 3
'Nummer der Spalte mit der PLZ
intOutPLZCol = 5
'Gesamtzahl der Spalten
intOutCols = 8
'*****************************************
Set objFSO = CreateObject("Scripting.FileSystemObject")
'Ausgabedatei öffnen
Set objOutStream = objFSO.OpenTextFile(strOutFile, ForAppending, true)
'Erste Eingabedatei verarbeiten
Call ProcessFile(objOutStream, strOutDelimiter, intOutCols,_
strInFile1, strInDelimiter1, intStartLine1,_
arrMappings1)
'Zweite Eingabedatei verarbeiten
Call ProcessFile(objOutStream, strOutDelimiter, intOutCols,_
strInFile2, strInDelimiter2, intStartLine2,_
arrMappings2)
'Ausgabedatei schließen
objOutStream.Close
Sub ProcessFile(objOutStream, strOutDelim, intOutCols,_
strInFile, strInDelim, intStartLine,_
arrMappings)
Dim intCnt, intMapCnt, intColCnt, arrLine, strOutLine, strStreet, strHouseNumber
Dim intSrcCol, intDstCol
Dim objInStream
If objFSO.FileExists(strInFile) Then
Set objInStream = objFSO.OpenTextFile(strInFile, ForReading, false)
For intCnt = 1 To intStartLine - 1
objInStream.SkipLine
Next
Do While Not objInStream.AtEndOfStream
arrLine = Split(objInStream.ReadLine, strInDelim)
strOutLine = ""
intColCnt = 1
If IsEmptyLine(arrLine) Then Exit Do
For intMapCnt = 0 To UBound(arrMappings(0))
intSrcCol = arrMappings(0)(intMapCnt) - 1
intDstCol = arrMappings(1)(intMapCnt) - 1
For intCnt = intColCnt To intDstCol
strOutLine = strOutLine & strOutDelim
Next
If intColCnt > intDstCol And _
arrLine(intSrcCol) <> "" And _
Len(strOutLine) > 0 And _
Right(strOutLine, 1) <> strOutDelim Then
strOutLine = strOutLine & " "
End If
If intDstCol + 1 = intOutPLZCol Then
arrLine(intSrcCol) = Right("00000" & arrLine(intSrcCol), 5)
End If
If intDstCol + 1 = intOutStreetCol Then
strStreet = arrLine(intSrcCol)
Call ExtractHouseNumber(strStreet, strHouseNumber)
strOutLine = strOutLine & strStreet & strOutDelim & strHouseNumber
intColCnt = intDstCol + 2
Else
strOutLine = strOutLine & arrLine(intSrcCol)
intColCnt = intDstCol + 1
End If
Next
For intCnt = intColCnt To intOutCols - 1
strOutLine = strOutLine & strOutDelim
Next
objOutStream.WriteLine(strOutLine)
Erase arrLine
Loop
objInStream.Close
End If
End Sub
Function IsEmptyLine(arrLine)
Dim intCnt
For intCnt = 0 To UBound(arrLine)
If arrLine(intCnt) <> "" Then Exit For
Next
IsEmptyLine = (intCnt > UBound(arrLine))
End Function
Sub ExtractHouseNumber(ByRef strStreet, ByRef strHouseNumber)
Dim objRegEx, colMatches
strStreet = Trim(strStreet)
strHouseNumber = ""
Set objRegEx = New RegExp
objRegEx.IgnoreCase = True
objRegEx.Pattern = "([^0-9]*)([0-9]*[a-z ]*)"
Set colMatches = objRegEx.Execute(strStreet)
If colMatches.Count > 0 Then
If colMatches(0).SubMatches.Count > 1 Then
strStreet = Trim(colMatches(0).SubMatches(0))
strHouseNumber = Trim(colMatches(0).SubMatches(1))
End If
End If
End Sub
Gestartet wird es, wie schon oben erwähnt, mit dem Befehl
cscript /nologo "PfadUndNameDesScripts.vbs"
VBS
speichern, in das gleiche Verzeichnis, in dem die Dateien liegen, mit denen es arbeiten soll. Oder Du gibst in den Zeilen 7, 19 und 31 die absoluten Pfade zu den Dateien an.Gruß
Friemler
[EDIT]
Kleine Fehlerkorrektur ergänzt
[/EDIT]
[EDIT2]
Anpassungen an Wünsche des TO
[/EDIT2]
Hallo Knut,
ich habe das Script aktualisiert.
Der Fehler btr. Sonderzeichen im Straßennamen ist behoben, auch die Postleitzahlen sollten jetzt immer 5-stellig sein.
Das von Dir geschilderte Fehlverhalten (Abbruch der Eingabedatei-Verarbeitung) bei der Ausnahme "Kunde hat mehr als einen Artikel bestellt" kann ich hier nicht nachvollziehen. Bei mir entsteht dann eine Zeile mit 7 Semikola (nach den Änderungen steht jetzt zwischen dem 4. und 5. Semikolon eine Kolonne von 5 Nullen wegen der nichtvorhandenen Postleitzahl). Das musst Du bitte nochmal genauer erläutern. Kann/Muss eine solche Zeile nicht ignoriert werden (zumindest für den Frankierservice)?
Verwende für das Posting von Daten und Code bitte die Codeformatierung, Deine obigen Angaben bzgl. des Ausnahmefalls sind nicht sehr informativ, da die Formatierung bei der Darstellung als normaler Text verloren geht.
Gruß
Friemler
ich habe das Script aktualisiert.
Der Fehler btr. Sonderzeichen im Straßennamen ist behoben, auch die Postleitzahlen sollten jetzt immer 5-stellig sein.
Das von Dir geschilderte Fehlverhalten (Abbruch der Eingabedatei-Verarbeitung) bei der Ausnahme "Kunde hat mehr als einen Artikel bestellt" kann ich hier nicht nachvollziehen. Bei mir entsteht dann eine Zeile mit 7 Semikola (nach den Änderungen steht jetzt zwischen dem 4. und 5. Semikolon eine Kolonne von 5 Nullen wegen der nichtvorhandenen Postleitzahl). Das musst Du bitte nochmal genauer erläutern. Kann/Muss eine solche Zeile nicht ignoriert werden (zumindest für den Frankierservice)?
Verwende für das Posting von Daten und Code bitte die Codeformatierung, Deine obigen Angaben bzgl. des Ausnahmefalls sind nicht sehr informativ, da die Formatierung bei der Darstellung als normaler Text verloren geht.
Gruß
Friemler
Hallo Knut,
ich habe das Script Deinen Anforderungen entsprechend umgeschrieben:
Außerdem habe ich das Script mit Kommentaren versehen, was zum besseren Verständnis beitragen kann.
Hier der Code:
Gruß
Friemler
ich habe das Script Deinen Anforderungen entsprechend umgeschrieben:
- Die Abtrennung der Hausnummer vom Straßennamen habe ich entfernt, da ich keine Methode gefunden habe, die bei allen möglichen Adressen sauber funktioniert, auch wenn eine Adresse fehlerhaft angegeben wurde (z.B. kein Leerzeichen zwischen Straßenname und Hausnummer).
- Es werden jetzt zwei Ausgabedateien erstellt, eine für deutsche und eine für ausländische Kunden.
- Die alten Inhalte der Ausgabedateien werden unter Beibehaltung der ersten 2 Zeilen gelöscht.
- Der Adresstyp "HOUSE" wird in jede Zeile der Ausgabedateien eingetragen.
- Wenn in einer Zeile der Eingabedatei kein Kundenname angegeben ist, wird für diese Zeile kein Eintrag in der Ausgabedatei erzeugt. Somit sollte der Fall "Kunde bestellt mehr als einen Artikel" nur noch zu einem Eintrag in der Ausgabedatei führen. Zumindest für Einträge aus der EB.csv, für die AM.csv hast Du noch keine Angaben für diesen Fall gemacht. Ich konnte übrigens das von Dir geschilderte Fehlverhalten (Script stoppt und schreibt keine Einträge) auch mit den von Dir geposteten Testdaten nicht reproduzieren.
- In die Spalte "LAND" der Ausgabedateien wird ein Ländercode eingetragen. Der Inhalt des Arrays
arrCountryMappings
in Zeile 60 legt die Zuordnung der Länderbezeichnungen in den Eingabedateien zum Ländercode in der Ausgabedatei fest. Hier musst Du evtl. jetzt oder später weitere Zuordnungen ergänzen! Die Groß-/Kleinschreibung spielt dabei keine Rolle. Folgende Zuordnungen sind z.Z. gesetzt:
- Länderspalte leer -> DE
- Deutschland -> DE
- DE -> DE
- Österreich -> AT
- AT -> AT
- Schweiz -> CH
- CH -> CH
Außerdem habe ich das Script mit Kommentaren versehen, was zum besseren Verständnis beitragen kann.
Hier der Code:
Option Explicit
Const ForReading = 1
Const ForWriting = 2
Dim strInFile1, strInDelimiter1, intStartLine1, arrMappings1
Dim strInFile2, strInDelimiter2, intStartLine2, arrMappings2
Dim strOutFileDE, strOutFileFC, strOutDelimiter
Dim intOutPLZCol, intOutCountryCodeCol, intOutAdrTypeCol, intOutTotalCols
Dim arrCountryMappings
Dim objFSO, objOutStreamDE, objOutStreamFC
'********** Konfiguration ****************
'Eingabedatei #1
strInFile1 = "EB.csv"
'Spalten-Trennzeichen
strInDelimiter1 = ";"
'Startzeile
intStartLine1 = 3
'Spalten-Mappings
arrMappings1 = Array(_
Array(3,7,6,10,8,11,1),_
Array(1,2,3, 5,6, 7,8)_
)
'Eingabedatei #2
strInFile2 = "AM.csv"
'Spalten-Trennzeichen
strInDelimiter2 = ";"
'Startzeile
intStartLine2 = 2
'Spalten-Mappings
arrMappings2 = Array(_
Array(17,19,20,18,23,21,24,1),_
Array( 1, 2, 2, 3, 5, 6, 7,8)_
)
'Ausgabedateien
strOutFileDE = "DPAG.csv"
strOutFileFC = "DPAG Ausland.csv"
'Spalten-Trennzeichen
strOutDelimiter = ";"
'Nummer der Spalte mit der PLZ
intOutPLZCol = 5
'Nummer der Spalte mit dem Länderkürzel
intOutCountryCodeCol = 7
'Nummer der Spalte mit dem Adresstyp
intOutAdrTypeCol = 8
'Gesamtzahl der Spalten
intOutTotalCols = 8
'Länderkürzel
arrCountryMappings = Array(_
Array("" ,"Deutschland","DE","Österreich","AT","Schweiz","CH"),_
Array("DE","DE" ,"DE","AT" ,"AT","CH" ,"CH")_
)
'*****************************************
Set objFSO = CreateObject("Scripting.FileSystemObject")
If Not FileExists(strOutFileDE) Then WScript.Quit
If Not FileExists(strOutFileFC) Then WScript.Quit
'Ausgabedateien initialisieren
Set objOutStreamDE = InitOutFile(strOutFileDE)
Set objOutStreamFC = InitOutFile(strOutFileFC)
'Erste Eingabedatei verarbeiten
Call ProcessFile(objOutStreamDE, objOutStreamFC, strOutDelimiter, intOutTotalCols,_
strInFile1, strInDelimiter1, intStartLine1,_
arrMappings1)
'Zweite Eingabedatei verarbeiten
Call ProcessFile(objOutStreamDE, objOutStreamFC, strOutDelimiter, intOutTotalCols,_
strInFile2, strInDelimiter2, intStartLine2,_
arrMappings2)
'Ausgabedateien schließen
objOutStreamDE.Close
objOutStreamFC.Close
Sub ProcessFile(objOutStreamDE, objOutStreamFC, strOutDelim, intOutTotalCols,_
strInFile, strInDelim, intStartLine,_
arrMappings)
Dim intCnt, intMapCnt, intColCnt
Dim arrLine, strOutLine, strCountryCode
Dim intSrcCol, intDstCol
Dim bolIsGermanCustomer
Dim objInStream
'Prüfen ob die Eingabedatei existiert
If objFSO.FileExists(strInFile) Then
'Flag initialisieren
bolIsGermanCustomer = True
'Eingabedatei zum Lesen öffnen
Set objInStream = objFSO.OpenTextFile(strInFile, ForReading, false)
'Soviele Zeilen überspringen, bis die gewünschte Startzeile erreicht ist
For intCnt = 1 To intStartLine - 1
objInStream.SkipLine
Next
'Eingabedatei einlesen bis das Dateiende erreicht ist
Do While Not objInStream.AtEndOfStream
'Eine Zeile einlesen, anhand des Trennzeichens zerteilen
'und in Array speichern
arrLine = Split(objInStream.ReadLine, strInDelim)
'Zeilenpuffer für die Ausgabe löschen
strOutLine = ""
'Spaltenzähler für jede Eingabezeile neu initialisieren
intColCnt = 1
'Wenn die eingelesene Zeile leer ist, das Einlesen der Datei beenden
If IsEmptyLine(arrLine) Then Exit Do
'Alle Spalten-Mappings verarbeiten
For intMapCnt = 0 To UBound(arrMappings(0))
'Quell- und Zielspalte ermitteln
intSrcCol = arrMappings(0)(intMapCnt) - 1
intDstCol = arrMappings(1)(intMapCnt) - 1
'Falls notwendig, den Zeilenpuffer bis zur
'ermittelten Zielspalte mit Leerzellen auffüllen
For intCnt = intColCnt To intDstCol
strOutLine = strOutLine & strOutDelim
Next
'Falls in die Zielspalte bereits etwas eingetragen wurde,
'ein Leerzeichen an den Zeilenpuffer anhängen
If intColCnt > intDstCol And _
arrLine(intSrcCol) <> "" And _
Len(strOutLine) > 0 And _
Right(strOutLine, 1) <> strOutDelim Then
strOutLine = strOutLine & " "
End If
'Dafür sorgen, dass in der Spalte für Postleitzahlen
'immer 5 Ziffern stehen
If intDstCol + 1 = intOutPLZCol Then
arrLine(intSrcCol) = Right("00000" & arrLine(intSrcCol), 5)
End If
'Aus dem Inhalt der Quellspalte mit dem Land der Versandadresse
'einen Ländercode erzeugen und ein Flag setzen, ob es sich um
'einen deutschen oder ausländischen Kunden handelt
If intDstCol + 1 = intOutCountryCodeCol Then
strCountryCode = CountryCode(arrLine(intSrcCol))
arrLine(intSrcCol) = strCountryCode
If StrComp(strCountryCode, "DE", vbTextCompare) = 0 Then
bolIsGermanCustomer = True
Else
bolIsGermanCustomer = False
End If
End If
'In die Spalte mit dem Adresstyp den Wert "HOUSE" schreiben
If intDstCol + 1 = intOutAdrTypeCol Then
arrLine(intSrcCol) = "HOUSE"
End If
'Jetzt den Spaltenwert in den Zeilenpuffer übertragen
strOutLine = strOutLine & arrLine(intSrcCol)
'Spaltenzähler auf die Nummer der Spalte setzen,
'die nach der gerade beschriebenen Spalte kommt
intColCnt = intDstCol + 1
Next
'Falls notwendig, den Zeilenpuffer bis zur
'vorgegebenen Endspalte mit Leerzellen auffüllen
For intCnt = intColCnt To intOutTotalCols - 1
strOutLine = strOutLine & strOutDelim
Next
'Den Zeilenpuffer nur in die Ausgabedatei schreiben,
'wenn die Namensspalte nicht leer ist
If Left(strOutLine, 1) <> strOutDelim Then
'Jetzt anhand des oben gesetzten Flags entscheiden, in welche
'der beiden Ausgabedateien der Zeilenpuffer geschrieben wird
If bolIsGermanCustomer Then
objOutStreamDE.WriteLine(strOutLine)
Else
objOutStreamFC.WriteLine(strOutLine)
End If
End If
'Speicher des Arrays mit der Eingabezeile freigeben
Erase arrLine
Loop
'Eingabedatei schließen
objInStream.Close
End If
End Sub
Function FileExists(strFile)
If objFSO.FileExists(strFile) Then
FileExists = True
Else
MsgBox "Die Datei" & vbNewLine & _
strFile & vbNewLine & _
"existiert nicht!", _
vbCritical + vbOKOnly + vbDefaultButton1, _
WScript.ScriptName
FileExists = False
End If
End Function
Function InitOutFile(strOutFile)
Dim objInStream, objOutStream, strFirstTwoLines
'Ausgabedatei zum Lesen öffnen und die ersten zwei Zeilen auslesen
Set objInStream = objFSO.OpenTextFile(strOutFile, ForReading, false)
strFirstTwoLines = objInStream.ReadLine & vbNewLine & _
objInStream.ReadLine & vbNewLine
objInStream.Close
'Ausgabedatei zum Schreiben öffnen und die ersten zwei Zeilen schreiben
Set objOutStream = objFSO.OpenTextFile(strOutFile, ForWriting, true)
objOutStream.Write(strFirstTwoLines)
Set InitOutFile = objOutStream
End Function
Function IsEmptyLine(arrLine)
Dim intCnt
For intCnt = 0 To UBound(arrLine)
If arrLine(intCnt) <> "" Then Exit For
Next
IsEmptyLine = (intCnt > UBound(arrLine))
End Function
Function CountryCode(strCountryName)
Dim intCnt
CountryCode = ""
For intCnt = 0 To UBound(arrCountryMappings(0))
If StrComp(arrCountryMappings(0)(intCnt), strCountryName, vbTextCompare) = 0 Then
CountryCode = arrCountryMappings(1)(intCnt)
Exit For
End If
Next
End Function
Gruß
Friemler
Hallo Knut,
auch mit Deinen zuletzt geposteten Testdaten läuft das Script hier bei mir und produziert Ausgabedateien, in denen alle in den Eingabedateien enthaltenen Datensätze vorhanden sind.
Bitte starte CMD.exe, navigiere mit dem
Poste evtl. auftauchende Fehlermeldungen hier.
Gruß
Friemler
auch mit Deinen zuletzt geposteten Testdaten läuft das Script hier bei mir und produziert Ausgabedateien, in denen alle in den Eingabedateien enthaltenen Datensätze vorhanden sind.
Bitte starte CMD.exe, navigiere mit dem
CD
-Kommando in das Verzeichnis, wo das Script liegt, und starte es mit der Befehlszeilecscript /nologo "NameDesScripts.vbs"
Gruß
Friemler
Hallo Knut,
wir nähern uns einer Lösung.
Ich habe das Script weiter angepasst:
Hier der Code:
Gruß
Friemler
[EDIT]
Code etwas aufgeräumt
[/EDIT]
wir nähern uns einer Lösung.
Ich habe das Script weiter angepasst:
- Am Anfang des Scripts wird das Vorhandensein sämtlicher benötigter Dateien abgefragt. Wenn eine davon fehlt, wird eine Fehlermeldung angezeigt und abgebrochen.
- Am Ende des Scriptlaufs wird eine Erfolgsmeldung ausgegeben.
- Es gibt jetzt noch ein Array zur Zuordnung der Ländercodes zu der im jeweiligen Land gültigen Länge der Postleitzahlen (siehe Zeile 66).
- Die Datei AM.csv benutzt als Trennzeichen zwischen den Feldern eines Datensatzes TAB-Zeichen. Nach Anpassung von Zeile 36 kannst Du nun die AM.csv direkt verarbeiten.
Hier der Code:
Option Explicit
'Definition der Konstanten
Const ForReading = 1
Const ForWriting = 2
'Deklaration der Variablen
Dim strInFile1, strInDelimiter1, intStartLine1, arrMappings1
Dim strInFile2, strInDelimiter2, intStartLine2, arrMappings2
Dim strOutFileDE, strOutFileFC, strOutDelimiter
Dim intOutPLZCol, intOutCountryCodeCol, intOutAdrTypeCol, intOutTotalCols
Dim arrCountryMappings, arrPostCodeMappings
Dim objFSO, objOutStreamDE, objOutStreamFC
'********** Konfiguration ****************
'Eingabedatei #1
strInFile1 = "EB.csv"
'Spalten-Trennzeichen
strInDelimiter1 = ";"
'Startzeile
intStartLine1 = 3
'Spalten-Mappings
arrMappings1 = Array(_
Array(3,7,6,10,8,11),_
Array(1,2,3, 5,6, 7)_
)
'Eingabedatei #2
strInFile2 = "AM.txt"
'Spalten-Trennzeichen
strInDelimiter2 = Chr(9)
'Startzeile
intStartLine2 = 2
'Spalten-Mappings
arrMappings2 = Array(_
Array(17,19,20,18,23,21,24),_
Array( 1, 2, 2, 3, 5, 6, 7)_
)
'Ausgabedateien
strOutFileDE = "DPAG.csv"
strOutFileFC = "DPAG Ausland.csv"
'Spalten-Trennzeichen
strOutDelimiter = ";"
'Nummer der Spalte mit der PLZ
intOutPLZCol = 5
'Nummer der Spalte mit dem Länderkürzel
intOutCountryCodeCol = 7
'Nummer der Spalte mit dem Adresstyp
intOutAdrTypeCol = 8
'Gesamtzahl der Spalten
intOutTotalCols = 8
'Ländercodes
arrCountryMappings = Array(_
Array("" ,"Deutschland","DE","Österreich","AT","Schweiz","CH"),_
Array("DE","DE" ,"DE","AT" ,"AT","CH" ,"CH")_
)
'Länge der Postleitzahlen in den verschiedenen Ländern
arrPostCodeMappings = Array(_
Array("DE","AT","CH"),_
Array( 5, 4, 4)_
)
'*****************************************
Set objFSO = CreateObject("Scripting.FileSystemObject")
'Alle verwendeten Dateien auf Vorhandensein prüfen
If Not FileExists(strInFile1) Then WScript.Quit
If Not FileExists(strInFile2) Then WScript.Quit
If Not FileExists(strOutFileDE) Then WScript.Quit
If Not FileExists(strOutFileFC) Then WScript.Quit
'Ausgabedateien initialisieren
Set objOutStreamDE = InitOutFile(strOutFileDE)
Set objOutStreamFC = InitOutFile(strOutFileFC)
'Erste Eingabedatei verarbeiten
Call ProcessFile(objOutStreamDE, objOutStreamFC, strOutDelimiter, intOutTotalCols,_
strInFile1, strInDelimiter1, intStartLine1,_
arrMappings1)
'Zweite Eingabedatei verarbeiten
Call ProcessFile(objOutStreamDE, objOutStreamFC, strOutDelimiter, intOutTotalCols,_
strInFile2, strInDelimiter2, intStartLine2,_
arrMappings2)
'Ausgabedateien schließen
objOutStreamDE.Close
objOutStreamFC.Close
'Erfolgsmeldung ausgeben
MsgBox "Adressen wurden erfolgreich erfasst.", _
vbInformation + vbOKOnly + vbDefaultButton1, _
WScript.ScriptName
Sub ProcessFile(objOutStreamDE, objOutStreamFC, strOutDelim, intOutTotalCols,_
strInFile, strInDelim, intStartLine,_
arrMappings)
Dim intCnt, intMapCnt, intColCnt
Dim arrInLine, arrOutLine, strLineBuffer
Dim strCountryCode, intPostCodeLength
Dim intSrcCol, intDstCol
Dim bolIsGermanCustomer
Dim objInStream
'Eingabedatei zum Lesen öffnen
Set objInStream = objFSO.OpenTextFile(strInFile, ForReading, false)
'Soviele Zeilen überspringen, bis die gewünschte Startzeile erreicht ist
For intCnt = 1 To intStartLine - 1
objInStream.SkipLine
Next
'Eingabedatei einlesen bis das Dateiende erreicht ist
Do While Not objInStream.AtEndOfStream
'Eine Zeile einlesen, anhand des Trennzeichens zerteilen
'und in Array speichern
arrInLine = Split(objInStream.ReadLine, strInDelim)
'Zeilenpuffer für die Ausgabe löschen
strLineBuffer = ""
'Spaltenzähler für jede Eingabezeile neu initialisieren
intColCnt = 1
'Wenn die eingelesene Zeile leer ist, das Einlesen der Datei beenden
If IsEmptyLine(arrInLine) Then Exit Do
'Alle Spalten-Mappings verarbeiten
For intMapCnt = 0 To UBound(arrMappings(0))
'Quell- und Zielspalte ermitteln
intSrcCol = arrMappings(0)(intMapCnt) - 1
intDstCol = arrMappings(1)(intMapCnt) - 1
'Falls notwendig, den Zeilenpuffer bis zur
'ermittelten Zielspalte mit Leerzellen auffüllen
For intCnt = intColCnt To intDstCol
strLineBuffer = strLineBuffer & strOutDelim
Next
'Falls in die Zielspalte bereits etwas eingetragen wurde,
'ein Leerzeichen an den Zeilenpuffer anhängen
If intColCnt > intDstCol And _
arrInLine(intSrcCol) <> "" And _
Len(strLineBuffer) > 0 And _
Right(strLineBuffer, 1) <> strOutDelim Then
strLineBuffer = strLineBuffer & " "
End If
'Jetzt den Spaltenwert in den Zeilenpuffer übertragen
strLineBuffer = strLineBuffer & arrInLine(intSrcCol)
'Spaltenzähler auf die Nummer der Spalte setzen,
'die nach der gerade beschriebenen Spalte kommt
intColCnt = intDstCol + 1
Next
'Falls notwendig, den Zeilenpuffer bis zur
'vorgegebenen Endspalte mit Leerzellen auffüllen
For intCnt = intColCnt To intOutTotalCols - 1
strLineBuffer = strLineBuffer & strOutDelim
Next
'Zeilenpuffer anhand des Trennzeichens zerteilen und in Array speichern
arrOutLine = Split(strLineBuffer, strOutDelim)
'Aus dem Inhalt der Landesspalte einen Ländercode erzeugen
'und ein Flag setzen, ob es sich um einen deutschen oder
'einen ausländischen Kunden handelt
arrOutLine(intOutCountryCodeCol - 1) = CountryCode(arrOutLine(intOutCountryCodeCol - 1))
strCountryCode = arrOutLine(intOutCountryCodeCol - 1)
bolIsGermanCustomer = (StrComp(strCountryCode, "DE", vbTextCompare) = 0)
'Dafür sorgen, dass in der Spalte für Postleitzahlen
'immer die im jeweiligen Land gültige Anzahl Ziffern steht
intPostCodeLength = PostCodeLength(strCountryCode)
arrOutLine(intOutPLZCol - 1) = Right(String(intPostCodeLength, "0") & arrOutLine(intOutPLZCol - 1), intPostCodeLength)
'In die Spalte mit dem Adresstyp den Wert "HOUSE" schreiben
arrOutLine(intOutAdrTypeCol - 1) = "HOUSE"
'Das Array wieder zu einem String wandeln
strLineBuffer = Join(arrOutLine, strOutDelim)
'Den Zeilenpuffer nur in die Ausgabedatei schreiben,
'wenn die Namensspalte nicht leer ist
If Left(strLineBuffer, 1) <> strOutDelim Then
'Jetzt anhand des oben gesetzten Flags entscheiden, in welche
'der beiden Ausgabedateien der Zeilenpuffer geschrieben wird
If bolIsGermanCustomer Then
objOutStreamDE.WriteLine(strLineBuffer)
Else
objOutStreamFC.WriteLine(strLineBuffer)
End If
End If
'Speicher des Arrays mit der Eingabezeile freigeben
Erase arrInLine
Erase arrOutLine
Loop
'Eingabedatei schließen
objInStream.Close
End Sub
Function FileExists(strFile)
If objFSO.FileExists(strFile) Then
FileExists = True
Else
MsgBox "Die Datei" & vbNewLine & _
strFile & vbNewLine & _
"existiert nicht!", _
vbCritical + vbOKOnly + vbDefaultButton1, _
WScript.ScriptName
FileExists = False
End If
End Function
Function InitOutFile(strOutFile)
Dim objInStream, objOutStream, strFirstTwoLines
'Ausgabedatei zum Lesen öffnen und die ersten zwei Zeilen auslesen
Set objInStream = objFSO.OpenTextFile(strOutFile, ForReading, false)
strFirstTwoLines = objInStream.ReadLine & vbNewLine & _
objInStream.ReadLine & vbNewLine
objInStream.Close
'Ausgabedatei zum Schreiben öffnen und die ersten zwei Zeilen schreiben
Set objOutStream = objFSO.OpenTextFile(strOutFile, ForWriting, true)
objOutStream.Write(strFirstTwoLines)
Set InitOutFile = objOutStream
End Function
Function IsEmptyLine(arrLine)
Dim intCnt
For intCnt = 0 To UBound(arrLine)
If arrLine(intCnt) <> "" Then Exit For
Next
IsEmptyLine = (intCnt > UBound(arrLine))
End Function
Function CountryCode(strCountryName)
Dim intCnt
CountryCode = ""
For intCnt = 0 To UBound(arrCountryMappings(0))
If StrComp(arrCountryMappings(0)(intCnt), strCountryName, vbTextCompare) = 0 Then
CountryCode = arrCountryMappings(1)(intCnt)
Exit For
End If
Next
End Function
Function PostCodeLength(strCountryCode)
Dim intCnt
PostCodeLength = 0
For intCnt = 0 To UBound(arrPostCodeMappings(0))
If StrComp(arrPostCodeMappings(0)(intCnt), strCountryCode, vbTextCompare) = 0 Then
PostCodeLength = arrPostCodeMappings(1)(intCnt)
Exit For
End If
Next
End Function
Gruß
Friemler
[EDIT]
Code etwas aufgeräumt
[/EDIT]
Hallo Knut,
prüfe bitte folgendes:
Ich kann Deinen Fehler hier nicht reproduzieren.
[EDIT]
Wenn Du eine der beteiligten Dateien umbenennst, musst Du das Script entsprechend anpassen.
[/EDIT]
Gruß
Friemler
prüfe bitte folgendes:
- Hast Du an den Arrays
arrMappings1
bzw.arrMappings2
etwas geändert? Wenn ja, ist das alles richtig? - Schau mal in den Ausgabedateien nach, bis zu welchem Datensatz Ausgaben erfolgten. Gibt es an dem darauf folgenden Datensatz irgendwelche Auffälligkeiten (Aufbau fehlerhaft)?
Ich kann Deinen Fehler hier nicht reproduzieren.
[EDIT]
Wenn Du eine der beteiligten Dateien umbenennst, musst Du das Script entsprechend anpassen.
[/EDIT]
Gruß
Friemler
Hallo Knut,
ich habe gerade etwas "Luft" im Job, deswegen konnte ich mich heute öfter mit Deinem Problem befassen. Ab morgen ist das wieder anders.
Ich habe das Script nochmals erweitert, um es an Deine neue Anforderung anzupassen. Die Datensätze zu einer Bestellung werden nach Abschluss der Adresserfassung in Windows-Messageboxen ausgegeben, die Du mit Klick auf den OK-Button oder mit Enter schließen kannst.
Im Konfigurationsabschnitt sind ein paar neue Optionen hinzugekommen, z.B. der Name der Datei, die die Datensätze der Bestellungen aufnimmt. Die Arrays
Ich hoffe sehr für Dich, dass die Online-Plattform, von der die AM.txt stammt, für den Fall, dass ein Kunde mehrere Artikel bestellt, die Datei nach dem gleichen Schema wie die EB.csv aufbaut, dass also die Artikel in Zeilen ohne Kundenname stehen, sonst wird mein Script nicht funktionieren.
Hier nun der Code (der Endfassung?):
Gruß
Friemler
ich habe gerade etwas "Luft" im Job, deswegen konnte ich mich heute öfter mit Deinem Problem befassen. Ab morgen ist das wieder anders.
Ich habe das Script nochmals erweitert, um es an Deine neue Anforderung anzupassen. Die Datensätze zu einer Bestellung werden nach Abschluss der Adresserfassung in Windows-Messageboxen ausgegeben, die Du mit Klick auf den OK-Button oder mit Enter schließen kannst.
Im Konfigurationsabschnitt sind ein paar neue Optionen hinzugekommen, z.B. der Name der Datei, die die Datensätze der Bestellungen aufnimmt. Die Arrays
arrMappings1
und arrMappings2
enthalten jetzt noch Einträge für die Nummern der Spalten mit der Bestellmenge und den Artikelbezeichnungen. Außerdem habe ich noch eine neue Zuordnung "Ländercode -> Name des Landes" eingeführt, damit bei der Ausgabe der Bestellungs-Datensätze das Land im Klartext unter der Kundenadresse angezeigt wird.Ich hoffe sehr für Dich, dass die Online-Plattform, von der die AM.txt stammt, für den Fall, dass ein Kunde mehrere Artikel bestellt, die Datei nach dem gleichen Schema wie die EB.csv aufbaut, dass also die Artikel in Zeilen ohne Kundenname stehen, sonst wird mein Script nicht funktionieren.
Hier nun der Code (der Endfassung?):
Option Explicit
'Definition der Konstanten
Const ForReading = 1
Const ForWriting = 2
'Deklaration der Variablen
Dim strInFile1, strInDelimiter1, intStartLine1, arrMappings1
Dim strInFile2, strInDelimiter2, intStartLine2, arrMappings2
Dim strOutFileDE, strOutFileFC, strOutDelimiter, strOrdersFile
Dim intOutCustomerCol, intOutAddOnCol, intOutStreetCol, intOutHNoCol, intOutPostCodeCol
Dim intOutTownCol, intOutCountryCodeCol, intOutAdrTypeCol, intOutTotalCols
Dim intArtNameCol, intQuantityCol
Dim arrCountryMappings, arrCountryCodeMappings
Dim objFSO, objOutStreamDE, objOutStreamFC, objOrdersStream
'********** Konfiguration ****************
'Eingabedatei #1
strInFile1 = "EB.csv"
'Spalten-Trennzeichen
strInDelimiter1 = ";"
'Startzeile
intStartLine1 = 3
'Spalten-Mappings
arrMappings1 = Array(_
Array(3,7,6,10,8,11),_
Array(1,2,3, 5,6, 7),_
Array(13,15)_
)
'Eingabedatei #2
strInFile2 = "AM.txt"
'Spalten-Trennzeichen
strInDelimiter2 = Chr(9)
'Startzeile
intStartLine2 = 2
'Spalten-Mappings
arrMappings2 = Array(_
Array(17,19,20,18,23,21,24),_
Array( 1, 2, 2, 3, 5, 6, 7),_
Array(12,13)_
)
'Ausgabedateien
strOutFileDE = "DPAG.csv"
strOutFileFC = "DPAG Ausland.csv"
'Spalten-Trennzeichen
strOutDelimiter = ";"
'Nummer der Spalte mit dem Kundennamen
intOutCustomerCol = 1
'Nummer der Spalte mit den Zusatzinfos
intOutAddOnCol = 2
'Nummer der Spalte mit der Strasse
intOutStreetCol = 3
'Nummer der Spalte mit der Hausnummer
intOutHNoCol = 4
'Nummer der Spalte mit der PLZ
intOutPostCodeCol = 5
'Nummer der Spalte mit der Stadt
intOutTownCol = 6
'Nummer der Spalte mit dem Ländercode
intOutCountryCodeCol = 7
'Nummer der Spalte mit dem Adresstyp
intOutAdrTypeCol = 8
'Gesamtzahl der Spalten
intOutTotalCols = 8
'Auftragsdatei
strOrdersFile = "Aufträge.txt"
'Arrayindex der Spaltennummer der Artikelbezeichnung
intArtNameCol = 0
'Arrayindex der Spaltennummer der Menge
intQuantityCol = 1
'Ländercodes
arrCountryMappings = Array(_
Array("" ,"Deutschland","DE","Österreich","AT","Schweiz","CH"),_
Array("DE","DE" ,"DE","AT" ,"AT","CH" ,"CH")_
)
'Zuordnung der Ländercodes zum Namen des Landes und
'der Länge der Postleitzahlen
arrCountryCodeMappings = Array(_
Array("DE" ,"AT" ,"CH" ),_
Array("Deutschland","Österreich","Schweiz"),_
Array( 5, 4, 4)_
)
'*****************************************
Set objFSO = CreateObject("Scripting.FileSystemObject")
'Alle verwendeten Dateien auf Vorhandensein prüfen
If Not FileExists(strInFile1) Then WScript.Quit
If Not FileExists(strInFile2) Then WScript.Quit
If Not FileExists(strOutFileDE) Then WScript.Quit
If Not FileExists(strOutFileFC) Then WScript.Quit
'Ausgabedateien initialisieren
Set objOutStreamDE = InitOutFile(strOutFileDE)
Set objOutStreamFC = InitOutFile(strOutFileFC)
Set objOrdersStream = objFSO.CreateTextFile(strOrdersFile, True)
'Erste Eingabedatei verarbeiten
Call ProcessFile(strInFile1, strInDelimiter1, intStartLine1, arrMappings1)
'Zweite Eingabedatei verarbeiten
Call ProcessFile(strInFile2, strInDelimiter2, intStartLine2, arrMappings2)
'Ausgabedateien schließen
objOutStreamDE.Close
objOutStreamFC.Close
objOrdersStream.Close
'Erfolgsmeldung ausgeben
MsgBox "Adressen wurden erfolgreich erfasst.", _
vbInformation + vbOKOnly + vbDefaultButton1, _
WScript.ScriptName
'Aufträge ausgeben
Set objOrdersStream = objFSO.OpenTextFile(strOrdersFile, ForReading, false)
Call ShowOrders()
objOrdersStream.Close
Sub ProcessFile(strInFile, strInDelim, intStartLine, arrMappings)
Dim intCnt, intMapCnt, intColCnt
Dim arrInLine, arrOutLine, strLineBuffer
Dim strCountryCode, intPostCodeLength
Dim intSrcCol, intDstCol
Dim bolIsGermanCustomer
Dim objInStream
'Eingabedatei zum Lesen öffnen
Set objInStream = objFSO.OpenTextFile(strInFile, ForReading, false)
'Soviele Zeilen überspringen, bis die gewünschte Startzeile erreicht ist
For intCnt = 1 To intStartLine - 1
objInStream.SkipLine
Next
'Eingabedatei einlesen bis das Dateiende erreicht ist
Do While Not objInStream.AtEndOfStream
'Eine Zeile einlesen
strLineBuffer = objInStream.ReadLine
'Codierte Sonderzeichen ersetzen
strLineBuffer = Replace(strLineBuffer, "&", "&", 1, -1, vbTextCompare)
'Zeile anhand des Trennzeichens zerteilen und in Array speichern
arrInLine = Split(strLineBuffer, strInDelim)
'Anführungszeichen um die Zelleninhalte entfernen
For intCnt = 0 To UBound(arrInLine)
arrInLine(intCnt) = UnQuote(arrInLine(intCnt))
Next
'Zeilenpuffer für die Ausgabe löschen
strLineBuffer = ""
'Spaltenzähler für jede Eingabezeile neu initialisieren
intColCnt = 1
'Wenn die eingelesene Zeile leer ist, das Einlesen der Datei beenden
If IsEmptyLine(arrInLine) Then Exit Do
'Alle Spalten-Mappings verarbeiten
For intMapCnt = 0 To UBound(arrMappings(0))
'Quell- und Zielspalte ermitteln
intSrcCol = arrMappings(0)(intMapCnt) - 1
intDstCol = arrMappings(1)(intMapCnt) - 1
'Falls notwendig, den Zeilenpuffer bis zur
'ermittelten Zielspalte mit Leerzellen auffüllen
For intCnt = intColCnt To intDstCol
strLineBuffer = strLineBuffer & strOutDelimiter
Next
'Falls in die Zielspalte bereits etwas eingetragen wurde,
'ein Leerzeichen an den Zeilenpuffer anhängen
If intColCnt > intDstCol And _
arrInLine(intSrcCol) <> "" And _
Len(strLineBuffer) > 0 And _
Right(strLineBuffer, 1) <> strOutDelimiter Then
strLineBuffer = strLineBuffer & " "
End If
'Jetzt den Spaltenwert in den Zeilenpuffer übertragen
strLineBuffer = strLineBuffer & arrInLine(intSrcCol)
'Spaltenzähler auf die Nummer der Spalte setzen,
'die nach der gerade beschriebenen Spalte kommt
intColCnt = intDstCol + 1
Next
'Falls notwendig, den Zeilenpuffer bis zur
'vorgegebenen Endspalte mit Leerzellen auffüllen
For intCnt = intColCnt To intOutTotalCols - 1
strLineBuffer = strLineBuffer & strOutDelimiter
Next
'Zeilenpuffer anhand des Trennzeichens zerteilen und in Array speichern
arrOutLine = Split(strLineBuffer, strOutDelimiter)
'Aus dem Inhalt der Landesspalte einen Ländercode erzeugen
'und ein Flag setzen, ob es sich um einen deutschen oder
'einen ausländischen Kunden handelt
arrOutLine(intOutCountryCodeCol - 1) = CountryCode(arrOutLine(intOutCountryCodeCol - 1))
strCountryCode = arrOutLine(intOutCountryCodeCol - 1)
bolIsGermanCustomer = (StrComp(strCountryCode, "DE", vbTextCompare) = 0)
'Dafür sorgen, dass in der Spalte für Postleitzahlen
'immer die im jeweiligen Land gültige Anzahl Ziffern steht
intPostCodeLength = PostCodeLength(strCountryCode)
arrOutLine(intOutPostCodeCol - 1) = Right(String(intPostCodeLength, "0") & arrOutLine(intOutPostCodeCol - 1), intPostCodeLength)
'In die Spalte mit dem Adresstyp den Wert "HOUSE" schreiben
arrOutLine(intOutAdrTypeCol - 1) = "HOUSE"
'Das Array wieder zu einem String wandeln
strLineBuffer = Join(arrOutLine, strOutDelimiter)
'Den Zeilenpuffer nur in die Ausgabedatei schreiben,
'wenn die Namensspalte nicht leer ist
'In diesem Fall auch den Kopf eines neuen Datensatzes
'in die Auftragsliste schreiben
If arrOutLine(intOutCustomerCol - 1) <> "" Then
'Jetzt anhand des oben gesetzten Flags entscheiden, in welche
'der beiden Ausgabedateien der Zeilenpuffer geschrieben wird
If bolIsGermanCustomer Then
objOutStreamDE.WriteLine(strLineBuffer)
Else
objOutStreamFC.WriteLine(strLineBuffer)
End If
'Jetzt die Einträge in die Auftragsliste schreiben
'Vor dem ersten Datensatz keine Leerzeilen schreiben
If objOrdersStream.Line > 1 Then objOrdersStream.WriteLine(vbNewLine)
'Kundendaten schreiben
objOrdersStream.WriteLine("Der Kunde:")
objOrdersStream.WriteLine(arrOutLine(intOutCustomerCol - 1))
If arrOutLine(intOutAddOnCol - 1) <> "" Then
objOrdersStream.WriteLine(arrOutLine(intOutAddOnCol - 1))
End If
objOrdersStream.WriteLine(arrOutLine(intOutStreetCol - 1))
objOrdersStream.WriteLine(arrOutLine(intOutPostCodeCol - 1) & " " & arrOutLine(intOutTownCol - 1))
objOrdersStream.WriteLine(CountryName(arrOutLine(intOutCountryCodeCol - 1)))
objOrdersStream.WriteLine("")
objOrdersStream.WriteLine("hat folgende Artikel bestellt:")
'Artikeldaten nur schreiben, wenn der aktuelle Datensatz
'in der Eingabedatei nicht aus mehreren Zeilen besteht.
'Es handelt sich also um eine Bestellung mit nur einem Artikel
If arrInLine(arrMappings(2)(intArtNameCol) - 1) <> "" Then
objOrdersStream.WriteLine(arrInLine(arrMappings(2)(intQuantityCol) - 1) & _
" x " & _
arrInLine(arrMappings(2)(intArtNameCol) - 1))
End If
Else
'Hier werden die Artikeldaten einer Bestellung,
'die aus mehreren Artikeln besteht, geschrieben
objOrdersStream.WriteLine(arrInLine(arrMappings(2)(intQuantityCol) - 1) & _
" x " & _
arrInLine(arrMappings(2)(intArtNameCol) - 1))
End If
'Speicher der Zeilen-Arrays freigeben
Erase arrInLine
Erase arrOutLine
Loop
'Eingabedatei schließen
objInStream.Close
End Sub
Sub ShowOrders()
Dim strLine, strOrderData, intCntEmptyLines
Dim bolIsDataSetComplete
intCntEmptyLines = 0
strOrderData = ""
bolIsDataSetComplete = False
Do While Not objOrdersStream.AtEndOfStream
strLine = objOrdersStream.ReadLine
If strLine = "" Then intCntEmptyLines = intCntEmptyLines + 1
If intCntEmptyLines <> 2 Then
If strLine <> "" Then
strOrderData = strOrderData & strLine & vbNewLine
ElseIf strOrderData <> "" Then
strOrderData = strOrderData & strLine & vbNewLine
Else
intCntEmptyLines = 0
End If
If objOrdersStream.AtEndOfStream Then bolIsDataSetComplete = True
Else
bolIsDataSetComplete = True
End If
If bolIsDataSetComplete Then
MsgBox strOrderData, vbInformation + vbOKOnly + vbDefaultButton1, WScript.ScriptName
intCntEmptyLines = 0
strOrderData = ""
bolIsDataSetComplete = False
End If
Loop
End Sub
Function FileExists(strFile)
If objFSO.FileExists(strFile) Then
FileExists = True
Else
MsgBox "Die Datei" & vbNewLine & _
strFile & vbNewLine & _
"existiert nicht!", _
vbCritical + vbOKOnly + vbDefaultButton1, _
WScript.ScriptName
FileExists = False
End If
End Function
Function InitOutFile(strOutFile)
Dim objInStream, objOutStream, strFirstTwoLines
'Ausgabedatei zum Lesen öffnen und die ersten zwei Zeilen auslesen
Set objInStream = objFSO.OpenTextFile(strOutFile, ForReading, false)
strFirstTwoLines = objInStream.ReadLine & vbNewLine & _
objInStream.ReadLine & vbNewLine
objInStream.Close
'Ausgabedatei zum Schreiben öffnen und die ersten zwei Zeilen schreiben
Set objOutStream = objFSO.OpenTextFile(strOutFile, ForWriting, true)
objOutStream.Write(strFirstTwoLines)
Set InitOutFile = objOutStream
End Function
Function UnQuote(strString)
Dim strResult
strResult = Trim(strString)
If Left(strResult, 1) & Right(strResult, 1) = """""" Then
strResult = Mid(strResult, 2, Len(strResult) - 2)
End If
UnQuote = strResult
End Function
Function IsEmptyLine(arrLine)
Dim intCnt
For intCnt = 0 To UBound(arrLine)
If arrLine(intCnt) <> "" Then Exit For
Next
IsEmptyLine = (intCnt > UBound(arrLine))
End Function
Function CountryCode(strCountryName)
Dim intCnt
CountryCode = ""
For intCnt = 0 To UBound(arrCountryMappings(0))
If StrComp(arrCountryMappings(0)(intCnt), strCountryName, vbTextCompare) = 0 Then
CountryCode = arrCountryMappings(1)(intCnt)
Exit For
End If
Next
End Function
Function CountryName(strCountryCode)
Dim intCnt
CountryName = ""
For intCnt = 0 To UBound(arrCountryCodeMappings(0))
If StrComp(arrCountryCodeMappings(0)(intCnt), strCountryCode, vbTextCompare) = 0 Then
CountryName = arrCountryCodeMappings(1)(intCnt)
Exit For
End If
Next
End Function
Function PostCodeLength(strCountryCode)
Dim intCnt
PostCodeLength = 0
For intCnt = 0 To UBound(arrCountryCodeMappings(0))
If StrComp(arrCountryCodeMappings(0)(intCnt), strCountryCode, vbTextCompare) = 0 Then
PostCodeLength = arrCountryCodeMappings(2)(intCnt)
Exit For
End If
Next
End Function
Gruß
Friemler
Hallo Knut,
ich habe das Script oben nochmals aktualisiert. Es kann jetzt mit Eingabedateien umgehen, bei denen die Spaltenwerte in Anführungszeichen eingeschlossen sind.Deine oben beschriebenen Fehler sollten damit eigentlich alle verschwunden sein.
Zu Deiner Frage nach dem Zusammenfassen der Bestellungen eines Kunden zu einem Eintrag in der Auftragsliste: Das wird mir zu aufwendig. Ich müsste das komplette Script neu schreiben. In der derzeitigen Version stelle ich ja nur einen Datensatz zusammen und schreibe ihn dann in die Ausgabedateien. Um Deinen Wunsch zu erfüllen, müsste ich bei jedem Datensatz zunächst nachsehen, ob es bereits einen Datensatz des selben Kunden gibt, wenn ja diesen ändern, den neuen Datensatz anhängen...
Wenn Du in die Richtung willst, deine Bestellungen zu verwalten, solltest Du Dich nach professionellen Lösungen umsehen, das sprengt dann doch den Rahmen einer Forumshilfe.
Ein möglicher Workaround für Dich: Du kannst die
Wenn es noch weitere Probleme mit dem Script gibt, die durch das Format oder die Art der Eingabedaten verursacht werden, kannst Du Dich gerne weiterhin melden.
Gruß
Friemler
ich habe das Script oben nochmals aktualisiert. Es kann jetzt mit Eingabedateien umgehen, bei denen die Spaltenwerte in Anführungszeichen eingeschlossen sind.Deine oben beschriebenen Fehler sollten damit eigentlich alle verschwunden sein.
Zu Deiner Frage nach dem Zusammenfassen der Bestellungen eines Kunden zu einem Eintrag in der Auftragsliste: Das wird mir zu aufwendig. Ich müsste das komplette Script neu schreiben. In der derzeitigen Version stelle ich ja nur einen Datensatz zusammen und schreibe ihn dann in die Ausgabedateien. Um Deinen Wunsch zu erfüllen, müsste ich bei jedem Datensatz zunächst nachsehen, ob es bereits einen Datensatz des selben Kunden gibt, wenn ja diesen ändern, den neuen Datensatz anhängen...
Wenn Du in die Richtung willst, deine Bestellungen zu verwalten, solltest Du Dich nach professionellen Lösungen umsehen, das sprengt dann doch den Rahmen einer Forumshilfe.
Ein möglicher Workaround für Dich: Du kannst die
DPAG.csv
bzw. DPAG Ausland.csv
in Excel öffnen, nach der Namens-Spalte sortieren und somit doppelte Einträge finden.Wenn es noch weitere Probleme mit dem Script gibt, die durch das Format oder die Art der Eingabedaten verursacht werden, kannst Du Dich gerne weiterhin melden.
Gruß
Friemler
Ja, das ist ein möglicher Workaround. Aber das funktioniert nur wie gewünscht, wenn die beiden Einträge direkt aufeinander folgend in der EB.csv stehen. Wenn ein Kunde also am gleichen Tag mit zeitlichem Abstand zwei Bestellungen tätigt und in dieser Zeit noch andere Kunden bestellt haben, musst Du den zweiten Eintrag unter den ersten verschieben.
Gruß
Friemler
Gruß
Friemler