Excel Unterschied .xlsx und .csv

  • Ich lese Daten wie z.B. XPathe aus einer Excel-Tabelle. Da nicht auf jedem Client Excel installiert ist, kopiere ich die Excel-Datei für diese in eine csv-Datei und lese dort aus der .csv .


    Hat anfänglich scheinbar funktioniert - nur mit "leichten" Störungen. :ironie:


    Befund: Die Fehler kamen nur bei kurzen XPathen. In der csv werden Anführungsstriche gedoppelt und dazu noch vor und hinter den String eingefügt:



    Fragen an die Spezialisten:

    1. kann ich das beim Schreiben der .csv verhindern?

    2. wenn nicht, wie in AutoIt damit umgehen?

    3. könnte es außer den Anführungsstrichen noch andere Unterschiede zwischen csv und xlsx geben? So werden sinnvollerweise Strings mit ";" auch in Anführungsstriche gesetzt.


    Was ist z.B. wenn in einem XPath ein ";" auftritt (gibt es das?). Da hätte ich übrigens Verständnis dafür, dass der String in Anführungsstriche gesetzt wird.


    Nachgedacht und getestet - vermutlich damit gelöst:

    1. beim Schreiben macht es keinen Sinn das zu verhindern

    2. Ich ersetze '""' durch '====' , dann führende und endende '"' durch '' und dann '====' durch '"'

    3. Gibt es eine automatische Funktion dafür in AutoIt?

  • Wie erstellst Du die CSV-Datei? Verwendest Du Excel's "Speichern unter"?


    CSV steht für Comma/Character Separated Value. Die konkrete Umsetzung ist leider nich ganz genormt.

    Zellen einer Zeile werden durch ein Trennzeichen separiert (Komma oder Semikolon), Texte werden von einfachen oder doppelten Hochkommas begrenzt.
    Enthält nun ein solcher String einen der Begrenzer, dann wird dieser verdoppelt um anzuzeigen, dass das Zeichen kein Begrenzer sondern ein Zeichen des Strings ist.

  • Warum nicht so (reine Theorie, nicht getestet):

    Code
    ;$CSV ist deine eingelesene CSV-Datei
    for $Row = 1 to $Zeilenanzahl_deiner_CSV Step 1
    $aArray = StringSplit($CSV[$Row], ';')
    Next
    UBound($aArray)
    for $Row = 1 to $aArray[0]
    $aArray[$Row] = StringReplace($aArray[$Row], '""', '"')
    Next
  • Ich verwende in allen Skripten die UDF von progandy um eine CSV zu lesen/schreiben: https://www.autoitscript.com/f…indComment&comment=799820

  • Wie erstellst Du die CSV-Datei? Verwendest Du Excel's "Speichern unter"?

    Ja, leider finde ich dort keine Einstellmöglichkeiten z.B. für den Delimiter (gibt es sicher).

    Warum nicht so (reine Theorie, nicht getestet):

    Ungefähr, nur gibt es, wenn " oder ; im Text, noch "klammernde" Anführungsstriche zusätzlich, die beim Lesen aus der Excel-Tabelle nicht dabei sind.

    Ich verwende in allen Skripten die UDF von progandy um eine CSV zu lesen/schreiben: https://www.autoitscript.com/f…indComment&comment=799820

    Wenn ich das gewusst hätte, hätte ich mir viel Zeit sparen können.

    AutoIt
    Func _CsvTrans($sString)
    ; doppelte "" ersetzen durch einen String, der sicher nicht vorkommt, hier !&=$/&%
    Local $sRes = StringStripWS(StringReplace($sString, '""', '!&=$/&%'), 3)
    ; falls vorne und hinten " sind - entfernen
    If StringLeft($sRes, 1) = '"' And StringRight($sRes, 1) = '"' Then $sRes = StringMid($sRes, 2, StringLen($sRes) - 2)
    ; !&=$/&% durch " ersetzen
    Return = StringReplace($sRes, '!&=$/&%', '"')
    EndFunc

    Mein erstes Programm bestand aus ca. 2.000 Lochkarten und nachdem sie mir das erste mal runtergefallen sind, habe ich die letzten beiden der 80 Byte für eine Numerierung benutzt :rofl:

  • Return = StringReplace($sRes, '!&=$/&%', '"')

    Hinter Return muss das = weg...


    Hier noch etwas kürzer:

    AutoIt
    Local $Csv = '"fgfgfg""kklk""jjj"'
    ConsoleWrite('- Original: ' & $Csv & @CRLF)
    ConsoleWrite('> Transcodiert: ' & _CsvTrans($Csv) & @CRLF)
    Func _CsvTrans($sString)
    ; doppelte "" ersetzen durch einen String, der sicher nicht vorkommt, hier !&=$/&%
    Local $sRes = StringStripWS(StringReplace($sString, '""', '!&=$/&%'), 3)
    ; falls vorne und hinten " sind - entfernen und !&=$/&% durch " ersetzen
    Return StringReplace(StringRegExpReplace($sRes, '^"(.+)"$', '\1'), '!&=$/&%', '"')
    EndFunc

    Oder als Einzeiler:

    AutoIt
    ; ...
    Func _CsvTrans($sString)
        Return StringReplace(StringRegExpReplace(StringStripWS(StringReplace($sString, '""', '!&=$/&%'), 3), '^"(.+)"$', '\1'), '!&=$/&%', '"')
    EndFunc
  • Macht diese Zeile auch die "klammernden" Anführungszeichen weg, wenn welche da sind? Und Leerzeichen davor und dahinter?

    Wenn ich die Tiefen von RegEx mal verstehen würde;(

    Mein erstes Programm bestand aus ca. 2.000 Lochkarten und nachdem sie mir das erste mal runtergefallen sind, habe ich die letzten beiden der 80 Byte für eine Numerierung benutzt :rofl:

  • Macht diese Zeile auch die "klammernden" Anführungszeichen weg, wenn welche da sind? Und Leerzeichen davor und dahinter?

    Ausprobieren :/

  • Etwas sehr kompliziert, finde ich. Warum so ein String-Konstrukt? Wie wäre es stattdessen mit z.B. Chr(5), kommt im Text zu 100% nicht vor.

    Ja, damit wird es sicher auch keine Probleme geben.

    AutoIt
    Func _CsvTrans($sString)
    Local Static $sChr5 = Chr(5)
    Return StringReplace(StringRegExpReplace(StringStripWS(StringReplace($sString, '""', $sChr5), 3), '^"(.+)"$', '\1'), $sChr5, '"')
    EndFunc


    Macht diese Zeile auch die "klammernden" Anführungszeichen weg, wenn welche da sind? Und Leerzeichen davor und dahinter?

    Ja und ja...


    0.) Return StringReplace(StringRegExpReplace(StringStripWS(StringReplace($sString, '""', $sChr5), 3), '^"(.+)"$', '\1'), $sChr5, '"')

    1.) .......................................................^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^..................................... ; doppelte Anführungszeichen "" maskieren

    2.) .........................................^^^^^^^^^^^^^^                                     ^^^^................................. ; entfernt Leerzeichen davor und dahinter

    3.) .....................^^^^^^^^^^^^^^^^^^^^                                                       ^^^^^^^^^^^^^^^^^^^.............. ; entfernt "klammernde" Anführungszeichen

    4.) .......^^^^^^^^^^^^^^                                                                                              ^^^^^^^^^^^^^^ ; Maskierung in einfaches Anführungszeichen " wandeln

  • Mit der Erläuterung verstehe ich es, hätte aber sicher Probleme, so eine Zeile aufzusetzen :)

    Mein erstes Programm bestand aus ca. 2.000 Lochkarten und nachdem sie mir das erste mal runtergefallen sind, habe ich die letzten beiden der 80 Byte für eine Numerierung benutzt :rofl:

  • Mit der Erläuterung verstehe ich es, hätte aber sicher Probleme, so eine Zeile aufzusetzen :)

    Ich auch... 8o


    Ja, das ist alles eine Sache der Übung... viele gute Coder in AutoIt mögen solche langen Einzeiler aber eher weniger , weil dadurch natürlich ohne Frage die Übersichtlichkeit leidet. Ich finde aber eher, das es eine Sache der Gewohnheit ist.


    Z. B. sowas:

  • $sTCPErrorText = @error = -2

    Das verstehe ich noch, ist True oder False, aber was dahinter kommt ???


    Ach das ist so etwas wie ein If ... then ... elseif ... elseif?

    Mein erstes Programm bestand aus ca. 2.000 Lochkarten und nachdem sie mir das erste mal runtergefallen sind, habe ich die letzten beiden der 80 Byte für eine Numerierung benutzt :rofl:

  • Ach das ist so etwas wie ein If ... then ... elseif ... elseif?

    Das ist ein Ternärer Operator, hier mehrfach verschachtelt. Wirkt wie If-Then-Else, wobei Else immer belegt sein muss. Wenn man es untereinander schreibt, wird es deutlich:

    AutoIt
    $sTCPErrorText = _ ; Zuweisung
    (@error = -2) ? 'not connected' : _ ; wie: If-Then
    (@error = 1) ? 'IPAddr is incorrect' : _ ; wie: ElseIf-Then
    (@error = 2) ? 'Port is incorrect' : _ ; wie: ElseIf-Then
    (@error = 10060) ? 'Connection timed out' : _ ; wie: ElseIf-Then
    'Unknown error' ; wie: Else
  • Bei StringReplace($sText, "//", Chr(5)) wird Chr(5) als Fehler gemeldet. Im Beispiel oben wird $sChr5 = Chr(5) erst einer Variablen zugewiesen. Wo ist das Problem Chr(5) direkt in StringReplace zu nutzen?


    Ich glaube, mir fehlen noch ein paar grundlegende Basisinformationen zu AutoIt ;(

    Mein erstes Programm bestand aus ca. 2.000 Lochkarten und nachdem sie mir das erste mal runtergefallen sind, habe ich die letzten beiden der 80 Byte für eine Numerierung benutzt :rofl:

    Einmal editiert, zuletzt von HansJ54 ()

  • Bei StringReplace($sText, "//", Chr(5)) wird Chr(5) als Fehler gemeldet. Im Beispiel oben wird $sChr5 = Chr(5) erst einer Variablen zugewiesen. Wo ist das Problem Chr(5) direkt in StringReplace zu nutzen?

    Ich sehe da kein Problem :

    Code
    Global $sString = "Z1 E1//Z1 E2//Z1 E3"
    ConsoleWrite($sString & @CRLF)
    ConsoleWrite("! >>> // mit Chr(5) ersetzen : " & @CRLF)
    ConsoleWrite(StringReplace($sString, "//", Chr(5)) & @CRLF)


    EDIT HansJ54 :

    Es ist für Einsteiger häufig leichter nachvollziehbar (und auch keine Schande ;) ), wenn man Funktionsketten wie :

    StringReplace(StringRegExpReplace(StringStripWS(StringReplace($sString, '""', $sChr5), 3), '^"(.+)"$', '\1'), $sChr5, '"') in Einzelschritte auflöst.


    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."


    Einmal editiert, zuletzt von Musashi () aus folgendem Grund: typo und edit

  • Ich bleibe an so vielen Problemen hängen und komme nicht weiter ...,


    Ich möchte der Variablen $sV den Wert von $sV2 zuweisen. Beide stehen in Textstrings. Bekomme ich nicht hin.

    Mein erstes Programm bestand aus ca. 2.000 Lochkarten und nachdem sie mir das erste mal runtergefallen sind, habe ich die letzten beiden der 80 Byte für eine Numerierung benutzt :rofl:

  • Ich möchte der Variablen $sV den Wert von $sV2 zuweisen.

    $sV = $sV2


    Da Du aber Execute verwendest, vermute ich, dass Du was anderes erreichen willst.

    Kannst Du das bitte in Worte fassen und kurz beschreiben?

  • Das wäre zu einfach ;-)

    1. Ich möchte per InputBox einen Variablennamen einlesen und dann den Wert dieser Variablen ausgeben

    2. Ich möchte per InputBox einen Befehl einlesen we z.B. "Setze Variable x auf Wert y" und das ausführen, also EIngabe '$sV1 = "abc"' oder '$sV1 = $sV2'


    Ist ein "proof of concept"


    Die Anzeige der Variablen und eine einfache Zuweisung habe ich. Da war das Problem, dass man bei Eval() der Variablen im Text den "$" wegnehmen muss:


    Jetzt fehlt mir noch eine Idee, wie ich mit

    $sCmd = "$sBrowser" und $sTodo = "$sText" oder

    $sTodo = "$SBrowser & $sText"

    umgehe. Also im Endeffekt eine Befehlszeile komplett ausführen.

    Mein erstes Programm bestand aus ca. 2.000 Lochkarten und nachdem sie mir das erste mal runtergefallen sind, habe ich die letzten beiden der 80 Byte für eine Numerierung benutzt :rofl:

    4 Mal editiert, zuletzt von HansJ54 ()