TC3 Daten in CSV-Datei schreiben / Zeilen überspringen

BrascoC

Level-2
Beiträge
40
Reaktionspunkte
4
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Leute,
ich möchte aus einem Array Datein in eine CSV-Tabelle schreiben. Mit Hilfe des Beispiels von Beckhoff ist mir das auch gelungen. Nun ist aber das Problem, dass die ersten drei Zeilen und die erste Spalte der bereits vorhandenen CSV-Datei nicht überschrieben werden dürfen. Das Programm soll quasi in der zweiten Spalte und der vierten Zeile beginnen zu schreiben.

Hier erstmal der Quelltext:

Code:
CASE step OF
    0:    (* Wait for rising edge at bWrite variable *)
        IF bWrite THEN
            bWrite         := FALSE;
            bBusy         := TRUE;
            bError        := FALSE;
            nErrId        := 0;
            hFile        := 0;
            nRow         := 0;
            nColumn    := 0;
            step         := 1;
        END_IF




    1:    (* Open source file *)
        fbFileOpen(  bExecute := FALSE  );
        fbFileOpen(     sNetId := sNetId, sPathName := sFileName, nMode := FOPEN_MODEWRITE OR FOPEN_MODETEXT,(* Open file in TEXT mode! *)
                        ePath := PATH_GENERIC, bExecute := TRUE );
        step := 2;




    2:(* Wait until open not busy *)
        fbFileOpen( bExecute := FALSE, bError => bError, nErrID => nErrID, hFile => hFile );
        IF NOT fbFileOpen.bBusy THEN
            IF NOT fbFileOpen.bError THEN
                step := 3;
            ELSE(* Error: file not found? *)
                step := 100;
            END_IF
        END_IF


    3:(* Convert one PLC record to CSV format *)
        sCSVLine := '';
        fbWriter.eCmd := eEnumCmd_First;(* Write first field value *)
        IF nRow <= 17 THEN




            FOR nColumn := 0 TO 23 BY 1 DO


                sCSVField := STRING_TO_CSVFIELD( gvl.arParameter[nRow,nColumn], FALSE );(* TODO: Get field value from your application *)




                (* Add new field to the record buffer *)
                fbWriter(     pBuffer := ADR( sCSVLine ), cbBuffer := SIZEOF( sCSVLine ) - 1, putValue := sCSVField, pValue := 0, cbValue := 0,
                            bCRLF := ( nColumn = 23 ) );(* bCRLF == TRUE => Write CRLF after the last field value *)
                IF fbWriter.bOk THEN
                    fbWriter.eCmd := eEnumCmd_Next;(* Write next field value *)
                ELSE(* Error *)
                    step := 100;
                    RETURN;
                END_IF




            END_FOR(* FOR nColumn := 0... *)




            (* FB_FilePuts adds allready CR (carriage return) to the written line.
            We have to replace the $R$L characters with $L character to avoid double CR. *)
            IF RIGHT( sCSVLine, 2 ) = '$R$L' THEN
                sCSVLine := REPLACE( sCSVLine, '$L', 2, LEN( sCSVLine ) - 1 );
            END_IF




            nRow := nRow + 1;(* Increment number of created records (rows) *)
            step := 4;(* Write record to the file *)




        ELSE(* All rows written => Close file *)
            step := 10;
        END_IF




    4:    (* Write single text line *)
        fbFilePuts( bExecute := FALSE );
        fbFilePuts( sNetId := sNetId, hFile := hFile, sLine := sCSVLine, bExecute := TRUE );
        step := 5;




    5:(* Wait until write not busy *)
        fbFilePuts( bExecute := FALSE, bError => bError, nErrID => nErrID );
        IF NOT fbFilePuts.bBusy THEN
            IF NOT fbFilePuts.bError THEN
                step := 3;(* Write next record *)
            ELSE(* Error *)
                step := 100;
            END_IF
        END_IF




    10:    (* Close source file *)
        fbFileClose( bExecute := FALSE );
        fbFileClose( sNetId := sNetId, hFile := hFile, bExecute := TRUE );
        step := 11;




    11:(* Wait until close not busy *)
        fbFileClose( bExecute := FALSE, bError => bError, nErrID => nErrID );
        IF ( NOT fbFileClose.bBusy ) THEN
            hFile := 0;
            step := 100;
        END_IF




    100: (* Error or ready step => cleanup *)
        IF ( hFile <> 0 ) THEN
            step := 10; (* Close the source file *)
        ELSE
            bBusy := FALSE;
            step := 0;    (* Ready *)
        END_IF




END_CASE

Eine meiner Ideen wäre es, dass er den CR denn er nach Beendigung einer Zeile hinzufügt, vor dem eigentlichen schreiben drei mal durchführt (Hoffe, ihr wisst was ich meine). Allerdings hat die Umsetzung nicht ganz funktioniert. :?

Ich danke euch schon mal für eure Ideen.

MfG, BrascoC
 
Zuletzt bearbeitet:
Die ersten drei Zeilen überspringen wird noch möglich sein: Die Datei mit FOPEN_MODEREAD OR FOPEN_MODEPLUS öffnen, dann die ersten 3 Zeilen einlesen. Dann steht der Dateizeiger am Anfang der 4. Zeile. Die erste Spalte stehen lassen wird schwieriger. Wenn die neue zu schreibende Zeile eine andere Länge haben kann als die bereits in der Datei stehende, hast Du eh keine Chance. Ansonsten könntest Du versuchen, den Dateizeiger mit einem FB_FileTell auszulesen und dann mit einem FB_FileSeek an den Anfang der zweiten Spalte zu setzen. Ich habe selbst mit diesen FBs aber noch auf einer Textdatei gearbeitet, ob das gutgeht, musst Du ausprobieren.
Alternativ könntest Du die bestehende Datei zeilenweise auslesen, das was Du ersetzen willst, löschen und stattdessen den neuen Inhalt dranhängen und dann in eine neue Datei schreiben.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hey StructuredTrash,
an den Befehl FOPEN_MODEREAD OR FOPEN_MODEPLUS habe ich ja überhaupt nicht gedacht. Danke.
Und was die Reihe anbetrifft, ist es eh egal, da in dieser nur Text in den oberen drei Zeilen steht, welche ja dann übersprungen werden.
Werde ich gleich mal Testen.
Danke dir.


 
Hallo StructedTrash,

ich habe es jetzt mal mit dem FOPEN_MODEREAD OR FOPEN_MODEPLUS probiert.

Code:
CASE step OF    0: (* Warte auf steigende Flanke von bWrite *)
       IF bWrite THEN
            bWrite       := FALSE;
            bBusy        := TRUE;
            bError        := FALSE;
            nErrId        := 0;
            hFile          := 0;
            nRow         := 0;
        nRow1         :=1;
            nColumn         := 0;
            step         := 10;
       END_IF


    10: (* Öffne Zieldatei im Lese- und Schreibmodus *)
        fbFileOpen( bExecute := FALSE  );
        fbFileOpen( sNetId := sNetId, sPathName := sFileName, nMode := FOPEN_MODEREAD OR FOPEN_MODEPLUS OR FOPEN_MODETEXT,(* Open file in TEXT mode! *)
                    ePath := PATH_GENERIC, bExecute := TRUE );
        step := 20;


    20: (* Warten bis FileOpen fertig *)
        fbFileOpen( bExecute := FALSE, bError => bError, nErrID => nErrID, hFile => hFile );
        IF NOT fbFileOpen.bBusy THEN
            IF NOT fbFileOpen.bError THEN
                step := 24;
            ELSE(* Error: Datei nicht gefunden? *)
                step := 100;
                stext:='Datei nicht gefunden!';
            END_IF
        END_IF
//--------------------------------------------------------------------------------


    24:    (*Lese einzelne Zeilen*)
    
        fbFileGets(bExecute:=FALSE);
        fbFileGets(sNetId:=sNetId, hFile:=hFile, bExecute:= TRUE);
        step:=28;
        
    28: (*Warte bis lesen fertig*)
        fbFileGets(bExecute:=FALSE, bError=>bError, nErrId=>nErrId, sLine=>sCSVLine);
        IF nRow1 <=3 THEN 
        IF NOT fbFileGets.bBusy THEN
            IF NOT fbFileGets.bError THEN
                IF fbFileGets.bEOF THEN
                    step:=30; (*Ende der Datei erreicht --> Datei schließen*)
                    sText:='Dateiende erreicht!';
                ELSE
                    (*FB_FileGets gibt eine Textzeile ohne das CR-Zeichen zurück. Diese wird 
                    wiederhergestellt ($L wird durch $R$L ersetzt*)
                    IF Right(sCSVLine, 1) = '$L' THEN
                        sCSVLine:=REPLACE (sCSVLine, '$R$L', 2, LEN(SCSVLine));
                    END_IF
                    nRow1:=nRow1+1;
                    step:=24;
                END_IF
            ELSE (*Error*)
                sText:='Fehler in Datei!';
                step:=100;
            END_IF
        END_IF
        ELSE
            step:=30;
        END_IF
    
//----------------------------------------------------------------        
    30: (* Konvertiere in CSV-Format *)
        sCSVLine := '';
        fbWriter.eCmd := eEnumCmd_First;(* Schreibe ersten Wert in Buffer *)
        IF nRow <= 15 THEN
            FOR nColumn := 0 TO 24 BY 1 DO
                sCSVField := STRING_TO_CSVFIELD( gvl.arParameter[nRow,nColumn], FALSE );(* Bekomme Feldwert aus Array *)


                (* Erzeuge neues Feld im Buffer *)
                fbWriter(pBuffer := ADR( sCSVLine ), cbBuffer := SIZEOF( sCSVLine ) - 1, putValue := sCSVField, pValue := 0, cbValue := 0,
                         bCRLF := ( nColumn = 23 ) );(* bCRLF == TRUE => Schreibe CRLF nach den letzten Wert *)
                IF fbWriter.bOk THEN
                    fbWriter.eCmd := eEnumCmd_Next;(* Schreibe nächsten Feld-Wert *)
                ELSE(* Error *)
                    step := 100;
                    RETURN;
                END_IF
            END_FOR(* FOR nColumn := 0... *)


            (*FB_FilePuts fügt der geschriebenen Zeile ein CR hinzu.
             Die $ R $ L-Zeichen muss durch $ L-Zeichen ersetzt werden, um doppelte CR zu vermeiden *)
            IF RIGHT( sCSVLine, 2 ) = '$R$L' THEN
                sCSVLine := REPLACE( sCSVLine, '$L', 2, LEN( sCSVLine ) - 1 );
            END_IF


            nRow := nRow + 1;
            step := 40;


        ELSE(* Alle Daten geschrieben => Datei schließen *)
            step := 60;
        END_IF


    40: (* Schreibe einzelne Zeile *)
        fbFilePuts( bExecute := FALSE );
        fbFilePuts( sNetId := sNetId, hFile := hFile, sLine := sCSVLine, bExecute := TRUE );
        step := 50;


    50: (* Warten bis fbFilePuts fertig *)
        fbFilePuts( bExecute := FALSE, bError => bError, nErrID => nErrID );
        IF NOT fbFilePuts.bBusy THEN
            IF NOT fbFilePuts.bError THEN
                step := 30;(* gehe zurück, schreibe nächste Zeile *)
            ELSE(* Error *)
                step := 100;
            END_IF
        END_IF


    60: (* Datei schließen *)
        fbFileClose( bExecute := FALSE );
        fbFileClose( sNetId := sNetId, hFile := hFile, bExecute := TRUE );
        step := 70;


    70: (* Warten bis fbFileClose fertig *)
        fbFileClose( bExecute := FALSE, bError => bError, nErrID => nErrID );
        IF ( NOT fbFileClose.bBusy ) THEN
            hFile := 0;
            step := 100;
        END_IF


    100: (* Error oder Fertig => cleanup *)
        IF ( hFile <> 0 ) THEN
            step := 60; 
        ELSE
            IF NOT bError THEN
            bBusy := FALSE;
            step := 0;    (* Fertig *)
            ELSE
                sText:='Fehler aufgetreten!';
            End_If
        END_IF
END_CASE

Er liest auch die ersten paar Zeilen, welche ich überspringen möchte ein. Dann springt er zu Schritt 30 weiter, ließt die erste zu schreibende Zeile ein und arbeitet bis Schritt 50 wunderbar durch. Dort allerdings kommt eine Fehlermeldung: Error 1792 (Device Error). Weißt du zufällig, woran das liegen kann? Was auch komisch ist, dass er den Error von den FB-Ausgängen nicht an die Variablen (bError und nErrId) weiter gibt.

MfG, BrascoC
 
Vermutlich tritt der Fehler schon beim fbFilePuts-Aufruf in Schritt 40 auf. Dort gibst Du bError und nErrId nicht zurück. Warum er es dann in Schritt 50 nicht tut, kann ich gerade nicht sagen. Könnte sein, dass er bei bExecute:=false den Fehler schon wieder zurücksetzt. Probier mal den fbFilePuts-Aufruf in Schritt 50 ohne bExecute:=false aus.
Fehler 1792 ist selten. Kann es sein, dass Dein CSV-String zu lang ist?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hey,
der String ist tatsächlich zu lang. Dachte eigentlich, der schneitet ihn einfach ab und macht in der zweiten Zeile weiter.
Ich habe jetzt die Tabelle verändert, so dass ich nicht mehr über die 253 Zeichen komme. Jetzt bin ich zufrieden.
Danke dir vielmals.

MfG, BrascoC
 
Zurück
Oben