View Issue Details
|ID||Project||Category||View Status||Date Submitted||Last Update|
|0027443||Lazarus||LCL||public||2015-02-11 11:22||2015-04-29 11:03|
|Reporter||Maris-S||Assigned To||Jesus Reyes|
|Platform||Windows||OS||Windows||OS Version||Windows 7 PRO|
|Product Version||1.2.6||Product Build|
|Target Version||1.6||Fixed in Version||1.5 (SVN)|
|Summary||0027443: TStringGrid.LoadFromCsvFile can't handle multiline cells.|
|Description||TStringGrid.LoadFromCsvFile can't handle csv files which contains cells with multiline text ("Line1\r\nLine2").|
|Additional Information||Attached example program contains two string grids. First grid is filled with texts on form create, where 2nd column contains 2 lines text, separated with LineEnding. Row height is adjusted.|
By pressing button "Save and Load" csv file is created in program current directory (file name multiline.csv), which contains 1St string grid results, after saving csv file is loaded into 2nd string grid with method LoadFromCsvFile.
Results in 2nd grid are mess. Each new line in cells goes to next row and leaves 2nd quote symbol.
Problem is because there is no check if new line symbol is between text delimiter symbols. Saving csv file works very good. Text delimiter symbols are placed where they are necessary, and opening file in any other software capable to deal with csv files, like Open/Libre office, works fine.
This bug makes method LoadFromCsvFile useless when csv file contains multiline values.
|Tags||No tags attached.|
|Fixed in Revision||48780|
LoadMultiline.zip (3,053 bytes)
Problem is that the grid itself cannot handle multi-line content in a single cell.
If this is fixed then this issue can be fixed as well, and possibly the cvs hnadling could be done using csvdocument to harmonize csv handling across Laz/Fpc.
Current csv handling in TStringGrid already is/was a workaround.
It's not really true that grid cannot handle multi-line content. Yes, it's necessary to do something like workaround with TStringGrid.Canvas.TextStyle, what is done in attached program, but problem is not about displaying multi-line content in Grid itself, problem is about loading csv file and placing text in cell where it suppose to be placed.
Even without Canvas workaround Grid still can hold multi-line text in cell. Yes, this text will be displayed in one line, you will not see new line characters, but string itself will contain new line symbols like \n and \r (depends on OS).
The problem is that each new line symbol in csv file is considered as new line/row, even if it's delimited by quotes.
Imagine such lines in csv:
2nd column has multi-line text "Text2\nText22", it's quoted so suppose to go in one cell, but it is not new row. It doesn't meter if StringGrid will be able to display it correctly, the question is about csv logic. Even if StringGrid can't display line breaks in the cell, it would be more correct to put multi-line text in one cell then breaking csv logic. So this cell should contain text "Text2\nText22", but it would be displayed like "Text2Text22", because new line symbol is invisible (without workarounds of course).
||Use csvdocument to read the file, it does respect cells with quoted line breaks correctly. (I never liked the idea of putting reading/writing code into visual controls such as a StringGrid)|
||WP, I think you are right. I would say it would be better to remove such code form this component, if it does not work correctly, or at least to make a note in documentation.|
I agree with WP.
But we can only do this when csvdocument is part of either Lazarus (my preference) or Fpc/FCL.
Currenlty it is in Lazarus CCR, so we cannot bind to it.
Still the issue of displaying multiline strings in a cell needs attention.
The fact that TStringGrid does not display it correctly made me decide to not implement this when I implemented current CSV handling.
I don't see an issue with displaying multiline strings in a cell: Just prepare the TextStyle of the grid's canvas accordingly:
procedure TForm1.FormCreate(Sender: TObject);
StringGrid1.Cells[1,1] := 'Line 1' + LineEnding + 'Line 2';
procedure TForm1.StringGrid1PrepareCanvas(sender: TObject; aCol, aRow: Integer;
ts := StringGrid1.Canvas.TextStyle;
ts.Wordbreak := true;
ts.SingleLine := false;
StringGrid1.Canvas.TextStyle := ts;
Yes, displaying multi-line is possible, but as mentioned before it's not about displaying, but about following correct line-column sequence while reading csv.
I made some tests with saving and loading StringGrid data.
TStringGrid.SaveToFile and TStringGrid.LoadFromFile works correctly. It stores data in xml and reads everything correctly, but it's super slow! Working with 17000 row (12 column) list is impossible as I need auto-save, which is done after each line processing, looks like even normal save when editing is finished is impossible. TStringGrid.SaveToCSVFile works correctly and super fast, even can't notice any delay while saving. So SaveToCSVFile is best for saving.
Reading with CSVDocument is much slower then TStringGrid.LoadFromCSVFile, but it works correctly and this delay is acceptable anyway, progress bar also is possible. So looks like best at the moment is to use TStringGrid.SaveToCSVFile for saving file and CSVDocument for file reading.
I'm not sure if it's good idea to implement reading/writing code into visual controls, but at least csv reading and writing methods in TCustomStringGrid looks very promising because of performance, only problem is that reading is useless for multi-line text. So it's up to developers if it's necessary to implement bug correction for it. Looks like bug is in TCustomStringGrid.LoadFromCSVStream method where reading is done.
> Reading with CSVDocument is much slower then TStringGrid.LoadFromCSVFile
Did you enclose the CSVDocument reading code by BeginUpdate/EndUpdate? It avoids unnecessary redraws when adding cells.
I did, yes. It becomes a bit faster when adding all rows to string grid before parsing csv, instead of adding row by row when needed, but it's not a solution, because files has different row count, from tens to thousands.
Even TCSVDocument.LoadFromFile (grid is not involved) is a bit slower then TStringGrid.LoadFromCSVFile. I suppose CSVDocument involves more checks while parsing csv, it makes it a bit slower, but at the same time parsing is made correctly.
> I don't see an issue with displaying multiline strings in a cell:
> Just prepare the TextStyle of the grid's canvas accordingly:
It shoud work "out of the box" IMO.
CSVDocument now is in fpc 3.1.1. (see 0024739).
So, we need to wait until fpc 3.2 (?) until we can use this.
|2015-02-11 11:22||Maris-S||New Issue|
|2015-02-11 11:22||Maris-S||File Added: LoadMultiline.zip|
|2015-02-11 11:54||Bart Broersma||Note Added: 0080953|
|2015-02-11 15:12||Maris-S||Note Added: 0080955|
|2015-02-11 15:13||Maris-S||Note Edited: 0080955||View Revisions|
|2015-02-11 15:14||Maris-S||Note Edited: 0080955||View Revisions|
|2015-02-11 15:54||wp||Note Added: 0080956|
|2015-02-11 16:06||Maris-S||Note Added: 0080957|
|2015-02-11 18:42||Bart Broersma||Note Added: 0080960|
|2015-02-11 22:08||wp||Note Added: 0080966|
|2015-02-11 22:08||wp||Note Edited: 0080966||View Revisions|
|2015-02-12 09:38||Maris-S||Note Added: 0080975|
|2015-02-12 09:41||Maris-S||Note Edited: 0080975||View Revisions|
|2015-02-12 10:24||wp||Note Added: 0080979|
|2015-02-12 10:52||Maris-S||Note Added: 0080980|
|2015-02-12 19:18||Bart Broersma||Note Added: 0081003|
|2015-04-01 19:43||Jesus Reyes||Assigned To||=> Jesus Reyes|
|2015-04-01 19:43||Jesus Reyes||Status||new => assigned|
|2015-04-04 13:11||Bart Broersma||Note Added: 0082579|
|2015-04-20 20:20||Jesus Reyes||Fixed in Revision||=> 48780|
|2015-04-20 20:20||Jesus Reyes||LazTarget||=> 1.6|
|2015-04-20 20:20||Jesus Reyes||Note Added: 0083067|
|2015-04-20 20:20||Jesus Reyes||Status||assigned => resolved|
|2015-04-20 20:20||Jesus Reyes||Fixed in Version||=> 1.5 (SVN)|
|2015-04-20 20:20||Jesus Reyes||Resolution||open => fixed|
|2015-04-20 20:20||Jesus Reyes||Target Version||=> 1.6|