Suchen und ersetzen in einer .csv

  • Hallo,

    ich hätte gerne ein Skript, dass diverse Werte in einer .csv (C:\preisliste.csv) in Spalte J einließt und entsprechen mit vorausgewählten Werten die Spalten P und Q füllt. (Also wenn in Spalte J dies steht, dann schreibe in Spalte P das und in Spalte Q jenes...) Das ganze auf alle 46k Datensätze der csv anwenden.

    Beispiel:

    Spalte J Spalte P Spalte Q

    USB-Speicher Speichermedien USB-Sticks

    Hat da vielleicht jemand von euch auf die schnelle etwas zur Hand.

    Das wäre wirklich perfekt.

    Vielen Dank im Vorraus.

  • Hast Du Excel installiert?
    Dann könntest Du die Datei einlesen, die angesprochenen Änderungen durchführen und die Datei wieder als CSV sichern.

  • Hallo,

    ja habe Excel, nur ist es halt nicht eine einzelne Änderung, sondern die Schlüsselbegriffe nach denen gesucht werden und anhand denen die beiden anderen Spalten gefüllt werden sollen, belaufen sich auf über 300.

    Zudem wird die Datei regelmäßig aktualisiert und bekommt täglich neue Datensätze.

    Deshalb wäre es sehr umständlich das von Hand über Excel zu machen ;)

  • Natürlich nicht von Hand. Selbstredend mit der Excel UDF.

  • Achso ok.

    Mir schwebte bis dato zwar eher sowas wie das vor..

    [autoit]

    For $i = 1 To UBound($array) - 1
    $array[$i] = StringReplace($array[$i], " ", " ")

    [/autoit]

    Aber dann werde ich mich morgen früh mal mit Excel UDF beschäftigen.

    Lässt sich das denn irgendwie mit Excel UDF realisieren, ohne dass Excel die Werte so komisch darstellt wie z.B. EANs 8,8877E+11 oder Preise Jun 29?

  • Ich würde die Lösung wählen, die mein Problem am besten löst.
    46K Datensätze und 300 verschiedene Änderungen sind ne Menge Holz.

  • Ja also es würde ausreichen, wenn das Skript hinterher 1 mal am Tag läuft. Ausgeführt werden würde es dann nachts auf dem TS, da kann es dann von mir aus auch 30 min ackern...

    Da ich selbst leider recht wenig Ahnung von Autoit oder auch anderen Programmierungen habe, weiß ich leider auch nicht auf welchem Weg ich mein Problem am besten löse :)

  • Ist die CSV eigentlich die Originaldatei oder ein Export aus einer Datenbank oder einem ERP System?

  • Wär es dann nicht sinnvoller, die Änderungen in der Datenbank durchzuführen?

  • Ja grundsätzlich schon, leider habe ich aber keinen Zugriff auf die Datenbank.

    Wenn jemand auf die schnelle etwas schreiben kann, würde auch 10 Euro für das erste funktionierende Skript bieten, dass hier gepostet wird.

  • Dazu wäre es aber nötig, die jeweiligen Möglichkeiten für [P] und [Q] im Bezug auf [J] zu kennen.

    Es sei denn, du willst bei jedem Datensatz die Eingaben von Hand machen... Pro Eingabe geschätzte 2.5 Sekunden, also 5 Sekunden pro Eintrag...
    5 * 46.000 = 230.000
    ((230.000 / 60) / 60) / 24 = ~2.7 Tage

    :D

  • ... die Schlüsselbegriffe nach denen gesucht werden und anhand denen die beiden anderen Spalten gefüllt werden sollen, belaufen sich auf über 300.


    Passiert bei jedem der 300 Schlüsselbegriffe das selbe in Spalte P und Q (feste Werte oder Formel) oder hängt das Ergebnis in P und Q nicht vom Schlüsselbegriff ab?

    Vielleicht kannst Du ja mal ein Beispiel Deiner Daten posten.

  • So: Hier ein Ansatz (müsstest J, P und Q selber setzen) oben Anfangsdatei und Zieldatei angeben und dann dürfte es durchlaufen (zumindest wenns eine Standard CSV ist (mit ; getrennt und in zeilen))

    Spoiler anzeigen
    [autoit]


    $file=FileOpen("test.txt",0)
    $zielDatei="test2.txt"
    $fileD=FileOpen("test2.txt",BitOR(8,1))
    while 1
    $line=FileReadLine($file)
    if @error then
    ExitLoop
    endif
    $ar=StringSplit($line,";",2)
    if UBound($ar)>16 then
    Switch $ar[9] ;J=9 (10 Buchstabe im Alphabet -1 wegen IndexStart bei 0)
    Case "Was ist J"
    $ar[15]="was ist dann P" ;P=15
    $ar[16]="was ist dann Q" ;Q=16
    Case "Was ist J sonst"
    $ar[15]="was ist dann P" ;P=15
    $ar[16]="was ist dann Q" ;Q=16
    endif
    $string=""
    for $l=0 to UBound($ar)-1 step 1
    $string&=$ar[$l]
    if $l<>UBound($ar)-1 then
    $string&=";"
    endif
    next
    FileWriteLine($fileD,$string)
    WEnd

    [/autoit]

    (und nein, dafür möchte ich keine 10€ :D)

    EDIT: EndIf entfernt; FileReadLine angepasst.
    Das WEnd steht doch in der letzten spalte... (Der Browser verhaut immer die Formatierung mit den Tabs:()

  • und nein, dafür möchte ich keine 10€ :D

    Wäre auch bisschen dreist ;)
    Es ist so nicht lauffähig, da ein WEnd fehlt und ein EndIf zu viel steht.
    Zweitens wird es bei 43000 Zeilen unheimlich langsam sein.
    Das liegt primär, daran, dass du den zweiten Parameter von FileReadLine verwendest und somit explizit Zeilen anspringst (mit jedesmal zurück Auf den Anfang setzen) anstatt einfach Zeile für Zeile die Datei durchzugehen.

  • Hi, danke für die zahlreichen Antworten.

    Code
    sku    stock    currency    price    title    manufacturer    msku    ean    egId    lwg1    availability    weight    width    depth    height
    164291    0    EUR    21. Okt    Belkin USB 2.0 HUB, 1:4, Ultraflach, mit Netzteil, Schwarz    Belkin    F4U040CW    7,22869E+11    84718000    HUBs    K    0.000    0.000    0.000    0.000
    164283    0    EUR    Jun 55    USB-Stick  16GB Silicon Power 720 Bronze/Alu Case    Silicon Power    SP016GBUF2720V1Z    4,7127E+12    85235110    USB-Speicher    K    0.015    0.126    0.083    0.010
    164282    0    EUR    Apr 56    USB-Stick  8GB Silicon Power 720 Bronze/Alu Case    Silicon Power    SP008GBUF2720V1Z    4,7127E+12    85235110    USB-Speicher    K    0.015    0.126    0.083    0.010

    Das ist die Datei, möchte nun in Spalte P und Q Werte haben, die abhängig von Spalte J sind.

    Beispiel anhand der drei Datensätze:
    J=Hubs P=Peripherie Q=Hubs
    J=USB-Speicher P=Speichermedien Q=USB-Sticks

    Also die Werte würde ich natürlich je Schlüsselbegriff händisch zuordnen.

    @ Kanashius vielen Dank. Kann ich jetzt einfach das:

    Code
    Case "Was ist J sonst"
     $ar[15]="was ist dann P" ;P=15
     $ar[16]="was ist dann Q" ;Q=16

    beliebig oft kopieren und die Werte entsprechend einsetzen?

  • Zitat

    @ Kanashius vielen Dank. Kann ich jetzt einfach das:

    Aber klar.

  • So. Ich habs geändert. (Die LeereZeile am Ende deiner Schlüsselwort-datei hat den Fehler ausgelöst)
    (Bei deinen Beispieldaten ging das nur bis 14 Spalten. Die letzten beiden 15&16 sind vermutlich leer. Das musst du dort dann noch anpassen (siehe Kommentar))

    Spoiler anzeigen
    [autoit]

    #include <array.au3>
    $file=FileOpen("pricelist.csv",0)
    $zielDatei="out.txt"
    $fileD=FileOpen($zielDatei,BitOR(8,1))
    $arSWords=_gibSchluesselwoerterAlsArray("schlüsselwörter.txt")
    while 1
    $line=FileReadLine($file)
    if @error then
    ExitLoop
    endif
    $ar=StringSplit($line,";",2)
    ;z.B.: ReDim $ar[Ubound($ar)>16?Ubound($ar):16]
    if UBound($ar)>16 then ;HIER ANPASSEN!!!!!! (nur exsistente Felder zählen)
    for $i=0 to UBound($arSWords)-1 step 1
    if $ar[9]=$arSWords[$i][0] then
    $ar[15]=$arSWords[$i][1]
    $ar[16]=$arSWords[$i][2]
    endif
    next
    endif
    $string=""
    for $l=0 to UBound($ar)-1 step 1
    $string&=$ar[$l]
    if $l<>UBound($ar)-1 then
    $string&=";"
    endif
    next
    FileWriteLine($fileD,$string)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    ;Falls deine Schlüsselworte in einer Datei stehen kannst das auch so machen:
    ;Aufbau der datei:
    ; J1;P1;Q1
    ; J2;P2;Q2
    Func _gibSchluesselwoerterAlsArray($file)
    $data=fileread($file)
    $ar=stringsplit($data,@crlf,2+1)
    local $array[UBound($ar)][3]
    for $i=0 to UBound($ar)-1 step 1
    if $ar[$i]<>"" then
    $tmp=StringSplit($ar[$i],";",2)
    $array[$i][0]=$tmp[0]
    $array[$i][1]=$tmp[1]
    $array[$i][2]=$tmp[2]
    endif
    next
    return $array
    EndFunc

    [/autoit]