CSV Merge - zwei Dateien zusammenfügen

  • Hallo Zusammen,

    bei einer Änderung an einer Umfrage mit dem Tool LimeSurvey (Hier mal der alte Thread "https://autoit.de/thread/87749-limesurvey-remote-api-json/"), bin ich auf ein komisches Problem beim Zusammenfügen von zwei CSV Dateien gekommen.

    Das Problem tritt nur auf, wenn in einem Freitextfeld Zeilenumbrüche gesetzt wurden.

    Ich lese beide CSV in ein Array und dort sehe ich schon, dass im Array alles verschoben ist.

    Jede Datei hat gleich viele Zeilen, diese möchte ich zusammenfügen, das heißt, am Ende von Zeile 1 aus Datei 1 soll der Text von Zeile 1 aus Datei 2 usw.

    Ich denke der Aufruf von _FileReadToArray ist noch nicht korrekt, habe da aber mit den Parametern noch keine Lösung zu Stande gebracht.

    Hier mal ein Array Display, w man sehen, kann, dass es einen Zeilenumbruch gibt.

    Hat jemand eine Idee?

    Danke

    Gruß Marcel

  • Naja, um die Zeilenumbrüche zu korrigieren, würde ich an deiner Stelle von hinten das Array durchgehen und folgendes in jeder Zeile machen:

    1. Prüfen ob Stringsplit mit dem Delimiter ; die erwartete Anzahl zurück gibt
      1. wenn nicht: Diese Zeile an die vorherige incl. einem @CRLF (grade unsicher ob das geht, sonst Leerzeichen verwenden) davor hinzufügen. Danach diese Zeile löschen
      2. wenn ja: nächste Zeile
    2. Am Ende wieder prüfen ob das Array nun passt

    Edit: Also quasi so (ungeprüft) :

    Edit2: Den Trenner mal mit eingebaut, das er übergeben werden muss, um flexibler zu sein.

    6 Mal editiert, zuletzt von Moombas (13. März 2023 um 15:55)

  • Zeilenumbrüche in Werten sind bei CSV erlaubt, wenn der Wert in Anführungszeichen steht.
    _FileReadToArray() kann dies nicht (und behauptet ja auch nirgends das csv-Format zu unterstützen).

    Daher gibt es spezielle Funktionen zum Einlesen von CSV-Daten, welche auch mit soetwas klarkommen:
    >>CSV-UDF<<

  • Hi Marcel ( gmmg),

    du hast uns zwei CSV Dateien zu Verfügung gestellt, welche TAB als Trennzeichen haben, nicht wie in deinem Beispiel Screenshot ; (Semikolon). Auch sind die Spalten nicht mit ";" (Anführungszeichen) getrennt 😒 .

    Abgesehen davon sollte der Ansatz/der Vorschlag von Moombas ganz gut funktionieren. Noch habe ich keine Zeit zum Test, doch dazu komme ich später hoffentlich.

    Viele Grüße
    Sven

    Update: Die UDF von AspirinJunkie macht es dir leicht, deine Daten korrekt einzulesen. Das zusammenfügen schaffst du dann sicherlich auch gut 😀🤞 .

  • Ok, ich bin jetzt nur von den Screenshots ausgegangen und habe oben mal einen funktionierenden Beispielcode gepostet.

    Bei TAB getrennter Liste, bin ich jedoch raus, da ich damit noch nicht gearbeitet habe, sorry.

    Ist das Trennzeichen Semikolon UND die Anführungszeichen (wie im Screenshot) oder nur Semikolon?

    Du müsstest das dann halt in meinem Code abändern.

  • Bei deinen Dateien die du zuletzt hochgeladen hast stimmt etwas noch nicht.
    In der einen Datei ist ein Header - in der anderen nicht.
    Ich habe mich daher mal an die ursprünglichen @Tab-getrennten Daten gehalten und folgendes gebastelt:

    Edit: Und wenn du deinen alten, rein zeilenbasierten Ansatz weiterverfolgen willst, könntest du das Einlesen der Datei folgendermaßen gestalten damit dir die Zeilenumbrüche in den Werten nicht mehr wehtun:

    AutoIt
    #include <Array.au3>
    
    $aCSV1 = StringRegExp(FileRead('results-0.csv'), '(?m)^(?>"(?>[^"]++|"")*+"|[^"\v]*)*+$', 3)
    
    _ArrayDisplay($aCSV1)

    Einmal editiert, zuletzt von AspirinJunkie (13. März 2023 um 16:25)

  • Hallo AspirinJunkie,

    ich habe jetzt mal die "parseCSV" Version genommen und auf Semikolon "; "umgeschrieben. Sieht erstmal ganz gut aus.

    Eins ist mir noch aufgefallen. Bei einigen Datensätzen ist noch ein Hochkomma " im Merged drin.

    Anbei nochmal die Dateien mit diesem einen Datensatz zum testen.

    Könnte man denn auch wieder die Texttrennzeichen "" mit in die Merge einfügen?

    Ich hatte auch noch eine Fehlerabfrage im Ursprünglichen Script. Wenn die CSV leer ist, soll nur der FileHeader geschrieben werden. Gibt es bei der parseCSV auch eine Fehlerrückgabe?

    $fileHeader = '"id";"submitdate";"lastpage";"startlanguage";"seed";"token";"startdate";"datestamp";"refurl";"G01Q01";"G01Q02";"G01Q03";"G01Q04";"firstname";"lastname";"email";"attribute_1";"attribute_2"'

    Vielen Dank erstmal an Alle, die sich hier beteiligt haben :)

    Gruß gmmg

  • Eins ist mir noch aufgefallen. Bei einigen Datensätzen ist noch ein Hochkomma " im Merged drin.

    Wie ich sagte, sind Zeilenumbrüchen innerhalb von Einzelwerten in csv nur dann erlaubt, wenn diese Werte in Hochkomma eingeschlossen werden.
    Die Hochkomma müssen also zwangsläufig erscheinen wenn du Werte schreiben willst, welche Zeilenumbrüche enthalten.

    Könnte man denn auch wieder die Texttrennzeichen "" mit in die Merge einfügen?

    Nicht mit der _Array2CSV() bisher. Aktuell habe ich eine umfangreichere UDF in Arbeit, welche auch diese Funktionalitäten hier mit beinhaltet. Dort wird das dann mit drin sein als Switch.

    Musst dir hierfür also was eigenes schreiben, was aber kein großes Problem ist, wenn du das 2D-Array schon vorliegen hast.

  • Ahh OK.

    Ich habe eben mal in dem FileWrite Abschnitt den Parameter in '";"' geändert. Hochkommas sind da.

    FileWrite("merged.csv", _Array2CSV($aMerged, Default, '";"'))

    Ich lasse aber am Mittwoch erstmal die Kollegen drüberschauen, ob die so erstellte CSV so verarbeitet werden kann.

    Ein herzliches Danke :)

    Gruß gmmg

  • Also abgesehen davon, dass AspirinJunkie durch seine komfortable UDF 👍 und die Beispiele bereits einen Lösungsweg aufgezeigt hat, gehe ich mit folgendem kleinen Skript ins Rennen 😅 :

    📂 Testdaten:

    demo-file-1.csv
    demo-file-2.csv

    💡 Hinweis: Es ist zu beachten, dass nur das spezielle Problem (CSV merge) bzw. die Anforderung aus dem 1. Beitrag damit umgesetzt werden kann. Also Voraussetzung zwei CSV-Dateien mit ; (Semikolon) als Spaltentrenner und Spaltenwerte sind in " (Anführungszeichen) eingeschlossen => "Text1";"Text2". Des Weiteren wird auch "nur" der reine Text der CSV-Dateien in einer Ziel-CSV kopiert (mit den mehrzeiligen CSV-Spaltenwerten). Somit ist das Ergebnis unverändert (es bleibt der jeweilige mehrzeiliger Spaltenwert ).

    Danke an AspirinJunkie für das RegEx pattern, so musste ich mir das nicht selbst zusammenbauen 🤝 .

    Mein Fazit und Empfehlung an dich gmmg : Nutze die UDF, denn damit bist du flexibler, wenn sich der CSV-Aufbau verändern sollte. Falls nicht, reicht auch mein "Wurf" dazu aus 😅 .

    Viele Grüße
    Sven

  • Ich habe eben mal in dem FileWrite Abschnitt den Parameter in '";"' geändert. Hochkommas sind da.


    FileWrite("merged.csv", _Array2CSV($aMerged, Default, '";"'))

    Ne das wird so nicht funktionieren. Zumindest nicht, wenn du Werte mit Zeilenumbrüchen oder Anführungszeichen hast.
    Und in deinem Beispiel war dies so.
    Denn auf die Art hättest du doppelte Anführungszeichen am Wertanfang und das wäre nicht csv-konform.

    Im Grunde ist es nicht viel Code um deinen String wie von dir gewollt zusammenzubauen

    SOLVE-SMART
    Schöne und womöglich bessere Lösung, da einfacher zu verstehen anstatt sich wie bei mir durch alle Spalten einzeln kämpfen zu müssen. :thumbup:

  • SOLVE-SMART
    Schöne und womöglich bessere Lösung, da einfacher zu verstehen anstatt sich wie bei mir durch alle Spalten einzeln kämpfen zu müssen. 👍

    Danke für die Blumen 🌻😀 . Wenn es konkret um CSV handling geht, ist man mit deiner UDF trotzdem besser aufgehoben.
    Was mir allerdings auch auffällt, dass du wenn du erklärst/dein Code beschreibst bzw. kommentierst, dass du dies in Deutsch tust. Das sollte ich mir hier im deutschen Forum auch angewöhnen 😅 .

    Viele Grüße
    Sven

  • Moombas, Trennzeichn ist Semikolon. In den Anführungszeichen steht dann der entsprechende Wert.

    Falls ich morgen nicht gleich Antworten sollte, habe kleine OP :)

    Generell ist mir das klar aber wenn zwischen den "" ein ; vorkommt, haut das mit stringsplit nicht hin, daher empfehle ich in diesem Fall ";" als kompletten Trenner zu nehmen, um auf Nummer sicher zu gehen.

  • gmmg

    Vorab GUTE BESSERUNG

    Ich habe mich - so ein Zufall - auch ein wenig mit csv Datensätzen beschäftigen müssen.

    Ich habe festgestellt dass Notepad ++ MIT eingestellter OPTION ALLE Zeichen anzeigen eine gute Grundlage fürein Ansehen der Strings ist.

    Bevor man etwas an den Datensätzen macht ev. alle Zeichen entfernen - die stören.

    Als Besispiel DU hast CR mitten im Datensatz? Nimm den letzten CR den Du behalten willst, (von rechts) ersetze diesen durch ein extrem seltenes ungebräuchliches Zeichen. Schmeiss dann alle cr aus dem String und wandle dann das letzte wieder um. Klingt ein wenig umständlich, aber geht fix so habe ich Ordnung in die CSvs gebracht.

    LG

    Peter

    Hinweise auf Suchmaschinen finde ich überflüssig - wer fragt hat es nicht gefunden oder nicht verstanden. Die Antwort gibt sich oftmals schneller als der Hinweis auf Dr. Goggle & Co.

    Ab 19-10-22 ergänzt um:

    Die Welt wird nicht bedroht von den Menschen, die böse sind, sondern von denen, die das Böse zulassen. (Albert Einstein)