# codesys v3 csv Datei einlesen und verarbeiten



## cobra123 (15 April 2016)

Hallo zusammen, ich bin dabei mich in die Programmiersprache strukturierter Text einzuarbeiten und habe dabei folgendes Problem.

Ich möchte mit Codesys V3 eine CSV Datei einlesen und verarbeiten. Die Datei soll aus drei Spalten bestehen (Index, Zeit, Spannung) die jeweils durch ein Trennzeichen getrennt werden. Mit Hilfe des Trennzeichen möchte ich erkennen zu welchen dieser drei Kategorien die Zeichen gehören. 
Beim einlesen möchte ich die Zeichen einzeln einlesen und anschließend in einem weiteren String wieder zusammen fügen. Das einlesen klappt soweit, allerdings funktioniert das zusammensetzen mit dem Befehl "CONCAT(x ,y)" der beiden STRINGs nicht. Mein Problem hierbei ist das ich online sehe dass die einzelnen Zeichen eingelesen werden allerdings werden diese nicht wie gewünscht zusammen gesetzt.

Mein Programm sieht wie folgt aus:

PROGRAM PLC_PRG
VAR
         myTON       : TON;
         SysFileOpenNum  : DWORD;
         FileName        : STRING := 'C:\CoDeSysCSV.csv';
         ReadBuffer        : STRING;    
         Buffer            : STRING;    
         pResult            : WORD;
         pResult_1        : WORD;
         DwWritten       : DWORD;    
         myCount         : INT;
END_VAR



myTON(IN:=NOT myTON.Q, PT:=T#1S); (* Sekunden oszi *)
IF myTON.Q THEN

    CASE myCount OF
                0:     SysFileOpenNum := SysFileOpen(FileName, am:= ACCESS_MODE.AM_READ, pResult:= pResult);

       1..20:    ReadBuffer := ' ';                
                            Buffer := CONCAT(Buffer ,ReadBuffer);    // In ReadBuffer sind die einzelnen Zeichen zu sehen aber im Buffer wird nichts geschrieben
                            DwWritten := SysFileRead(SysFileOpenNum, ADR(ReadBuffer), LEN(ReadBuffer), pResult:= pResult_1);

          21:       SysFileClose(SysFileOpenNum);

    END_CASE

         IF myCount < 22 THEN
                 myCount := myCount + 1;
         END_IF;
END_IF


----------



## lord2k3 (15 April 2016)

Hi,
am besten nimmst du für den ReadBuffer ein array of Byte dann kannst du mit einer Schleife das array durchlaufen und auf die Trennzeichen reagieren.


----------



## cobra123 (15 April 2016)

Hallo lord2k3,

Vielen Dank für die schnelle Antwort.

Das  ist leider nicht ganz das was ich wissen wollte, aber danke für den Tipp  (Die Auswertung der Trennzeichen habe ich noch nicht versucht).

Ich kann die Zeichen aus der Datei lesen diese werden im "ReadBuffer" nacheinander angezeigt allerdings werden diese nicht in "Buffer" übernommen woran kann dies liegen?

anbei ein Bild im Online Modus ich hoffe das verdeutlicht mein Problem.


----------



## Ghosty (15 April 2016)

Hallo,
du musst das Zusammensetzen nach dem Lesen ausführen.
Bei deinem aktuellen Code ist der ReadBuffer beim Zusammensetzen leer initialisiert.

Versuchs mal so:

ReadBuffer := ' '; 
                            DwWritten := SysFileRead(SysFileOpenNum, ADR(ReadBuffer), LEN(ReadBuffer), pResult:= pResult_1);
                            Buffer := CONCAT(Buffer ,ReadBuffer);


Gruß


----------



## excelite (15 April 2016)

ich vermute du bekommst in der Onlineansicht "Der Wert des Ausdrucks kann nicht gelesen werden" angezeigt. Korrekt? Oder hat "????"

Das ist ein Problem wenn der keine Termininierung am Ende findet. Ist mir neulich auch passiert.

Hier ein Beispiel (noch nicht fertig) wie ich CSV einlese:

ACHTUNG: Die Abbruchbedingung ist noch nicht gut mit dem "bNewLineFound", es besteht noch ein Risiko einer Endlosschleife. Es handelte sich hierbei nur um eine schnelle Lösung was zu testen, vielleicht hilft dir das so schon mal weiter.
Es funktioniert auch nur wenn deine Zeilen immer <255 Zeichen sind sonst gibt's ein Problem und $R wird nicht gefunden.


```
PROGRAM PRG_CSVREAD
VAR
 strParameterFile : STRING(80) := 'EPCO.csv';
 iStep : INT := 0;
  
 rtsHandle : CmpErrors.RTS_IEC_HANDLE;
 rtsResult : CmpErrors.RTS_IEC_RESULT;
 iBytesRead : UDINT := 0;
 
 strLineBuffer : STRING(255) := '';
 strPNU : STRING(20) := '';
 strSubindex : STRING(20) := '';
 strDataType : STRING(20) := '';
 strValue : STRING(30);
 iNewLinePosition : INT := 0;
 iReadStartPosition : INT := 0;
 iReadEndPosition : INT := 0;
 iReadPosInFile : DINT := 0;
 bNewLineFound : BOOL := FALSE;
// byLineBuffer : ARRAY [0..200] OF BYTE;


 
END_VAR





rtsHandle := file.SysFileOpen(
    szFile := strParameterFile,
    am := file.AM_READ,
    pResult := ADR(rtsResult)
   );


bNewLineFound := TRUE;
WHILE bNewLineFound DO
  
 // Datei einlesen   
 iBytesRead := file.SysFileRead(
      hFile := rtsHandle, 
      pbyBuffer := ADR(strLineBuffer), 
      ulSize := SIZEOF(strLineBuffer),
      pResult := ADR(rtsResult)
     ); 
 iNewLinePosition := FIND(strLineBuffer, '$R'); 
 IF iNewLinePosition = 0 THEN
  bNewLineFound := FALSE;
  EXIT;
 END_IF;
  
 IF iNewLinePosition > 0 THEN
  strLineBuffer := MID(strLineBuffer, iNewLinePosition,1);
  
  iReadStartPosition := 1;
  iReadEndPosition := FIND(strLineBuffer,',');
  strPNU := MID(strLineBuffer, iReadEndPosition - iReadStartPosition, iReadStartPosition);
  strLineBuffer := MID(strLineBuffer,LEN(strLineBuffer),iReadEndPosition+1 );
  
  iReadStartPosition := 1;
  iReadEndPosition := FIND(strLineBuffer,',');
  strSubindex := MID(strLineBuffer, iReadEndPosition - iReadStartPosition, iReadStartPosition);
  strLineBuffer := MID(strLineBuffer,LEN(strLineBuffer),iReadEndPosition+1 );
  
  iReadStartPosition := 1;
  iReadEndPosition := FIND(strLineBuffer,',');
  strDataType := MID(strLineBuffer, iReadEndPosition - iReadStartPosition, iReadStartPosition);
  strLineBuffer := MID(strLineBuffer,LEN(strLineBuffer),iReadEndPosition+1); 
  
  iReadStartPosition := 1;
  iReadEndPosition := FIND(strLineBuffer,'$R');
  strValue := MID(strLineBuffer, iReadEndPosition - iReadStartPosition, iReadStartPosition);
  strLineBuffer := MID(strLineBuffer,LEN(strLineBuffer),iReadEndPosition+1 );
  
  
     
 END_IF;
 iReadPosInFile := iReadPosInFile + iNewLinePosition+1;
 // Leseposition auf Anfang setzen
 file.SysFileSetPos(
  hFile := rtsHandle,
  ulOffset := iReadPosInFile
 );
END_WHILE
    
file.SysFileClose(rtsHandle);
```


----------



## cobra123 (18 April 2016)

@ghosty wenn ich das Zusammensetzen verschiebe funktioniert es.

@excelite es wird leider keine Meldung angezeigt.

Den angefügten Programmcode kann ich leider nicht ausführen da folgende Fehlermeldung angezeigt wird: "Bezeichner 'file' nicht definiert" . Meine Versuche file zu deklarieren sind leider gescheitert. Wie muss 'file' definiert werden?


----------



## excelite (18 April 2016)

Das ist ein Namespace, kein Bezeichner. Musst im Blibiotheksmanager schauen wie deine Syslibfile Lib eingebunden ist. Da steht dann der Namespace dran.


----------



## Ghosty (18 April 2016)

Hallo cobra, 
freut mich wenn es funktioniert.
Vielleicht noch eine kurze Anmerkung. Ich würde bei der Programmierung von SPS-Steuerungen versuchen, möglichst auf While-Schleifen zu verzichten.
Du hast hier einen Task mit festem Zeitraster. In diesem Zeitraster muss dein Programm abgearbeitet werden. Ansonsten wirst du Probleme mit Zykluszeitüberschreitungen bekommen. 
Bei While-Schleifen kannst du nie wissen wie lange diese zur Abarbeitung brauchen. Im schlechtesten Fall wird deine Schleife nie beendet.


----------

