StringGrid.SaveToFile creating XML files rather than simple CSV files lazarus / 31-LCL ---------------------------------------------------------------------- Gizmo · 2011-08-12 21:11 Hi I have a StringGrid with two columns of data. I'm using StringGrid1.SaveToFile(MyFile.txt); to output the content of the grid to a file. But rather than the MyFile.txt file being a simple deliminated file of two values seperated by a ',', it's an XML file. I just want a simple text file with the following layout : Column1Content,Column2Content Am I doing something wrong with SaveToFile or is that it's only mode? Ted ---------------------------------------------------------------------- IPguy · 2011-08-13 01:44 FYI - I just found this article titled: ...save a StringGrid as a CSV file? http://www.swissdelphicenter.ch/en/showcode.php?id=1743 ---------------------------------------------------------------------- IPguy · 2011-08-13 01:54 Or, you could dump each comma delimited line from the StringGrid into a Memo, then save the memo as a .csv file. And I can think of a few more ways, but most require that you move away from the .savetofile method. Did you set the DelimitedText property before calling .savetofile? "Get or set the list via a big string. This string will have the list strings separated by the Delimiter value (default is a comma). Strings containing embedded blanks must be enclosed in the QuoteChar (default is "). " Here is another interesting page: http://www.delphipages.com/forum/archive/index.php/t-153170.html ---------------------------------------------------------------------- Gizmo · 2011-08-14 18:32 Hi I'd read that first link already having Googled the issue before posting, but I thought it seemed a bit tricky overall, given my aims. I often find out there's an easier way to code something, having spent ages trying to do it another way. So I hoped I might be missing the obvious. I guess what I don't quite understand is that, if I can just Ctrl + C all the cells of my two column StringGrid that is displayed in my program and then paste that into Excel (which I can do currently), the values are obviously stored in memory like that - i.e. two columns of data with lots of rows. So why, when I want to export that same memory resident data to a file, do I end up with an XML file? The SaveToFile procedure is obviously converting my simple data from a form that I actually want it in and already have it in, into a form that I don't want it in. So is there not a way to just ask SaveToFile to "don't convert to xml?" ---------------------------------------------------------------------- mas steindorff · 2011-08-14 20:20 You have set something  different from standard install or how you import your data into the tstrings.   I create  CVS with tstrings all of the time.  I was wondering if the tstring  could  create an xml  directly  or if I needed to translate it's contents across. (Like you have) ---------------------------------------------------------------------- Gizmo · 2011-08-14 21:23 Hui Well maybe we can exchange ideas! I have no idea how I have set mine to the non-default. I'm using Lazarus 0.9.30 on Ubuntu 10.04 using FPC 2.4.2. The relevant parts of my code are : Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i ...var  SizeOfFile : int64;  NameOfFileToHash, fileHashValue, PercentageProgress : string;  FI : TFileIterator;                      //File Iterator class  SG : TStringGrid;                                                               begin  FI := TFileIterator.Create;  SG := TStringGrid.Create(self);    ...//Stuff done here   // StringGrid Elements:      StringGrid1.rowcount:= FileCounter+1;      StringGrid1.Cells[0,FileCounter] := IntToStr(FileCounter);      Stringgrid1.Cells[1,FileCounter] := NameOfFileToHash;      Stringgrid1.Cells[2,FileCounter] := UpperCase(fileHashValue);            Application.ProcessMessages;      ...end  How do you do things differently to get CSV by default? Thanks Ted ---------------------------------------------------------------------- mas steindorff · 2011-08-15 22:03 I think I see the difference.  I was thinking the stringgrid used a TStringlist for storage and "savetofile" but it may be different.  my code looks like this without the try..finally and getdata stuff: Code: [Select]... var tstr:TStringlist; str:string begin tstr := Tstringlist.create(); tstr.add(HeaderString);  //  := 'Var1,Var2,Var3,Var4';   ...   loop    str := format('%d,%d,%d,%d',[v1,v2,v3,v4]);    tstr.add(str);  // simple ------ or to add another Tstringlist ---   tstr.addstrings(TstrLineOfData); ----   endofloop  tstr.savetofile(CVS_filename);  tstr.free; end; sometimes I use something like..   str:= timestr + ',' + tstrLine.commatext;   Tstr.add(str); and I don't even change the tstr.delimiter or .delinitertext properties and I still get one line per .add() in the final file. you may be able to transfer a line at a time from the grid to a tstringlist or someone may answer your original question ---------------------------------------------------------------------- Gizmo · 2011-08-20 21:48 Well this is defeating me. I've spent another two hours this evening trying to work it out. There must be an easier way than the many variation I've read about (using AssignFile etc). Does nobody here export the data of StringGrids, specifically, to files? If so, how are you doing it? ---------------------------------------------------------------------- Scoops · 2011-08-20 23:17 This is a quick way that i save my stringgrids, probably not the best way, or maybe what you want, but it works for me ... Code: [Select]procedure TForm1.Button1Click(Sender: TObject); var col : integer; var row : integer; string1 : string; file1 : TStringlist; begin file1 := TStringList.Create; file1.Sorted := True; file1.Duplicates := dupIgnore; file1.CaseSensitive := True; for row := 0 to stringgrid1.RowCount - 1 do begin string1 := '';   for col := 0 to stringgrid1.ColCount - 1 do   begin   string1 := string1 + stringgrid1.Cells [col,row];   if col < stringgrid1.ColCount - 1 then string1 := string1 + ',';   end; file1.Add(string1);   end; file1.SaveToFile(ExtractFilePath(Application.ExeName) + 'test.csv'); file1.Free; end; ---------------------------------------------------------------------- Dick, from the internet · 2011-08-21 00:31 Not as elegant as posted by Scoops, but does the job: Code: [Select]   var i : integer;      str : string; begin  memo1.Lines.Clear;   for i := 1 to StringGrid1.RowCount - 1 do    begin      str := StringGrid1.Cells[1,i] + ',' + StringGrid1.Cells[2,i];      memo1.Lines.Add(str);    end;   memo1.Lines.SaveToFile('output.csv'); end; ---------------------------------------------------------------------- Gizmo · 2011-09-03 21:05 Deepest thanks to JesusRMX from the IRC forum whoi kindly pointed out that the solution was simple this : Code: [Select]StringGrid1.rows[1].savetofile('/home/ted/test.txt'); Apparently, though a StringGrid is a StringGrid, the 'SG.rows' element is actually a StringList within a StringGrid (http://wiki.lazarus.free pascal.org/Grids_Reference_Page#property_Rows.5Bindex:_Integer.5D:_TSt rings_read_GetRows_write_SetRows.3B) Or, you can do this: Code: [Select]StringGrid1.Cols[X].savetofile('/home/ted/test.txt');  // where X = your column index, e.g 1, 2 or 3 Now I just need to work out how to get it to fill the whole file with the content of the whole grid, as opposed to just the last row, or last column! It's very frustrating.  Because this : Code: [Select]StringGrid1.Cols[0].savetofile('/home/ted/test.txt'); StringGrid1.Cols[1].savetofile('/home/ted/test.txt'); StringGrid1.Cols[2].savetofile('/home/ted/test.txt');  Results in the last column (No 2) been in the file, but columns 1 and 0 get wiped out. ---------------------------------------------------------------------- jesusr · 2011-09-05 02:28 grid.SaveToCSVFile and grid.LoadFromCSVFile methods were added to StringGrid in Lazarus r32179, they are documented here: http://wiki.la zarus.freepascal.org/Grids_Reference_Page#procedure_SaveToCSVFile.28AF ileName:_string.3B_ADelimiter:Char.3D.27.2C.27.3B_WithHeader:boolean.3 Dtrue.29.3B ---------------------------------------------------------------------- User137 · 2011-09-05 04:31 savetofile() always starts from beginning of file, you can't use it to continue writing. Modifying above code a little: Code: [Select]var i : integer;     sl : TStringList; begin   sl:=TStringList.Create;   for i := 1 to StringGrid1.RowCount - 1 do     sl.Add(StringGrid1.Rows[i].Text);   sl.SaveToFile('output.csv');   sl.Free; end;Did i miss something? This is completely untested code, but you said Rows[] are TStringList's so this should work. ---------------------------------------------------------------------- Gizmo · 2011-09-05 11:34 Thanks Jesus... User137 - thanks for that. I will give it a try tonight and report back. Yes - as I understand it from the links above, the rows and column elements of a StringGrid are actually 'just' the simpler StringLists. So I will give your code snippet a go. I always got muddled up with for loops when dealing with streams, so thanks for the code. ---------------------------------------------------------------------- Gizmo · 2011-09-05 19:19 Thanks man! That has worked. I just need to tweak it a bit to get the final output I want, but yes, that outputs each row of my StringGrid into a file. Very much appreciated. ---------------------------------------------------------------------- Gizmo · 2011-09-13 22:17 Jesus Further to our chat in IRC 2 days ago, this works! I had to update my Lazarus install from 0.9.30 to 0.9.31 as expected but that step caused me considerable headaches (see this http://www.lazarus.freepascal.org/ index.php/topic,14615.msg77518.html#msg77518 if interested). I eventually got that sorted and now running Lazarus 0.9.31 with FPC 2.5.1 and, as you rightly pointed out, adding Stringgrid1.SaveToCSVFile('/home/ted/test.csv');    works a treat! I am very appreciative for you doing this for me and the rest of the community who will no doubt benefit greatly from this. Ted