Zu Langsames erstellen einer .csv Datei und deren Export

Zuviel Werbung?
-> Hier kostenlos registrieren
Hi Eddi,
ne das liegt an der Code formatierung hier.
Wie kann ich denn die WriteLen bestimmen?
Auch die Formatierung wird nicht mehr eingehalten. Das heisst er schreibt willkürlich alle Sachen Hintereinander.
Muss ich mehr umarbeiten als einfach nur die FileWrite Schritt 31 und 32 einzufügen?
Die Formatierung wurde ja bis jetzt so gemacht

Code:
IF RIGHT( sCSVLine, 2 ) = '$R$L' THENsCSVLine := REPLACE( sCSVLine, '$L', 2, LEN( sCSVLine ) - 1 );
END_IF

Vermutlich geht das ja jetzt nicht mehr weil er keine einzelnen Zeilen Schreibt sondern das Array auf einmal.
 
Zuletzt bearbeitet:
Da das Array komplett am Stück geschrieben wird, sollte eigentlich jeder String, getrennt durch ein Nullbyte hintereinanderweg im File auftauchen. Das ist natürlich kein csv.
Im einfachsten Fall gibst Du Deinem Array noch zwei Spalten.
Erste Spalte, erster Wert
Zweite Spalte Separator (Komma, Semikolon whatever)
Dritte Spalte zweiter Wert
Vierte Spalte Separator und Zeilenumbruch

Die Nullbytes im File werden m.W. in Excel, notepad++ oder Openoffice beim Import ignoriert, also würde ich darauf keine Kopfschmerzen verwenden.

PS: Schau Dir mal die Funktion String_to_csvfield an. Die macht das schon. Passt denn jetzt das Timing?
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
So ich bin jetzt schon weiter :D mir fehlt nur noch die Formatierung. Zur Zeit sieht es so aus wie im Anhang zu sehen.
Normalerweise sieht es so aus
[TABLE="width: 500"]
[TR]
[TD]Widerstand[/TD]
[TD]Druck[/TD]
[TD]Weg[/TD]
[/TR]
[TR]
[TD]Ohm Wert1[/TD]
[TD]Druck Wert1[/TD]
[TD]Weg Wert1[/TD]
[/TR]
[TR]
[TD]OhmWert2[/TD]
[TD]Druck Wert2[/TD]
[TD]Weg Wert2[/TD]
[/TR]
[TR]
[TD]usw[/TD]
[TD]usw[/TD]
[TD]usw[/TD]
[/TR]
[TR]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[/TR]
[TR]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[/TR]
[TR]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[/TR]
[TR]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[/TR]
[TR]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[/TR]
[TR]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[/TR]
[/TABLE]



csv.jpg[TABLE="width: 500"]
[TR]
[TD]Druck[/TD]
[/TR]
[/TABLE]
 
Hi,
das Timing passt. So wollte ich das haben :D ,ich versuche mich gerade an dem String_to_csvfield. Jedoch kommt dabei nur Mist rum. Der schreibt die Erste Zeile Korrekt und dannach kommen komische Zeichen

BSP:

[TABLE="width: 160"]
[TR]
[TD]Prüfling:[/TD]
[TD]500 x 500[/TD]
[/TR]
[TR]
[TD]`Ê•‚ð3‡[/TD]
[TD][/TD]
[/TR]
[TR]
[TD="colspan: 2"]ø3‡$ì…·tªL‡ì…·‚ð3‡[/TD]
[/TR]
[TR]
[TD="colspan: 2"]÷3‡ø3‡÷3‡Lì…·z!M‡‚ð3‡[/TD]
[/TR]
[TR]
[TD="colspan: 2"]ì…·lò3‡ø3‡èß3‡hî…·[/TD]
[/TR]
[TR]
[TD="colspan: 2"]ÈL‡*ÈLRöÔÐB‡D:\Pruefberichte\bumper\17.500 x 500.KWG.D80_17.11\P 1_17-11-2017_ 8-27-44.csv"ˆRöÌÏB‡'x" ò3‡$ô3‡ˆÝ$ô3‡\¾>"Rö$ÏB‡ìÐB‡ˆÌÏB‡'yÑB‡ˆÌÏB‡'ÑB‡Römð3‡§±¸
ÌÏB‡'{Rö§±mð3‡”ö3‡¸
”ö3‡z¾>$ÏB‡LÑB‡mð3‡ÿé4ÑB‡Œù3‡00 x 500Žù3‡[/TD]
[/TR]
[/TABLE]


Code:
3:// Konvertierung in .CSV Format
sCSVLine := '';
fbWriter.eCmd := eEnumCmd_First; //Schreiben der ersten Zeile
IF nRow <= MAX_CSV_ROWS THEN
FOR nColumn := 0 TO MAX_CSV_COLUMNS BY 1 DO
sCSVField := STRING_TO_CSVFIELD( database[ nRow, nColumn ], FALSE );//Daten aus dem Array lesen


.
.
.
.IF RIGHT( sCSVLine, 2 ) = '$R$L' THEN
sCSVLine := REPLACE( sCSVLine, '$L', 2, LEN( sCSVLine ) - 1 );
    
END_IF

.
.
.

4:(*datei geöffnet; bytebuffer schreiben*)
fbfileopen(bExecute:= FALSE );
fbfilewrite(
    sNetId:= ,
    hFile:=hFile ,
    pWriteBuff:=ADR(sCSVLine),
    cbWriteLen:=SIZEOF (database) ,
    bExecute:= TRUE,
    tTimeout:=t#3s ,
    bBusy=> ,
    bError=> ,
    nErrId=> ,
    cbWrite=>cbwrite_vrfy );
IF fbfilewrite.bExecute AND NOT fbfilewrite.bBusy THEN
    step:=5;
END_IF;


5:
fbfilewrite(bExecute:=FALSE  );
fbfileclose(
    sNetId:= ,
    hFile:=hFile ,
    bExecute:=TRUE ,
    tTimeout:=t#500ms ,
    bBusy=> ,
    bError=> ,
    nErrId=> );
IF fbfileclose.bExecute AND NOT fbfileclose.bBusy THEN
step:=100;
END_IF;




10:// Erstelle Quell Datei
fbFileClose( bExecute := FALSE );
fbFileClose( sNetId := sNetId, hFile := hFile, bExecute := TRUE );
step := 11;




11:// Warten bis Schließen nicht busy
fbFileClose( bExecute := FALSE, bError => bError, nErrID => nErrID );
IF ( NOT fbFileClose.bBusy) THEN
hFile := 0;
step := 100;




END_IF




100: //Beenden
IF ( hFile <> 0 ) THEN    
step := 10; 




ELSE




bBusy := FALSE;
step := 0; 
END_IF
END_CASE
 
So nochmal von vorn :)
Also ich lasse das Array so wie es ist ohne hinzufügen von weiteren Spalten und wandele stattdessen das Array per string_to_csvfield um.
Dieses csvfield nehme ich als pWriteBuff im FB_Filewrite richtig?
Welche cbWriteLen wird da benötigt? Ich habe jetzt da SIZE OF (csvfield)
Das Problem ist dabei das er nur die erste Zeile Richtig darstellt. Wahrscheinlich weil in der csvfield auch nur die eine Zeile drinnen steht.
Stehe echt aufm schlauch..... :(
 
Ein csv-Feld ist das, was in Excel nachher in einer einzelnen Zelle stehen soll. Es gibt wie immer nicht nur einen Lösungsweg.

Die zulestzt vorgeschlagene Funktion musst Du anwenden, bevor ein Datum in Dein Array geschrieben wird. Eine Alternative ist der FB_Format_String oder so ähnlich, wie ich ihn in meinem Konzeptcode angewendet habe. Hier würdest Du das ganze gleich zeilenweise behandeln, also allen Daten in einem Schritt zeilenweise formatieren. Der FB_Formatstring hat direkt Hilfsfunktionen, um verschiedene Eingangsdatenformate passend in einen String umzuwandeln. Den Spaltenseparator, die Wertformatierung (anz. Stellenusw.) und das Zeilenende fügt man dann im Formatstring hinzu. Die Anwendung des ganzen ist etwas gestreut aber im infosys zu finden.

Aus dem Konzept:
Code:
bastelstring(
        sFormat:='%2u.%2u.%4u;%2u:%2u;%5u;%5u;%5u;%5u;%5u;',
        arg1:=F_WORD(systemzeit.systemTime.wDay) ,
        arg2:=F_WORD(systemzeit.systemTime.wMonth) ,
        arg3:=F_WORD(systemzeit.systemTime.wYear) ,
        arg4:= F_WORD(systemzeit.systemTime.wHour),
        arg5:= F_WORD(systemzeit.systemTime.wMinute),
        arg6:=F_WORD(mav_speed.Y) ,
        arg7:=F_WORD(mav_strom.Y) ,
        arg8:=F_WORD(mav_feuchte_rel.Y),
        arg9:=F_WORD(mav_feuchte_abs.Y) ,
        arg10:=F_WORD(mav_temp.Y) ,
        bError=> ,
        nErrId=> ,
        sOut=>s_Datensatz_a);




    zeitstempel:= CONCAT(s_datensatz_a,crlf);     (*datensatz mit CRLF abschließen*)
    cblen:=LEN(zeitstempel);                (*datensatzlänge ermitteln*)

Hier wird also eine einzelne Zeile bestehend aus 7 csv-Fields (Spalten) getrennt mit Semikolon zusammengesetzt. Das Zeilenende wird mit concat angehängt. Anschließend wird die korrekte Länge erfasst.
Diese Zeile könntest Du jetzt byteweise in ein Array of Byte schreiben, weil fertig formatiert. Die Gesamtlänge im Bytearray kannst du durch zeilenweises Aufsummieren von cblen erreichen. Dann weißt Du die Gesamtlänge des auf die Platte zu schreibenden Datensatzes. Ist doch ganz einfach :cool:;).
Das Array of Byte ist übrigens eindimensional und sollte großzügig gemäß dem maximalen Datenanfall dimensioniert werden. Inneerhalb des Array navigierst Du mittels "Pointer", den Du jeweils aus der Länge der letzten Datenzeile errechnest. Du Hast Dann also einen fixen Startindex, einen Schreibindex für die nächste Zeile/ nächstes Byte und eine Gesamtlänge für den filwrite-BS.

Du weißt doch schon, wie das Endergebnis aussehen soll. Das schreibst Du mal als Beispielzeile auf ein Blatt Papier und fügst die entsprechend csv-Definition benötigten Steuerzeichen hinzu.
Wichtig ist, das Du keine Separatoren vergisst und nicht soviele Nicht-AscII's drin hast, weil das sind die seltsamen Zeichen in Deinem Beeispiel. Also nicht den Überblick verlieren :D

PS: Bequem wäre das umkopieren vom formatierten String in das Bytearray mit memcpy zu erledigen.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Welche cbWriteLen wird da benötigt?
Du übergibst an fbfilewrite den String sCSVLine - also solltest Du die tatsächliche Stringlänge von sCSVLine angeben und nicht die Speichergröße von völlig anderen Variablen.

Warum er nur die erste Zeile richtig schreibt kann man an Deinem Code nicht sehen, weil der entscheidende Code fehlt. Du schreibst Deine Daten in sCSVField und in die Datei schreibst Du sCSVLine - wie kommt sCSVField in sCSVLine? Wie wird nRow verändert?

@Gizzl0r
ich halte mich nun hier raus, weißnix_ erklärt ja schon fleißig.
Also nimm das genannte Blatt Papier und male erstmal auf was Du da genau erreichen willst/tun mußt. SPS-Programmieren sollte nicht wie Bingo-spielen aussehen...

Harald
 
Zuletzt bearbeitet:
Ich packe mal meinen ganzen Code rein. Der obere teil dient nur den Dateinamen zusammenstellen :D




Code:
//Auswahl Pruflingsbezeichnungs IF GL_VAR.start_b
	THEN GL_VAR.Prueflingsart := '17';
	
	GL_VAR.Prueflingsordner :='bumper';
ELSIF GL_VAR.start_m	
	THEN GL_VAR.Prueflingsart := '16';
	
	GL_VAR.Prueflingsordner :='mat';
ELSIF GL_VAR.start_e OR GL_VAR.start_end
	THEN GL_VAR.Prueflingsart := '15';
	
	GL_VAR.Prueflingsordner :='edge';
END_IF;


//Auswahl Prüfart
IF GL_VAR.Pruefart = 0
	THEN GL_VAR.Pruefbezeichnung := 'KWG';
	ELSIF GL_VAR.Pruefart = 1
	THEN GL_VAR.Pruefbezeichnung := 'KWR';
	ELSIF GL_VAR.Pruefart = 2
	THEN GL_VAR.Pruefbezeichnung := 'SKR';
	ELSIF GL_VAR.Pruefart = 3
	THEN GL_VAR.Pruefbezeichnung := 'SKG';	
END_IF


//Ordnernamen bestimmen
D1 := LREAL_TO_FMTSTR(GL_VAR.dim_x, 0, TRUE);
D2 := LREAL_TO_FMTSTR(GL_VAR.dim_y, 0, TRUE);
Dim1 := CONCAT (D1,' x ');
Dimensionen:= CONCAT (Dim1,D2);


IF LEN(GL_VAR.Bezeichnung) <=1 
	THEN 
	GL_VAR.Pruefling := Dimensionen;	
	ELSE
	GL_VAR.Pruefling := GL_VAR.Bezeichnung;
END_IF
Ordnername_1 := CONCAT (GL_VAR.Prueflingsordner,'\');
Ordnername_2 := CONCAT (Ordnername_1,GL_VAR.Prueflingsart); 
Ordnername_3 := CONCAT (Ordnername_2,'.'); 
Ordnername_4 := CONCAT (Ordnername_3,GL_VAR.Pruefling);
Ordnername_5 := CONCAT (Ordnername_4,'.');
Ordnername_6 := CONCAT (Ordnername_5,GL_VAR.Pruefbezeichnung);
Ordnername_7 := CONCAT (Ordnername_6,'.');
Ordnername_8 := CONCAT (Ordnername_7,GL_VAR.Pruefkoerperbezeichnung);
Ordnername_9 := CONCAT (Ordnername_8,'_');
GL_VAR.Ordnername :=CONCAT (Ordnername_9,Tag_Monat);


//Wandeln der Widerstandsvariable
Widerstand:=REAL_TO_STRING (GL_VAR.Widerstand);


//Informationsdarstellung in der .csv Datei
//Datum auslesen und zusammensetzen
Tag := LREAL_TO_FMTSTR(systemzeit.systemTime.wDay, 0, TRUE);
Monat := LREAL_TO_FMTSTR(systemzeit.systemTime.wMonth, 0, TRUE);
Jahr := LREAL_TO_FMTSTR(systemzeit.systemTime.wYear, 0, TRUE);


Tag_Punkt := CONCAT (Tag,'.');
Tag_Monat := CONCAT (Tag_Punkt,Monat);
Monat_Punkt := CONCAT(Tag_Monat,'.');
Datum := CONCAT (Monat_Punkt,Jahr);


//Uhrzeit auslesen und Zusammensetzen 
MilliSekunden := LREAL_TO_FMTSTR(systemzeit.systemTime.wMilliseconds, 0, TRUE);
Sekunden := LREAL_TO_FMTSTR(systemzeit.systemTime.wSecond, 0, TRUE);
Stunde := LREAL_TO_FMTSTR(systemzeit.systemTime.wHour, 0, TRUE);
Minute := LREAL_TO_FMTSTR(systemzeit.systemTime.wMinute, 0, TRUE);
Sekunden_ := CONCAT (Sekunden,'-');
Sekunden_MS := CONCAT (Sekunden_,MilliSekunden);
Stunde_Punkt := CONCAT(Stunde,':');
Stunde_Strich := CONCAT(Stunde,'-');
Uhrzeit := CONCAT (Stunde_Punkt,Minute);
Uhrzeit_Ordner :=CONCAT (Stunde_Strich,Minute);


database[0,0]:= 'Prüfling:';
database[0,1]:= GL_VAR.Pruefling;
database[1,0]:= 'Prueferkuerzel:';
database[1,1]:= GL_VAR.Pruefer;
database[2,0]:= 'Datum:';
database[2,1]:= Datum;
database[3,0]:= 'Zeit:';
database[3,1]:=	 Uhrzeit;
database[4,0]:= 'Geschwindigkeit:';
database[4,1]:=	 GL_VAR.geschw_z_str;
database[5,0]:=	 'Anmerkung:';
database[5,1]:=	 GL_VAR.Druck_niO_str;
database[9,0]:= 'Widerstand';
database[9,1]:= 'Druck';
database[9,2]:= 'Weg';


GL_VAR.Zeit_fertig_str := TIME_TO_STRING( GL_VAR.Zeit_fertig);


(*IF GL_VAR.Zeit_ende
	THEN 
	database[6,0]:= 'Benötitgte Zeit';
	database[6,1]:=	 GL_VAR.Zeit_fertig_str;
END_IF*)
IF GL_VAR.start_e_f
	THEN 
	database[7,0]:= 'Seriennummer';
	database[7,1]:=	 GL_VAR.Seriennummer;
END_IF




//Startbedingung Datensammeln Datenbank
IF (GL_VAR.Pruefkoerper) OR ( NOT GL_VAR.Pruefkoerper_ohne_kontakt AND GL_VAR.KMZ_Anzeige > 5  AND GL_VAR.Widerstand < 8000) THEN b_sammeln:=TRUE; ELSE b_sammeln:=FALSE; 	  END_IF;
bWrite:= NOT b_sammeln AND GL_VAR.Direction_z_ret; //OR GL_VAR.Messung_fertig);
bCreate:= GL_VAR.start_b OR GL_VAR.start_e OR GL_VAR.start_m OR GL_VAR.start_end;
IF row>=2501 THEN b_sammeln:=FALSE; row:=0; column:=0; END_IF;




IF NOT b_sammeln   THEN 
         row:=0; Column := 0  ;            				 
ELSE
cyclecount:=cyclecount+1;	
IF GL_VAR.Newton > 400 AND GL_VAR.Messung =2
	THEN Cyclecount2 := 50;
	ELSE Cyclecount2 := 25;
END_IF
IF 


cyclecount=Cyclecount2 THEN   
    cyclecount:=0;
						  
                          database[row+10,0]:=Widerstand;
                          database[row+10,1]:=GL_VAR.KMZ_String;
						  database[row+10,2]:=GL_VAR.hoehe_dif;
                          row:=row+1;
						  csvRecord := csvRecord + fbWriter.cbWrite;
								  
END_IF;  
	
END_IF;
IF GL_VAR.Messung_fertig
	THEN
	 row:=0; column:=0;
END_IF








//Systemzeit ermitteln
systemzeit(
    sNetID:= , 
    bEnable:=TRUE ,
    dwCycle:=5 ,
    dwOpt:=1 ,
    tTimeout:= , 
    bValid=> ,
    systemTime=> ,
    tzID=> );






CASE step OF


0: //Bedingung bWrite erfüllt
IF bWrite THEN
bWrite := FALSE;
bBusy := TRUE;
bError := FALSE;
nErrId := 0;
hFile := 0;
nRow := 0;
nColumn := 0;
step := 1;
END_IF




ePath := SEL( bBootFolder, PATH_GENERIC, PATH_BOOTPATH );
sPathName := SEL( bBootFolder, CONCAT('D:\Pruefberichte\', GL_VAR.Ordnername), sFolderName );


IF bCreate THEN
        bCreate := FALSE;
        fbCreateDir( bExecute := FALSE );
        fbCreateDir(sNetId:= '',
                sPathName:= sPathName,
                ePath:= ePath,
                bExecute:= TRUE,
                tTimeout:= DEFAULT_ADS_TIMEOUT,
                bBusy=>bCreate_Busy, bError=>bCreate_Error, nErrId=>nCreate_ErrID );
ELSE
        fbCreateDir( bExecute := FALSE, bBusy=>bCreate_Busy, bError=>bCreate_Error, nErrId=>nCreate_ErrID );
END_IF






1: //Öffne Quelldatei




//Dateinnamen zusammensetzen




bastelstring(
        sFormat:='%s\P%2u_%2u-%2u-%4u_%2u-%2u-%2u.csv',	
  		arg1:=F_STRING(sPathName) ,	
		arg2:=F_WORD(MAIN.Dimensionen.Punkt) ,
        arg3:=F_WORD(systemzeit.systemTime.wDay) ,
        arg4:=F_WORD(systemzeit.systemTime.wMonth) ,
        arg5:=F_WORD(systemzeit.systemTime.wYear) ,
		arg6:=F_WORD(systemzeit.systemTime.wHour) ,
		arg7:=F_WORD(systemzeit.systemTime.wMinute) ,
		arg8:=F_WORD(systemzeit.systemTime.wSecond) ,
        sOut=>sFileName );




		
//Öffne Datei im Text Mode		
fbFileOpen( bExecute := FALSE );
fbFileOpen( sNetId := sNetId, sPathName := sFileName, nMode := FOPEN_MODEWRITE OR FOPEN_MODETEXT,
ePath := PATH_GENERIC, bExecute := TRUE );
step := 2;


2:// Wearten bis open nicht busy *)
fbFileOpen( bExecute := FALSE, bError => bError, nErrID => nErrID, hFile => hFile );
IF NOT fbFileOpen.bBusy THEN
IF NOT fbFileOpen.bError THEN
step := 3;
ELSE//Fehler: Datei nicht gefunden
step := 100;
END_IF
END_IF


3:// Konvertierung in .CSV Format
csvRecord := 0;
sCSVLine := '';
fbWriter.eCmd := eEnumCmd_First; //Schreiben der ersten Zeile
IF nRow <= MAX_CSV_ROWS THEN
FOR nColumn := 0 TO MAX_CSV_COLUMNS BY 1 DO
sCSVField := STRING_TO_CSVFIELD( database[ nRow, nColumn ], FALSE );//Daten aus dem Array lesen




//Neues Feld in Buffer Schreiben
fbWriter( pBuffer := ADR( sCSVLine ),
cbBuffer := SIZEOF( sCSVLine ) - 1,
putValue := sCSVField, pValue := 0,
cbValue := 0,
bCRLF := ( nColumn = MAX_CSV_COLUMNS ));
IF fbWriter.bOk THEN
fbWriter.eCmd := eEnumCmd_Next;


ELSE
step := 100;
RETURN;
END_IF
END_FOR
IF RIGHT( sCSVLine, 2 ) = '$R$L' THEN
sCSVLine := REPLACE( sCSVLine, '$L', 2, LEN( sCSVLine ) - 1 );	
END_IF
nRow := nRow+1;//Inkrementieren der Zeile
step := 4;	
ELSE	
Memset(ADR(Database), 0, SIZEOF(Database));
step := 10;
END_IF






4:(*datei geöffnet; bytebuffer schreiben*)
fbfileopen(bExecute:= FALSE );
fbfilewrite(
    sNetId:= ,
    hFile:=hFile ,
    pWriteBuff:=ADR(sCsvLine),
    cbWriteLen:=SIZEOF (sCsvLine) ,
    bExecute:= TRUE,
    tTimeout:=t#3s ,
    bBusy=> ,
    bError=> ,
    nErrId=> ,
    cbWrite=>cbwrite_vrfy );
IF fbfilewrite.bExecute AND NOT fbfilewrite.bBusy THEN
    step:=5;
END_IF;


5:
fbfilewrite(bExecute:=FALSE  );
fbfileclose(
    sNetId:= ,
    hFile:=hFile ,
    bExecute:=TRUE ,
    tTimeout:=t#500ms ,
    bBusy=> ,
    bError=> ,
    nErrId=> );
IF fbfileclose.bExecute AND NOT fbfileclose.bBusy THEN
	step := 100;
END_IF;




10:// Erstelle Quell Datei
fbFileClose( bExecute := FALSE );
fbFileClose( sNetId := sNetId, hFile := hFile, bExecute := TRUE );
step := 11;




11:// Warten bis Schließen nicht busy
fbFileClose( bExecute := FALSE, bError => bError, nErrID => nErrID );
IF ( NOT fbFileClose.bBusy) THEN
hFile := 0;
step := 100;




END_IF




100: //Beenden
IF ( hFile <> 0 ) THEN	
step := 10; 




ELSE




bBusy := FALSE;
step := 0; 
END_IF
END_CASE
 
Ist es richtig das ich statt der einzelnen scsvline den Inhalt des Buffers (fbWriter) als pWriteBuff Quelle angeben muss? Wen ja wie komme ich an den Inhalt? mit fbWriter.pbuffer kriege ich nur paar Kryptische Zeichen heraus
 
Zuviel Werbung?
-> Hier kostenlos registrieren
fbfilewrite hast Du doch schon???? Das bleibt meiner Meinung nach auch so.

Das was ich heute Mittag schrieb bezog sich darauf, wie Du den Schreibpuffer aufbaust und befüllst.
Dem fbfilewrite übergibst Du dann nur die Startadresse ADR(writebuffer) und die Länge in Byte. Wenn Du den Puffer richtig befüllst ist doch eigentlich alles schon erledigt.
Wenn ich das bisher richtig mitgeschnitten habe, hattest Du zuletzt Probleme bei der formatrichtigen Befüllung und bei der Längenbestimmung. Und genau dazu hab ich Dir was geschrieben. Bevor ich sowas versuche in einem Programm umzusetzen brauch ich erstmal gaanz viel Papier. Dann wird erstmal aufgemalt, wie die Bytes im Puffer liegen müssen und dann mach ich mir Gedanken, wie ich die da reinkriege.

Mein letzter Vorschlag war doch die Daten unmittelbar bei der Erfassung richtig formatiert runterzuschreiben. Was wegfällt ist Dein zweidimensionales Array of String und wird direkt durch den Schreibpuffer ersetzt.
PS: Ich hab noch nicht in Deinen Code reingesehen, weil ich heute eine Opreation am offenen Herzen habe, die noch lange nicht abgeschlossen ist. Da wird frühestens morgen was nach ganz viel Kaffee :lol:
 
Zuletzt bearbeitet:
Hi,
also das Format wie ich es haben will ist bereits vorhanden. Ich habe auch ein Puffer namens fbWriter (FB_CSVMemBufferWriter).
Auch fbFileWrite ist vorhanden. Als pWriteBuff ist auch der fbWriter.pbuffer hinterlegt.
Als cbWriteLen habe ich den fbWriter.cbsize angegeben. <--- Was für mich nach der beckhoff anleitung logisch klingt.

Das Problem was ich aber habe, das er mir so nur die erste Zeile schreibt, jedoch in der passenden Formatierung wie ich es haben will. Siehe Anhang

nur_zeile.jpgcsv_quell.jpg
 

Anhänge

  • csv_quell.jpg
    csv_quell.jpg
    36,5 KB · Aufrufe: 8
Hast du denn mal online nachgeschaut, ob denn mehr in pBuffer drinsteht als nur die erste Zeile? (Breakpoint setzen und Variablen beobachten)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Habe denke den Fehler gefunden. Weiss jedoch nicht wie ich den Fehler beheben kann. Der schreibt hier wohl immer nur eine Zeile in das CSV_FIELD und im nächsten Umlauf den zweiten usw. weil er am ende nrow inkrementiert und nicht vor dem Filewrite


Code:
3:// Konvertierung in .CSV FormatsCSVLine := '';
fbWriter.eCmd := eEnumCmd_First; //Schreiben der ersten Zeile
IF nRow <= MAX_CSV_ROWS THEN
FOR nColumn := 0 TO MAX_CSV_COLUMNS DO




sCSVField := STRING_TO_CSVFIELD( database[ nrow , nColumn ], FALSE );//Daten aus dem Array lesen


fbWriter( pBuffer := ADR( sCSVLine ),
cbBuffer := SIZEOF( sCSVLine ) - 1,
putValue := sCSVField, 
pValue := 0,
cbValue := 0,
bCRLF := ( nColumn = MAX_CSV_COLUMNS ));
IF fbWriter.bOk THEN
	
fbWriter.eCmd := eEnumCmd_Next;
ELSE
step := 100;
RETURN;
END_IF
END_FOR
IF RIGHT( sCSVLine, 2 ) = '$R$L' THEN
sCSVLine := REPLACE( sCSVLine, '$L', 2, LEN( sCSVLine ) - 1 );
END_IF
nRow := nRow + 1;//Inkrementieren der Zeile
step := 4;
ELSE	
//Memset(ADR(Database), 0, SIZEOF(Database));
step := 10;
END_IF
 
Die For-Schleife ist für die Spalten. Füge doch eine äußere For-Schleife hinzu, innerhalb der nRow dann incrementiert wird.
 
Zurück
Oben