none
Datei in Powershell einlesen, verändern und exportieren RRS feed

  • Frage

  • Guten Abend,

    ich habe ein Problem, welches ich momentan nicht gelöst bekomme. Es wird täglich eine Cab-Datei vom Server abgeholt, diese soll in Powershell so aufbereitet werden, dass ich diese in Access besser einbinden kann. Die Datei ändert sich vom Format her nicht, es sind lediglich andere Werte hinterlegt. 

    So sieht die Datei aus:

    02 15
       02150100 00051 0000 NO 90901             90901 3029335025            00 090001001
       02150608 00000 0000 DC                       4003 1520528618            00      4005

    Ich muss die Datei wie folgt aufbereiten:

       - 1. Zeile entfernen (das bekomme ich mit einer Pipe-Funktion und dem Skip-Befehl bereits hin).

    $Input = "C:/xxx"
    $Output = "C:/yyy"
    get-content $Input | select -skip 1 |Out-File -Path $Output -Append
    
    - ersten 4 Zeichen entfernen

    - zwischen den Zahlen / Zeichen jeweils ein Semikolon setzen, damit Access die einzelnen Tabellenspalten erkennt. (oder geht es auch anders?)

    LG


    Montag, 25. Februar 2019 20:11

Antworten

  • Hallo,

    also wenn die Lücken nur in der Spalte 5 auftreten könnte man diese über folgenden Schnellschuss lösen. Das kann man mit Sicherheit noch schöner lösen, aber da fehlt mir im Moment die Zeit mich länger damit zu beschäftigen.

    $LineRAW = '  02150100 00051 0000 NO 90901             90901 3029335025            00 090001001'
    $LineRAW
    $LineAccess = ($LineRAW.Trim() -replace '\s{2,}',' ').Split(' ')
    If ($LineAccess.Count -eq 8) {
        $LineAccess[3] = $LineAccess[3] + ';'
        $LineAccess = $LineAccess -join ';'
    } else {
        $LineAccess = $LineAccess -join ';'
    }
    $LineAccess
    
    
    $LineAccess
    $LineRAW = '  02130608 00000 0000 DC                  4003 1520528618                 00      4005'
    $LineRAW
    $LineAccess = ($LineRAW.Trim() -replace '\s{2,}',' ').Split(' ')
    If ($LineAccess.Count -eq 8) {
        $LineAccess[3] = $LineAccess[3] + ';'
        $LineAccess = $LineAccess -join ';'
    } else {
        $LineAccess = $LineAccess -join ';'
    }
    $LineAccess

    Ausgegeben wird dann:

    02150100;00051;0000;NO;90901;90901;3029335025;00;090001001

    bzw.

    02130608;00000;0000;DC;;4003;1520528618;00;4005

    Im zweiten Fall wird also ein zusaetzliches >;< eingefuegt.

    Beste Gruesse
    brima



    Dienstag, 26. Februar 2019 14:42

Alle Antworten

  • Hallo Bianca, das hört sich nach einem lösbaren Problem an, aber es fehlen so ziemlich alle wichtigen Informationen.
    Lies bitte erstmal diesen Post LINK ,pass deinen Beitrag entsprechend an und dann schauen wir mal. :)

    Grüße, Denniver


    Blog: http://www.bytecookie.de

    Powershell Code Manager: Link
    (u.a. Codesnippets verwalten + komplexe Scripte graphisch darstellen)

    Hilf mit und markiere hilfreiche Beiträge mit dem "Abstimmen"-Button (links) und Beiträge die eine Frage von dir beantwortet haben, als "Antwort" (unten).
    Warum das Ganze? Hier gibts die Antwort.

    Montag, 25. Februar 2019 21:00
    Moderator
  • Hallo Bianca,

    hier ein Beispiel wie Du die Zeilen ändern kannst.

    PS U:\> $LineRAW = '  02150100 00051 0000 NO 90901             90901 3029335025            00 090001001'
    PS U:\> $LineRAW
      02150100 00051 0000 NO 90901             90901 3029335025            00 090001001
    PS U:\> $LineAccess = ($LineRAW.Trim() -replace '\s{2,}',' ').Split(' ') -join ';'
    PS U:\> $LineAccess
    02150100;00051;0000;NO;90901;90901;3029335025;00;090001001

    Das sollte Dir schon mal weiterhelden, durch den Trim werdendie Leerzeichen am Anfang abgeschnitten, der Replace ersetzt wenn mehr als 1 Leerzeichen (\s{2,} durch ein Leerzeichen, der Split teil das ganze dann an den Leerzeichen und der Join baut das Ganze mit >;< dazwischen wieder zusammen.

    Beste Gruesse
    brima


    Dienstag, 26. Februar 2019 10:41
  • Hallo brima,

    erstmal danke für deine Hilfe! Die Datei sieht jetzt schon wesentlich besser aus. :)

    Ich habe noch das Problem, dass teilweise Felder nicht "richtig" bestückt werden in Access, da der Inhalt leer ist und dann kein zusätzliches Semikolon gesetzt wird durch PS.

    Beispielhaft ist das in Zeile 2 und 3 erkennbar. In Zeile 2 ist die "Spalte" 90901 ausgefüllt. (unterstrichen). Die Spalte wird in Access richtig importiert. In Zeile 3 fehlt dieser Wert, sodass dieser übersprungen wird.

    Hast du da eventuell noch eine Idee zu? 

    02 13
       02130100 00051 0000 NO 90901                     90901 3029335025                               00 090001001
       02130608 00000 0000 DC                            4003 1520528618                               00      4005
       02130609 00000 0000 CJ                            6904 1404                                     00      6904
       02130613 00325 0000 J                             6923 1404                                     00      6923
       02130625 00000 0000 CO     090910               828283 2108                                     00 010001001
       02130626 00021 0000 J                             2206 2102                                     00      2206
       02130626 00000 0000 CO     090910             97259514 9921                                     00 010001002

    Dienstag, 26. Februar 2019 13:56
  • Hallo,

    also wenn die Lücken nur in der Spalte 5 auftreten könnte man diese über folgenden Schnellschuss lösen. Das kann man mit Sicherheit noch schöner lösen, aber da fehlt mir im Moment die Zeit mich länger damit zu beschäftigen.

    $LineRAW = '  02150100 00051 0000 NO 90901             90901 3029335025            00 090001001'
    $LineRAW
    $LineAccess = ($LineRAW.Trim() -replace '\s{2,}',' ').Split(' ')
    If ($LineAccess.Count -eq 8) {
        $LineAccess[3] = $LineAccess[3] + ';'
        $LineAccess = $LineAccess -join ';'
    } else {
        $LineAccess = $LineAccess -join ';'
    }
    $LineAccess
    
    
    $LineAccess
    $LineRAW = '  02130608 00000 0000 DC                  4003 1520528618                 00      4005'
    $LineRAW
    $LineAccess = ($LineRAW.Trim() -replace '\s{2,}',' ').Split(' ')
    If ($LineAccess.Count -eq 8) {
        $LineAccess[3] = $LineAccess[3] + ';'
        $LineAccess = $LineAccess -join ';'
    } else {
        $LineAccess = $LineAccess -join ';'
    }
    $LineAccess

    Ausgegeben wird dann:

    02150100;00051;0000;NO;90901;90901;3029335025;00;090001001

    bzw.

    02130608;00000;0000;DC;;4003;1520528618;00;4005

    Im zweiten Fall wird also ein zusaetzliches >;< eingefuegt.

    Beste Gruesse
    brima



    Dienstag, 26. Februar 2019 14:42
  • Danke <3 Jetzt klappt es.


    Dienstag, 26. Februar 2019 21:03
  • Hallo brima,

    leider habe ich schlechte Neuigkeiten.. :/ Das ganze funktioniert so nicht ganz, wenn ich über Get-Content "URL" die Daten einlese.

    Die Ausgabe entspricht dann folgendem:

    02;13;02130100;00051;0000;NO;90901;90901;3029335025;00;090001001;02130608;00000;0000;DC;4003;1520528618;00;4005;02130609;00000;0000;CJ;6904;1404;00;6904;02130613;00325;0000;J;6923;1404;0
    0;6923;02130625;00000;0000;CO;090910;828283;2108;00;010001001;02130626;00021;0000;J;2206;2102;00;2206;02130626;00000;0000;CO;090910;97259514;9921;00;010001002;02130627;00357;0000;I;5025;
    1732314716;00;5025;02130631;00000;0000;CI;3296;00;3296;02130635;00116;0001;M;090910;22007811;1404;00;010001002;02130636;01007;0003;M;090910;828283;2108;00;010001001;02130636;00000;0000;C
    J;1010;2102;00;1010;02130637;00003;0000;DO;1006;2102;00;097001001;02130638;00000;0000;CI;3203;5114103116;00;3203;02130639;00000;0000;CJ;1010;2102;00;1010;02130641;00004;0000;DO;1006;2102
    ;00;097001001;02130641;00000;0000;CJ;1002;2102;00;1002;02130641;00000;0000;CJ;1003;2102;00;1003;02130643;00000;0000;CJ;1004;2102;00;1004;02130643;00000;0000;CJ;1010;2102;00;1010;02130646
    ;00130;0000;I;6912;5119843993;00;6912;02130648;00000;0000;CJ;2202;2102;00;2202;02130651;00038;0000;I;3230;1713021618;00;3235;02130655;00000;0000;CI;3215;1733871675;00;3215;02130657;00013
    ;0000;NI;2201;5112108068;00;90901;02130657;00000;0000;CJ;1010;.....

    Er trennt nicht richtig nach Spalten, sodass er die If-Anweisung eig komplett ignoriert. Wenn ich die Datei einfach so einlese und nichts dran verändere, entspricht das wieder dem oben genannten Format.

    Man könnte die Einlesung mittels Arrays umsetzen, da die "Spaltengröße" immer identisch ist oder? . z.B. ist das erste Feld immer von 0 - 3, das zweite von 4 - 11, etc.

    Ich bin in dem Bereich nur leider ganz und gar kein Profi..

    LG

    Donnerstag, 28. Februar 2019 07:14
  • Bianca,

    wenn Du hier im Forum Code oder Beispiel-Daten postest, formatier das bitte alles als Code. So werden ungewollte Zeilenumbrüche vermieden und der Code oder die Beispiel-Daten sehen so aus wie im Original.

    Vielleicht postest Du einfach mal die ersten 3 oder 4 Zeilen der Original-Datei und 3 oder 4 Zielen der Datei, wie sie aussehen soll.
    Wenn es mehr unterschiedliche Zielen-"Konfigurationen" gibt, solltest Du natürlich entsprechend mehr Zielen posten.  ;-)


    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''


    • Bearbeitet BOfH-666 Donnerstag, 28. Februar 2019 09:11
    Donnerstag, 28. Februar 2019 09:00
  • Hallo Bianca,

    es sieht so aus dass du die Datei mit deinem Code nicht zeilenweise bearbeitest.

    foreach ($LineRAW in (Get-Content C:\temp\testdaten.txt)) {
        # hier dann der Code für die Aenderung und das Zuruekschreiben
    }

    Beste Gruesse
    brima

    Donnerstag, 28. Februar 2019 11:02
  • Hallo brima,

    es geht in die richtige Richtung. Danke schonmal für deine Bemühungen.

    Nun habe ich das Problem, dass beim auslesen nur die letzte Zeile ausgegeben wird, da das Skript die Zeilen überschreibt. Mein Skript sieht bisher so aus. Den output kriege ich mit Write-Output hin, weiß aber nicht genau, wie ich die erste Zeile dann wieder lösche. Mit einer Select -skip 1 Anweisung funktioniert das glaube ich nicht mehr.

    cls
    $input = Get-Content "C:\Users\wagnerb\Documents\GBDaten\cab"
    
    foreach ($LineRAW in $input)
    {
        $LineAccess = ($LineRAW.Trim() -replace '\s{2,}',' ').Split(' ')
    If ($LineAccess.Count -eq 8) 
        {
            $LineAccess[3] = $LineAccess[3] + ';'
            $LineAccess = $LineAccess -join ';'     
        } 
    else 
        {
            $LineAccess = $LineAccess -join ';' 
        }
    }
    Write-Output $LineAccess > "C:\Users\wagnerb\Documents\GBDaten\Test.csv"

    LG

    Bianca



    • Bearbeitet Bianca21 Freitag, 1. März 2019 12:09
    Freitag, 1. März 2019 08:17
  • Hallo Bianca,

    ist klar, in deinem Code lässt du in der Schleife alle Zeilen bearbeiten, und wenn die damit fertig ist steht in der Variablen die letzte bearbeitete Zeile und die schreibst du dann nach der Schleife zurück.

    Dann ersetze mal deine letzten beiden Zeilen

    }
    Write-Output $LineAccess > "C:\Users\wagnerb\Documents\GBDaten\Test.csv"

    damit

        $LineAccess | Out-File "C:\Users\wagnerb\Documents\GBDaten\Test.csv" -Append
    }

    Du musst dich unbedingt mit den Grundlagen der Programmierung beschäftigen, sonst scheiterst du immer wieder an Kleinigkeiten...

    Beste Gruesse
    brima

    Freitag, 1. März 2019 12:13
  • Dann ersetze mal deine letzten beiden Zeilen

    }
    Write-Output $LineAccess > "C:\Users\wagnerb\Documents\GBDaten\Test.csv"

    damit

        $LineAccess | Out-File "C:\Users\wagnerb\Documents\GBDaten\Test.csv" -Append
    }

    Du musst dich unbedingt mit den Grundlagen der Programmierung beschäftigen, sonst scheiterst du immer wieder an Kleinigkeiten...

    Hmmm ... je nach Größe der resultierenden Datei, ist diese Methode aber nicht gerade effizient. ;-) Besser wäre vermutlich vor das foreach eine Variable zu packen, in der Du erstmal alles sammelst und das dann in einem Rutsch in eine CSV-Datei zu exportieren.

    Die Empfehlung, die Grundlagen von Powershell zu erlernen kann ich nur unterschreiben. Das erspart Dir bestimmt eine Menge verschwendete Zeit und Frustration.


    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Freitag, 1. März 2019 15:33
  • Hallo Olaf,

    sicher geht das effektiver, nur habe ich die Erfahrung gemacht, dass der Lern-Elan sinkt, wenn man gleich mit der optimalen Lösung um die Ecke kommt. :-)

    So kann man dann beim optimieren der ersten Lösung schon mal dazu lernen.

    Beste Gruesse
    brima

    Freitag, 1. März 2019 16:17
  • Du bist ja ein pädagogischer Fuchs!  ;-) :-D

    Nach meiner Erfahrung brennen sich gerade scheinbar einfache Lösungen gern mal unauslöschlich ins Gehirn und sind dann schwer wieder zu korrigieren.

    Schauen wir mal, was Bianca draus macht.  :-)


    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Freitag, 1. März 2019 16:22
  • So. Ich habe jetzt noch ein wenig gebastelt. 

    Mein Skript sieht nun folgendermaßen aus, falls es jemanden interessiert. 

    cls
    #Variablen deklarieren
    $Datei = "C:\Users\BiancaW\Desktop\Arbeit\cab"
    $Datum = Get-Date
    $Meldung = "cab-Datei nicht vorhanden"
    
    #prüfen, ob die Datei cab im  Verzeichnis vorhanden ist. Falls nicht, dies in die Log-Datei schreiben.
    
    if (Test-Path $Datei )
        {
        $input = Get-Content "C:\Users\BiancaW\Desktop\Arbeit\cab*"
        }
    else
    {
    Write-Output $Datum $Meldung >> "C:\Users\BiancaW\Desktop\Arbeit\log.csv"
    }
    
    #Datei Zeilenweise in eine Variable $LineRAW einlesen
    foreach ($LineRAW in $input)
    {
        $LineAccess = ($LineRAW.Trim() -replace '\s{2,}',' ').Split(' ') #die unnötigen Leerzeichen entfernen
    #Wenn das Array $LineAccess 8 Datenätze hat, setze nach dem 3. Wert ein ;
    If ($LineAccess.Count -eq 8) 
        {
            $LineAccess[3] = $LineAccess[3] + ';'
            $LineAccess = $LineAccess -join ';'     
        } 
    #lösche den Datensatz aus dem Array, wenn dieser 5 beträgt
    elseif($LineAccess.Count -eq 2) 
        {
            $LineAccess = $LineAccess | Where-Object {$LineAccess -ne $LineAccess.IsFixedSize(5)} 
        }
    #Setze nach jedem Datensatz im Array ein ;
    else
        {
            $LineAccess = $LineAccess -join ';' 
        }
    #schreibe die Werte nacheinander in eine csv.Datei
    Write-Output $LineAccess >> "C:\Users\BiancaW\Desktop\Arbeit\cab.csv"
    }

    Das Skript prüft nun noch, ob die Datei vorhanden ist. Falls nicht, können wir das nachvollziehen anhand der Log-Datei, die dann geschrieben wird. Außerdem wird die erste Zeile immer gelöscht. Wenn wir mal mehrere cab-Dateien einlesen wollen, kommen wir nicht ins Gehege mit 0213, 0215,etc.

    LG


    • Bearbeitet Bianca21 Dienstag, 5. März 2019 16:34
    Dienstag, 5. März 2019 16:26
  • Bianca,

    wenn ich darf, würd ich gern ein paar Tipps geben.

    Am Anfang legst Du den Dateinamen auf "cab" fest (ohne Endung). Beim Einlesen der Datei mittels Get-Content gibst Du aber "cab*" an (mit Sternchen), was auch Dateien wie "cab.txt", "cab.log", "cab1.txt" oder "cab2.log" usw. mit einsammeln würde. Das würde z.B. auch Deine Ausgabedatei "cab.csv" erneut wieder mit einsammeln, falls sie noch im Ordner liegt.Ist das so gewollt?

    Du gibst für Deine Log-Datei einen Dateinamen mit der Endung ".csv" an, erstellst ab er keine valide CSV-Datei. Bei Doppelklick öffnet sich Excel, kann dann aber mit dem Format nix anfangen. Besser wäre vielleicht die Endung ".log" für eine Log-Datei.

    Kommentare sind zwar eigentlich erwünscht, machen aber nur wirklich Sinn, wo sie Informationen liefern, die nicht sowieso aus dem Code erkennbar sind. Jeder der Powershell kennt und ein Script liest, weiß wie Variablen-Deklarationen aussehen und jeder weiß auch was Test-Path macht. Das Offensichtliche braucht man also nicht unbedingt zu kommentieren - da ist dann ma Weniger Mehr.  ;-)

    Die Variable $Input ist eine von Powershells automatischen Variablen, die man nicht direkt selbst "befüllen" sollte. In Deinem Fall wäre vielleicht $Content oder $Inhalt besser.

    Ich hab mal versucht, Dein Script etwas zu "streamlinen". Schau mal, ob Du davon etwas verwenden kannst.

    $Datei = 'C:\Users\BiancaW\Desktop\Arbeit\cab'
    $Datum = Get-Date -Format 'ddd, dd.MM.yyyy HH:mm:ss'
    $Meldung = 'cab-Datei nicht vorhanden'
    
    if (Test-Path -Path $Datei ) {
        $Content = Get-Content -Path $Datei
    }
    else {
        "$Datum - $Meldung" |
            Out-File -FilePath 'C:\Users\BiancaW\Desktop\Arbeit\AccessInput.log' -Append
    }
    
    $Ergebnis = foreach ($LineRAW in $Content) {
        $LineAccess = $LineRAW.Trim() -Split "\s+" 
        If ($LineAccess.Count -eq 8) {
            $LineAccess[3] += ';'
            $LineAccess -join ';'     
        }
        elseif ($LineAccess.Count -eq 9) {
            $LineAccess -join ';'
        }
    }
    
    $Ergebnis | Out-File -FilePath 'D:\sample\test\leer\cab.csv' -Append


    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''





    • Bearbeitet BOfH-666 Dienstag, 5. März 2019 20:40
    Dienstag, 5. März 2019 20:22
  • Guten Abend BOfH_666,

    danke dir für deine Tipps. Ich werde diese definitiv beherzigen :) Ich habe das Skript kommentiert, da mein Chef das gerne so haben wollte. Ich wollte jetzt noch einbauen, dass am Anfang des Skriptes immer die csv-Datei gelöscht wird. Dann werden die Daten am Ende nicht redundant in Access eingelesen, da evtl. noch Restdaten dort drin sind. 

    Zu der Einlesung mit Get-Content habe ich ausversehen das * drin gelassen, was definitiv so nicht gewollt ist. Aber danke dir nochmal für den Hinweis ;)

    Folgendes habe ich noch hinzugefügt:

    If  (Test-Path -Path $Ausgabe) 
    {
      Remove-Item $Ausgabe
    }

    • Bearbeitet Bianca21 Dienstag, 5. März 2019 22:20
    Dienstag, 5. März 2019 22:03
  • Ich habe das Skript kommentiert, da mein Chef das gerne so haben wollte.
    ...  ;-)  :-D ... einfach meinen Kommentar dem Chef weiterleiten und ihm empfehlen, auch dringend die Grundlagen von Powershell zu erlernen!  :-P

    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Dienstag, 5. März 2019 22:30
  • Hallo BOfH_666,

    ich komme heute aus dem Urlaub zurück und muss feststellen, dass das Skript nicht 100 % so funktioniert, wie ich es gedacht habe. Leider :(

    Zu Beginn hatte ich erst einige Testdaten, die allesamt gleich aufgebaut waren. Nun ist ein Monat vergangen und wir haben natürlich nun auch mehr Daten.

    Das Problem an der Sache ist, dass die "Lücken" nicht immer an der selben Stelle sind, sodass der Count nicht funktioniert und die Semikolons ggf. an die falsche Stelle setzt.

    Folgende Szenarien können auftreten:

    1. Der 4. Block fehlt.

    2. Der 5. Block fehlt

    3. Der 7. Block fehlt

    4. Kein Block fehlt

    1                 2         3     4   5                    6         7                                        8      9   
    03111021 00107 0000     9994                      9994 5113739801                       00 038001001
    03111021 00000 0000 CJ                            4001 6003                                    00      4001
    03110806 00019 0001 M      090910            067351579                                  00 010001002
    03110805 00000 0000 CI     090910                 6903 5119837112                      00      6903

    Jeder Block hat eine gewisse Länge, die sich wiederum nie verändert. Wahrscheinlich muss darüber gegangen werden. Ich habe bereits überlegt, eine If-Anweisung zu erstellen, falls der 4. Block nicht aus Buchstaben besteht, das Semikolon an eine andere Stelle zu setzen. Leider klappt das nicht so wirklich.

    LG


    Wagner










    • Bearbeitet Bianca21 Montag, 25. März 2019 14:34
    Montag, 25. März 2019 13:53
  • ich komme heute aus dem Urlaub zurück und muss feststellen, dass das Skript nicht 100 % so funktioniert, wie ich es gedacht habe. Leider :(

    Dann war der ganze schöne Urlaub ja quasi umsonst ... :-O ;-)

    Das Problem an der Sache ist, dass die "Lücken" nicht immer an der selben Stelle sind, sodass der Count nicht funktioniert und die Semikolons ggf. an die falsche Stelle setzt.

    Hatten wir eigentlich schon mal geklärt, ob es nicht möglich wäre, die Quelldatei irgendwie CSV-Standard-konform zu bekommen? Wo stammt die Datei her? Könnte man eventuell diesen Process einfacher beeinflussen, anstatt ständig den möglichen neuen Änderungen hinterherzuscripten?

    Jeder Block hat eine gewisse Länge, die sich wiederum nie verändert. Wahrscheinlich muss darüber gegangen werden. Ich habe bereits überlegt, eine If-Anweisung zu erstellen, falls der 4. Block nicht aus Buchstaben besteht, das Semikolon an eine andere Stelle zu setzen. Leider klappt das nicht so wirklich.


    ;-) ... eine Fehlermeldung wie "Leider kappt das nicht so wirklich" hab ich auf einem meiner Systeme noch nie gesehen. :-) Wie Deniver schon mal ganz oben geschrieben hatte: Es fehlen so ziemlich alle wichtigen Informationen.

    Was heißt denn "es klappt nicht"? Wie dürfen/können die einzelnen Blöcke aussehen? Was hast Du probiert? (Wo ist Dein Code?) Was ist das Ergebnis?

    Für eine Lösung musst Du quasi Regeln definieren, wie die Datei oder die Zeile aussehen muss und wie Du dann jeweils reagieren willst.
    Du könntest auch mit regulären Ausdrücken arbeiten, um die Struktur der Zeilen zu zerlegen. Mit gerade mal 4 Beispiel-Zeilen ist es schwer, eine Struktur zu erkennen und daraus einen Algorithmus abzuleiten.


    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Montag, 25. März 2019 15:34

  • 1                 2         3     4   5                    6         7                                        8      9   
    03111021 00107 0000     9994                      9994 5113739801                       00 038001001
    03111021 00000 0000 CJ                            4001 6003                                    00      4001
    03110806 00019 0001 M      090910            067351579                                  00 010001002
    03110805 00000 0000 CI     090910                 6903 5119837112                      00      6903

    Jeder Block hat eine gewisse Länge, die sich wiederum nie verändert. Wahrscheinlich muss darüber gegangen werden.

    #################

    Also aus den 4 Zeilen geht schon mal hervor, das die 5. Spalte 4 Stellen hat oder auch 6 usw.

    Von daher macht es keinen Sinn sich näher damit zu beschäftigen, sondern es wäre dann schon sinnvoller mit den original Daten zu arbeiten, sonst treffen wir uns hier alle paar Tage wieder, um eine neue Ausnahme einzubauen. :-)

    ich würde auch empfehlen  nicht hinter her zu basteln, sondern das Probleme an der Quelle anzugehen.

    Beste Grüße
    brima



    • Bearbeitet brima Montag, 25. März 2019 15:52
    Montag, 25. März 2019 15:50

  • 1                 2         3     4   5                    6         7                                        8      9   
    03111021 00107 0000     9994                      9994 5113739801                       00 038001001
    03111021 00000 0000 CJ                            4001 6003                                    00      4001
    03110806 00019 0001 M      090910            067351579                                  00 010001002
    03110805 00000 0000 CI     090910                 6903 5119837112                      00      6903

    Jeder Block hat eine gewisse Länge, die sich wiederum nie verändert. Wahrscheinlich muss darüber gegangen werden.

    #################

    Also aus den 4 Zeilen geht schon mal hervor, das die 5. Spalte 4 Stellen hat oder auch 6 usw.

    Von daher macht es keinen Sinn sich näher damit zu beschäftigen, sondern es wäre dann schon sinnvoller mit den original Daten zu arbeiten, sonst treffen wir uns hier alle paar Tage wieder, um eine neue Ausnahme einzubauen. :-)

    ich würde auch empfehlen  nicht hinter her zu basteln, sondern das Probleme an der Quelle anzugehen.

    Beste Grüße
    brima



    Ja das möchte ich persönlich auch nicht, da das dann auf Dauer doch umständlich wird. Dadurch, dass die Zeilen immer die selbe Anzahl an Zeichen erhalten, egal ob dieser ausgefüllt wird oder nur durch Leerzeichen gefüllt wird, wird es darüber glaube am einfachsten werden. 

    Ich bekomme die Daten jeden Tag von einem FTP-Server bereitgestellt in diesem Format. Ich kann da auch nichts daran ändern, da die Datei automatisch dort abgelegt wird vom System. Ich werde mal weiter googlen, ob es möglich ist, in einem Array die Spaltenbreiten zu definieren. So hat es mir mein Chef als Alternativlösung genannt, bevor ich in den Urlaub gegangen bin. Hatte es aber nicht verfolgt gehabt, da bis dato alles lief.

    Da ich noch in der Ausbildung bin, hab ich mich bisher noch nicht viel mit Powershell und co beschäftigt. Das werde ich definitiv nachholen.

    Die Tabelle ist wie folgt aufgebaut:

    1. Zeichen 4 - 12

    2. Zeichen 13 - 18

    3. Zeichen 19 - 23

    4. Zeichen 24 - 26

    5. Zeichen 27 - 37

    6. Zeichen 38 - 58

    7. Zeichen 59 - 99

    8. Zeichen 100 - 102

    9. Zeichen 103 - 111


    Wagner

    Dienstag, 26. März 2019 06:51
  • Dann war der ganze schöne Urlaub ja quasi umsonst ... :-O ;-)

    -- Ja leider. Zumal ich auch noch andere wichtige Themen derzeit betreuen darf und die Abschlussprüfung auch näher rückt.. :/

    Hatten wir eigentlich schon mal geklärt, ob es nicht möglich wäre, die Quelldatei irgendwie CSV-Standard-konform zu bekommen? Wo stammt die Datei her? Könnte man eventuell diesen Process einfacher beeinflussen, anstatt ständig den möglichen neuen Änderungen hinterherzuscripten?                            

    -- die Quelldatei als solche kann ich nicht standardkonform bekommen, ohne Powershell anwenden zu müssen. Zumindest meines Wissens nach, da ich das Format nicht beeinflussen kann von der Datei. Die Datei stammt von einem FTP-Server, wo wir mithilfe eines Skriptes die Datei bei uns ablegen. Die Datei hat immer das gleiche Format (Spaltendefinition ist die selbe, wird nur ggf. durch Leerzeichen ausgetauscht, wenn kein Inhalt vorhanden ist).

    ;-) ... eine Fehlermeldung wie "Leider kappt das nicht so wirklich" hab ich auf einem meiner Systeme noch nie gesehen. :-) Wie Deniver schon mal ganz oben geschrieben hatte: Es fehlen so ziemlich alle wichtigen Informationen.

    Was heißt denn "es klappt nicht"? Wie dürfen/können die einzelnen Blöcke aussehen? Was hast Du probiert? (Wo ist Dein Code?) Was ist das Ergebnis?

    Für eine Lösung musst Du quasi Regeln definieren, wie die Datei oder die Zeile aussehen muss und wie Du dann jeweils reagieren willst.
    Du könntest auch mit regulären Ausdrücken arbeiten, um die Struktur der Zeilen zu zerlegen. Mit gerade mal 4 Beispiel-Zeilen ist es schwer, eine Struktur zu erkennen und daraus einen Algorithmus abzuleiten.

    -- Ich habe zunächst überlegt, zu definieren, dass geprüft wird, ob der Code (Buchstabenfolge) vorhanden ist, falls nicht, soll dann definiert werden, ob Spalte 4,5,6 fehlt. Ich denke, ich muss grundsätzlich erstmal die Breiten definieren, damit ich Regeln definieren kann.



    Wagner

    Dienstag, 26. März 2019 07:07
  • Hallo,

    so langsam kommen ja nun entscheidende Informationen rüber, wie die Zeilen sind immer gleich lang, es wird mit Leerzeichen aufgefüllt...

    Hier ein sehr einfach gehaltenes Beispiel:

    $Daten  = @('0123 223257 DC 8904563 457',
                '5634        XF 3425463 234',
                '87             342     89 ',
                '2424 434324    4564643    ',
                '4578        DE 3244523 3  ')
    foreach ($RAWLine in $Daten) {
        $Spalte01 = $RAWLine.Substring(0,5).Trim()
        $Spalte02 = $RAWLine.Substring(5,7).Trim()
        $Spalte03 = $RAWLine.Substring(12,3).Trim()
        $Spalte04 = $RAWLine.Substring(15,8).Trim()
        $Spalte05 = $RAWLine.Substring(23,3).Trim()
        $Line = $Spalte01 + ';' + $Spalte02 + ';' + $Spalte03 + ';' + $Spalte04 + ';' + $Spalte05
        $Line
    }
    
    
    
    
    0123;223257;DC;8904563;457
    5634;;XF;3425463;234
    87;;;342;89
    2424;434324;;4564643;
    4578;;DE;3244523;3

    Den Code kannst Du ja dann selber optimieren, wenn du dich näher in die PowerShell einarbeitest. :-)

    Beste Grüße
    brima

     
    Dienstag, 26. März 2019 09:02
  • So jetzt hab ich mir nochmal paar Gedanken gemacht und bin auf folgende Lösung gekommen. Mit meiner Testdatei (die 4 Zeilen) funktioniert das, weil ich jetzt nach der festen Breite gehe.

    cls
    $Datei = 'C:\GBDaten\cab-Datei\cab'
    $Datum = Get-Date -Format 'ddd, dd.MM.yyyy HH:mm:ss'
    $Meldung = 'cab-Datei nicht vorhanden'
    $Ausgabe = 'C:\GBDaten\cab-Datei\cab.csv'
    $Logdatei = 'C:\GBDaten\log-Datei\AccessInput.log'
    
    
    If  (Test-Path -Path $Ausgabe) 
    {
      Remove-Item $Ausgabe
    }
    if (Test-Path -Path $Datei ) 
    {
        $Content = Get-Content -Path $Datei
    }
    else 
    {
        "$Datum - $Meldung" | Out-File -FilePath $Logdatei -Append
    }
    
    $Ergebnis = foreach ($LineRAW in $Content)
     {
            $LineAccess = $LineRAW.Trim() 
            $Spalte1 = $LineRAW.Substring("0","8")
            $Spalte1 = $Spalte1.Insert(8,";")
    
            $Spalte2 = $LineRAW.Substring("9","5")
            $Spalte2 = $Spalte2.Insert(5,";")
    
            $Spalte3 = $LineRAW.Substring("15","4")
            $Spalte3 = $Spalte3.Insert(4,";")
    
            $Spalte4 = $LineRAW.Substring("20","2")
            $Spalte4 = $Spalte4.Insert(2,";")
    
            $Spalte5 = $LineRAW.Substring("23","10")
            $Spalte5 = $Spalte5.Insert(10,";")
    
            $Spalte6 = $LineRAW.Substring("34","20")
            $Spalte6 = $Spalte6.Insert(20,";")
    
            $Spalte7 = $LineRAW.Substring("55","40")
            $Spalte7 = $Spalte7.Insert(40,";")
    
            $Spalte8 = $LineRAW.Substring("96","2")
            $Spalte8 = $Spalte8.Insert(2,";")
    
            $Spalte9 = $LineRAW.Substring("99","9")
          
         $Ergebnis = $Spalte1 + $Spalte2 + $Spalte3 + $Spalte4 + $Spalte5 + $Spalte6 + $Spalte7 + $Spalte8 + $Spalte9 
       
         $Ergebnis | Out-File -FilePath $Ausgabe -Append
          }


    Wagner

    Dienstag, 26. März 2019 09:37
  • Hallo Bianca,

    jo, so sollte es gehen, man kann den Code natürlich noch optimieren ...

    Diese Zeile
    $LineAccess = $LineRAW.Trim()
    mach keinen Sinn weil du die Variable LineAccess nicht verwendest.

    Beste Grüße
    brima

    Dienstag, 26. März 2019 09:58
  • Hallo Bianca,

    jo, so sollte es gehen, man kann den Code natürlich noch optimieren ...

    Diese Zeile
    $LineAccess = $LineRAW.Trim()
    mach keinen Sinn weil du die Variable LineAccess nicht verwendest.

    Beste Grüße
    brima

    Hallo brima,

    ja natürlich macht die keinen Sinn. Die hab ich auch bereits gelöscht :) Danke aber für die großartige Hilfe. Mir ist klar, dass da noch viel Optimierung vorgenommen werden kann, fürs erste bin ich aber erstmal froh, dass es nun klappt ohne zig Ausnahmen einbauen zu müssen.


    Wagner

    Dienstag, 26. März 2019 11:11
  • Die Datei stammt von einem FTP-Server, wo wir mithilfe eines Skriptes die Datei bei uns ablegen. Die Datei hat immer das gleiche Format (Spaltendefinition ist die selbe, wird nur ggf. durch Leerzeichen ausgetauscht, wenn kein Inhalt vorhanden ist).
    Hmmm ... Du machst es uns wirklich nicht so einfach ... Ihr legt die Datei dort mittels eines Scriptes ab? Wie wird diese Datei erzeugt?  Wer erzeugt diese Datei? Nicht vorhandenen Inhalt mit dem gleichen Zeichen zu ersetzten, das den Delimiter darstellt, ist eine zumindest fragwürdige Entscheidung.

    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Dienstag, 26. März 2019 14:45
  • Die Datei stammt von einem FTP-Server, wo wir mithilfe eines Skriptes die Datei bei uns ablegen. Die Datei hat immer das gleiche Format (Spaltendefinition ist die selbe, wird nur ggf. durch Leerzeichen ausgetauscht, wenn kein Inhalt vorhanden ist).

    Hmmm ... Du machst es uns wirklich nicht so einfach ... Ihr legt die Datei dort mittels eines Scriptes ab? Wie wird diese Datei erzeugt?  Wer erzeugt diese Datei? Nicht vorhandenen Inhalt mit dem gleichen Zeichen zu ersetzten, das den Delimiter darstellt, ist eine zumindest fragwürdige Entscheidung.

    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Es tut mir leid :( Die Datei wird automatisch von unserer Telefonanlage erzeugt und in einen Ordner auf dem FTP-Server abgelegt. Von dort aus greifen wir über WinSCP  auf den Server zu und holen die Datei (cab) zu uns an einen bestimmten Ort. Das klappt auch automatisiert wunderbar.

    Das Problem war dann, dass ich diese cab-Datei so formatieren musste, dass ich diese als csv erhalte und in Access importieren kann. Das klappt nun mithilfe des Skriptes auch ohne Probleme.


    Wagner

    Dienstag, 26. März 2019 15:29
  • Diese Informationen hätte ich mir in Deinem ersten Beitrag gewünscht. ;-)

    Wenn man mir diese Aufgabe übertragen hätte, würde ich, unabhängig von meinen Bemühungen, die Datei in einen nutzbaren Zustand zu bekommen, den Hersteller oder den Lieferanten oder den Supporter kontaktieren und versuchen, ihn dazu zu bringen, diese Datei in einem gut nutzbaren, anerkannten Industriestandard zu liefern (CSV). Das brächte vielleicht auch einen Mehrwert für die Zukunft und für andere Kunden.  ... und es würde Dir das Leben erleichtern.  ;-)


    Live long and prosper!

    (79,108,97,102|%{[char]$_})-join''

    Dienstag, 26. März 2019 15:50