copy current col to a new current col
copy current col to a new current col
Hello,
can someone tell me how I can get the content of one rveTable.cell.
I want to copy the content of current col to a new current col.
my idea:
procedure TForm1.SpaltenInhaltKopierenClick(Sender: TObject);
var r,c,tSpalte: integer;
begin
try
rveTable.GetEditedCell(r,tSpalte);
strl1.Clear; //TStringList
memo.Color:=clBtnFace;
Application.ProcessMessages;
SendMessage(rve.Handle, WM_SETREDRAW, 0, 0);
for r := 0 to rveTable.Rows.Count-1 do
for c := 0 to rveTable.Rows[r].Count-1 do
if rveTable.Cells[r,c]<>nil then begin
// if c=tSpalte then strl1.add(???);
end;
finally
SendMessage(rve.Handle, WM_SETREDRAW, 1, 0);
memo.color:=clWhite;
end;
end;
procedure TForm1.SpaltenInhaltEinfuegenClick(Sender: TObject);
var r,c,tSpalte: integer;
begin
try
rveTable.GetEditedCell(r,tSpalte);
strl1.Clear;
memo.Color:=clBtnFace;
Application.ProcessMessages;
SendMessage(rve.Handle, WM_SETREDRAW, 0, 0);
for r := 0 to rveTable.Rows.Count-1 do
for c := 0 to rveTable.Rows[r].Count-1 do
if rveTable.Cells[r,c]<>nil then begin
if c=tSpalte then begin
rveTable.EditCell(r,c);
memo.TopLevelEditor.SelectAll;
memo.InsertText(strl1.lines[r]);
end;
end;
finally
SendMessage(rve.Handle, WM_SETREDRAW, 1, 0);
rve.Invalidate;
memo.color:=clWhite;
end;
end;
can someone tell me how I can get the content of one rveTable.cell.
I want to copy the content of current col to a new current col.
my idea:
procedure TForm1.SpaltenInhaltKopierenClick(Sender: TObject);
var r,c,tSpalte: integer;
begin
try
rveTable.GetEditedCell(r,tSpalte);
strl1.Clear; //TStringList
memo.Color:=clBtnFace;
Application.ProcessMessages;
SendMessage(rve.Handle, WM_SETREDRAW, 0, 0);
for r := 0 to rveTable.Rows.Count-1 do
for c := 0 to rveTable.Rows[r].Count-1 do
if rveTable.Cells[r,c]<>nil then begin
// if c=tSpalte then strl1.add(???);
end;
finally
SendMessage(rve.Handle, WM_SETREDRAW, 1, 0);
memo.color:=clWhite;
end;
end;
procedure TForm1.SpaltenInhaltEinfuegenClick(Sender: TObject);
var r,c,tSpalte: integer;
begin
try
rveTable.GetEditedCell(r,tSpalte);
strl1.Clear;
memo.Color:=clBtnFace;
Application.ProcessMessages;
SendMessage(rve.Handle, WM_SETREDRAW, 0, 0);
for r := 0 to rveTable.Rows.Count-1 do
for c := 0 to rveTable.Rows[r].Count-1 do
if rveTable.Cells[r,c]<>nil then begin
if c=tSpalte then begin
rveTable.EditCell(r,c);
memo.TopLevelEditor.SelectAll;
memo.InsertText(strl1.lines[r]);
end;
end;
finally
SendMessage(rve.Handle, WM_SETREDRAW, 1, 0);
rve.Invalidate;
memo.color:=clWhite;
end;
end;
I think you may want to go along the lines of
SourceCell.SaveRVFToStream()
DestinationCell.LoadRVFFromStream()
The thread "Cell Streaming does not save Styles" in this forum has slightly more stuff on this subject. E.g., WhateverCell in the pseudo-code-like example above may need to be a more involved "beast" (RVData or the like).
Michel
SourceCell.SaveRVFToStream()
DestinationCell.LoadRVFFromStream()
The thread "Cell Streaming does not save Styles" in this forum has slightly more stuff on this subject. E.g., WhateverCell in the pseudo-code-like example above may need to be a more involved "beast" (RVData or the like).
Michel
Thank you, but I don't understand your hints because I'm a beginner.
Can you answer my question
if c=tSpalte then strl1.add(content of cell);
(instead of a StringList I can take a delphi-richedit, so that content doesn't loose his attributes),
too ?
It would be nice, if you would write your hint in more detail (I'm a beginner )
PS: Naturally it must be called 'memo.InsertText(strl1.strings[r])' instead of strl1.lines[r];
Can you answer my question
if c=tSpalte then strl1.add(content of cell);
(instead of a StringList I can take a delphi-richedit, so that content doesn't loose his attributes),
too ?
It would be nice, if you would write your hint in more detail (I'm a beginner )
PS: Naturally it must be called 'memo.InsertText(strl1.strings[r])' instead of strl1.lines[r];
Oh, sorry. That was not apparent from the cell-iteration code you presented!Thank you, but I don't understand your hints because I'm a beginner.
That was more or less what I meant. Basically, to save the contents of a cell to some temporary/intermediate storage location/object, you must use a stream (a cell can contain much more than just lines of text, e.g., an entire document with more tables inside). However, you can't use a Delphi TRichEdit as that intermediate storage, that's for sure.(instead of a StringList I can take a delphi-richedit, so that content doesn't loose his attributes)
I can offer small pieces of C++ code as an example of what I meant. You'll have to adapt it to your needs.
Code: Select all
TMemoryStream *MS = new TMemoryStream; // You'll need a stream to transfer cell contents
TRVTableCellData *Cell = Table->Cells[0][0]; // Get somehow to the cell of interest
Cell->SaveRVFToStream(MS, false, clNone, NULL, NULL); // Save it to the stream
TCustomRVData *CRVD = Cell->GetRVData(); // This is an alternative to the above
CRVD->SaveRVFToStream(MS, false, clNone, NULL, NULL);
TRVTableInplaceRVData *CED = (TRVTableInplaceRVData *)Cell->Edit(); // Another alternative
CED->SaveRVFToStream(MS, false, clNone, NULL, NULL);
Now, get somehow to the destination cell Dest and with it:
Code: Select all
MS->Position = 0; // "Rewind" the stream
Dest->LoadRVFFromStream(MS, <...>); // "Stream in" the saved source cell contents
I hope this is starting to make sense. To reiterate, stop thinking of RichView in terms of lists of strings or lines and such. I find it much more useful to think of it as a tree of RVData objects organized into a hierarchy of tables and cells containing more of the same.
Hope this helps,
Michel
-
- Site Admin
- Posts: 17569
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
Thanks again, Michel
Some comments about copying to the stream:
The code above will work only if the cell is not edited.
It will fail if the cell is edited
This is the best method. Will work in all cases, and it is fast.
This method works, but it creates cell inplace editor for the cell, and it is not necessary and relatively slow.
Some comments about copying to the stream:
Code: Select all
// c++
TRVTableCellData *Cell = Table->Cells[0][0];
Cell->SaveRVFToStream(MS, false, clNone, NULL, NULL);
// pascal
var Cell: TRVTableCellData;
Cell := Table.Cells[0,0];
Cell.SaveRVFToStream(MS, False, clNone, nil, nil);
It will fail if the cell is edited
Code: Select all
// c++
TCustomRVData *CRVD = Cell->GetRVData();
CRVD->SaveRVFToStream(MS, false, clNone, NULL, NULL);
// pascal
var CRVD: TCustomRVData;
CRVD := Table.Cells[0,0].GetRVData;
CRVD.SaveRVFToStream(MS, False, clNone, nil, nil);
Code: Select all
//c++
TRVTableInplaceRVData *CED = (TRVTableInplaceRVData *)Cell->Edit(); CED->SaveRVFToStream(MS, false, clNone, NULL, NULL);
// pascal
var CED: TCustomRVFormattedData;
CED := Table.Cells[0,0].Edit;
CED.SaveRVFToStream(MS, False, clNone, nil, nil);
-
- Site Admin
- Posts: 17569
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
Now about writing from stream to the cell.
There are two ways
1) First, using LoadRVFFromStream.
This method cannot be undone/redone and damages undo buffers (as viewer-style method), so call RichViewEdit1.ClearUndo after calling it.
Cell loading does not support styles, so we must turn off style reading from RVF wile loading.
RichViewEdit1 is TDBRichViewEdit, call RichViewEdit1.CanChange before and RichViewEdit1.Change after the operation.
2) Preferred method for editor:
PS: Do not forget to call MS.Free after loading
PPS: Tables already have methods for copying multicell range, but loading it currently has some limitations which will be removed in one of next updates.
There are two ways
1) First, using LoadRVFFromStream.
This method cannot be undone/redone and damages undo buffers (as viewer-style method), so call RichViewEdit1.ClearUndo after calling it.
Cell loading does not support styles, so we must turn off style reading from RVF wile loading.
Code: Select all
var oldps, oldts:TRVFReaderStyleMode;
oldps := RichViewEdit1.RVFParaStylesReadMode;
oldts := RichViewEdit1.RVFTextStylesReadMode;
RichViewEdit1.RVFParaStylesReadMode := rvf_sIgnore;
RichViewEdit1.RVFTextStylesReadMode := rvf_sIgnore;
MS.Position := 0;
DestCell.GetRVData.LoadRVFFromStream(MS, <...>);
RichViewEdit1.RVFParaStylesReadMode := oldps;
RichViewEdit1.RVFTextStylesReadMode := oldts;
2) Preferred method for editor:
Code: Select all
DestCell.Edit;
RichViewEdit1.TopLevelEditor.SelectAll;
RichViewEdit1.TopLevelEditor.InsertRVFFromStreamEd(MS);
PPS: Tables already have methods for copying multicell range, but loading it currently has some limitations which will be removed in one of next updates.
Hello,
you are on another level than I.
Is it therefore not more simply for you to show the correct solution, because people will ask you again if there is an error or they have missunderstand you ?
procedure TForm1.SpalteKopierenClick(Sender: TObject);
var oldps, oldts:TRVFReaderStyleMode;
destCell: TRVTableCellData;
begin
if (not memo.CanChange) or (not memo.GetCurrentItemEx(TRVTableItemInfo, rve, TCustomRVItemInfo(rveTable))) then begin
ShowMessage('Tabelle hat nicht den Focus.');
exit;
end;
//if (not memo.CanChange) then exit; //s.o.
oldps := memo.RVFParaStylesReadMode;
oldts := memo.RVFTextStylesReadMode;
memo.RVFParaStylesReadMode := rvf_sIgnore;
memo.RVFTextStylesReadMode := rvf_sIgnore;
stream1.Position := 0;
//DestCell.GetRVData.LoadRVFFromStream(Stream1, < whatever I write, I get an error >); <<--------------------
{function LoadRVFFromStream(Stream: TStream; var Color: TColor;
Background: TRVBackground; Layout: TRVLayoutInfo):Boolean;}
memo.RVFParaStylesReadMode := oldps;
memo.RVFTextStylesReadMode := oldts;
memo.Change;
end;
procedure TForm1.SpalteEinfuegenClick(Sender: TObject);
var destCell: TRVTableCellData;
begin
if (not memo.CanChange) or (not memo.GetCurrentItemEx(TRVTableItemInfo, rve, TCustomRVItemInfo(rveTable))) then begin
ShowMessage('Tabelle hat nicht den Focus.');
exit;
end;
// because of error in procedure TForm1.SpalteKopierenClick
DestCell.Edit;
memo.TopLevelEditor.SelectAll;
memo.TopLevelEditor.InsertRVFFromStreamEd(Stream1);
//Stream1 created and free in form1.activate and form1.close
end;
you are on another level than I.
Is it therefore not more simply for you to show the correct solution, because people will ask you again if there is an error or they have missunderstand you ?
procedure TForm1.SpalteKopierenClick(Sender: TObject);
var oldps, oldts:TRVFReaderStyleMode;
destCell: TRVTableCellData;
begin
if (not memo.CanChange) or (not memo.GetCurrentItemEx(TRVTableItemInfo, rve, TCustomRVItemInfo(rveTable))) then begin
ShowMessage('Tabelle hat nicht den Focus.');
exit;
end;
//if (not memo.CanChange) then exit; //s.o.
oldps := memo.RVFParaStylesReadMode;
oldts := memo.RVFTextStylesReadMode;
memo.RVFParaStylesReadMode := rvf_sIgnore;
memo.RVFTextStylesReadMode := rvf_sIgnore;
stream1.Position := 0;
//DestCell.GetRVData.LoadRVFFromStream(Stream1, < whatever I write, I get an error >); <<--------------------
{function LoadRVFFromStream(Stream: TStream; var Color: TColor;
Background: TRVBackground; Layout: TRVLayoutInfo):Boolean;}
memo.RVFParaStylesReadMode := oldps;
memo.RVFTextStylesReadMode := oldts;
memo.Change;
end;
procedure TForm1.SpalteEinfuegenClick(Sender: TObject);
var destCell: TRVTableCellData;
begin
if (not memo.CanChange) or (not memo.GetCurrentItemEx(TRVTableItemInfo, rve, TCustomRVItemInfo(rveTable))) then begin
ShowMessage('Tabelle hat nicht den Focus.');
exit;
end;
// because of error in procedure TForm1.SpalteKopierenClick
DestCell.Edit;
memo.TopLevelEditor.SelectAll;
memo.TopLevelEditor.InsertRVFFromStreamEd(Stream1);
//Stream1 created and free in form1.activate and form1.close
end;
I can only fluently write in C++, and it may not be of much help, so I'll leave the challenge up to Sergey!
The point you seem to be missing though is that the code snippets we have suggested are just that - the most crucial pieces that are supposed to be integrated into your original code from your first post.
In the last code you posted you were obviously missing
DestCell := rveTable.Cells[r, c];
or similar. But this and all that stuff needs to go into your original functions - where you do somehow get the r and c of interest.
Sorry if I can't offer a complete solution.
Michel
The point you seem to be missing though is that the code snippets we have suggested are just that - the most crucial pieces that are supposed to be integrated into your original code from your first post.
In the last code you posted you were obviously missing
DestCell := rveTable.Cells[r, c];
or similar. But this and all that stuff needs to go into your original functions - where you do somehow get the r and c of interest.
Sorry if I can't offer a complete solution.
Michel
Hello Michel,
I am happy that you (or other people) give me a hint so that I further can go on at my work (if I could convert the hints). Often it is so that one only gets some code, which can't be used in lack of experience or knowledge.
In this case you/Sergey use a shortened call (DestCell.GetRVData.LoadRVFFromStream(MS, <...>)).
I looked up for the parameters in RVData.pas
(function LoadRVFFromStream(Stream: TStream; var Color: TColor;
Background: TRVBackground; Layout: TRVLayoutInfo):Boolean
and tried it with them. The result is an error.
In addition that I am not sure if I set the code correctly in my program I think that often it is better for both sides (and the inexperienced readers of the question) that helper give an executable code (with call).
Here I would thank expressly Sergey for his many helps and I hope that he doesn't understand my inquiring as beef.
Jürgen
I am happy that you (or other people) give me a hint so that I further can go on at my work (if I could convert the hints). Often it is so that one only gets some code, which can't be used in lack of experience or knowledge.
In this case you/Sergey use a shortened call (DestCell.GetRVData.LoadRVFFromStream(MS, <...>)).
I looked up for the parameters in RVData.pas
(function LoadRVFFromStream(Stream: TStream; var Color: TColor;
Background: TRVBackground; Layout: TRVLayoutInfo):Boolean
and tried it with them. The result is an error.
In addition that I am not sure if I set the code correctly in my program I think that often it is better for both sides (and the inexperienced readers of the question) that helper give an executable code (with call).
Here I would thank expressly Sergey for his many helps and I hope that he doesn't understand my inquiring as beef.
Jürgen
Hey there!
I haven't tried it, but I think that call should go something like this:
If that's not what you have tried, try this. If it still gives you trouble, let us know what the exact results/problems are (e.g., when you say "error" - what is it?). Perhaps once you have hit the proverbial "brick wall" it'd be time for you to re-post your latest code (so that Sergey could take a look ).
All this stuff takes a little time to wrap one's head around, so don't give up. Good luck!
Michel
I haven't tried it, but I think that call should go something like this:
Code: Select all
var DummyColor: TColor;
LoadRVFFromStream(MS, DummyColor, nil, nil);
All this stuff takes a little time to wrap one's head around, so don't give up. Good luck!
Michel
-
- Site Admin
- Posts: 17569
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
Copying the column SourceCol to the column DestCol.
This method works for all RichViews, not only for the editors.
It cannot be undone/redone.
Example of call (I assume that you already assigned table variable):
Example of call for DBRichViewEdit:
Code: Select all
procedure CopyTableColumn(rv: TCustomRichView; table: TRVTableItemInfo;
SourceCol, DestCol: Integer);
var r: Integer;
Stream: TMemoryStream;
UnusedColor: TColor;
oldps, oldts:TRVFReaderStyleMode;
begin
if SourceCol=DestCol then
exit;
UnusedColor := clNone;
oldps := rv.RVFParaStylesReadMode;
oldts := rv.RVFTextStylesReadMode;
rv.RVFParaStylesReadMode := rvf_sIgnore;
rv.RVFTextStylesReadMode := rvf_sIgnore;
try
for r := 0 to table.Rows.Count-1 do
if (table.Cells[r, SourceCol]<>nil) and
(table.Cells[r, DestCol]<>nil) then begin
Stream := TMemoryStream.Create;
try
table.Cells[r, SourceCol].GetRVData.SaveRVFToStream(Stream,
False, UnusedColor, nil, nil);
Stream.Position := 0;
table.Cells[r, DestCol].GetRVData.LoadRVFFromStream(Stream,
UnusedColor, nil, nil);
finally
Stream.Free;
end;
end;
finally
rv.RVFParaStylesReadMode := oldps;
rv.RVFTextStylesReadMode := oldts;
end;
end;
It cannot be undone/redone.
Example of call (I assume that you already assigned table variable):
Code: Select all
CopyTableColumn(RichViewEdit1, table, 0, 1);
RichViewEdit1.ClearUndo;
RichViewEdit1.Format;
Code: Select all
if DBRichViewEdit1.CanChange then begin
CopyTableColumn(DBRichViewEdit1, table, 0, 1);
DBRichViewEdit1.ClearUndo;
DBRichViewEdit1.Change;
DBRichViewEdit1.Format;
Last edited by Sergey Tkachenko on Sun Nov 06, 2005 10:05 pm, edited 1 time in total.
-
- Site Admin
- Posts: 17569
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
This method can be called only for editors, and it can be undone/redone by the user.
Calling is the same for DBRichViewEdit and RichViewEdit:
Since editing-style method is used (InsertText), CanChange+Change+ClearUndo+Format are not required.
PS: Modifying RVFParaStylesReadMode and RVFTextStylesReadMode is not required in this method, but makes loading faster a bit.
Code: Select all
procedure CopyTableColumnEd(rv: TCustomRichViewEdit; table: TRVTableItemInfo;
SourceCol, DestCol: Integer);
var r: Integer;
Stream: TMemoryStream;
UnusedColor: TColor;
oldps, oldts:TRVFReaderStyleMode;
begin
if SourceCol=DestCol then
exit;
UnusedColor := clNone;
oldps := rv.RVFParaStylesReadMode;
oldts := rv.RVFTextStylesReadMode;
rv.RVFParaStylesReadMode := rvf_sIgnore;
rv.RVFTextStylesReadMode := rvf_sIgnore;
SendMessage(rv.Handle, WM_SETREDRAW, 0, 0);
try
for r := 0 to table.Rows.Count-1 do
if (table.Cells[r, SourceCol]<>nil) and
(table.Cells[r, DestCol]<>nil) then begin
Stream := TMemoryStream.Create;
try
table.Cells[r, SourceCol].GetRVData.SaveRVFToStream(Stream,
False, UnusedColor, nil, nil);
Stream.Position := 0;
table.Cells[r, DestCol].Edit;
rv.TopLevelEditor.SelectAll;
rv.TopLevelEditor.InsertRVFFromStreamEd(Stream);
finally
Stream.Free;
end;
end;
finally
rv.RVFParaStylesReadMode := oldps;
rv.RVFTextStylesReadMode := oldts;
SendMessage(rv.Handle, WM_SETREDRAW, 1, 0);
while rv<>nil do begin
rv.Invalidate;
rv := TCustomRichViewEdit(rv.InplaceEditor);
end;
end;
end;
Code: Select all
CopyTableColumn(RichViewEdit1, table, 0, 1);
PS: Modifying RVFParaStylesReadMode and RVFTextStylesReadMode is not required in this method, but makes loading faster a bit.
You never sleep, Sergey, do you?
Just a little question for my own understanding: why is it necessary (especially in this example) to set RVF*StylesReadMode := rvf_sIgnore? Here's why I'm asking:
A) As we have discussed earlier in the "Cell Streaming does not save Styles" thread, SaveRVFToStream() doesn't appear to be saving any styles to the stream, so there should be nothing to ignore, and
B) The saving/loading operations are obviously within the same RichView, so "incoming" styles (if any) would be the same ones we already have, so we can't get any problems with styles "overlapping" or missing.
I suspect that I am overlooking some subtle (or not) problem, so I would greatly appreciate it if you could explain this.
Thanks!
Michel
Just a little question for my own understanding: why is it necessary (especially in this example) to set RVF*StylesReadMode := rvf_sIgnore? Here's why I'm asking:
A) As we have discussed earlier in the "Cell Streaming does not save Styles" thread, SaveRVFToStream() doesn't appear to be saving any styles to the stream, so there should be nothing to ignore, and
B) The saving/loading operations are obviously within the same RichView, so "incoming" styles (if any) would be the same ones we already have, so we can't get any problems with styles "overlapping" or missing.
I suspect that I am overlooking some subtle (or not) problem, so I would greatly appreciate it if you could explain this.
Thanks!
Michel
-
- Site Admin
- Posts: 17569
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
Well, really, if RVF does not contain styles, it's not necessary to set modes to ignore.
In the second example, it is not necessary because editor.InsertRVFFromStreamEd supports styles. But... In the ignore mode, the i-th style in RVF is mapped to the i-th style of document. In the merge mode, the component first tries to find the existing style equal to the style from RVF. If all styles are unique (which is normal), the i-th style will be mapped to the i-th style. But if, for some reason, they are not unique, it will be mapped to another style (visually the same, though). Exception: list styles are mapped to the same list styles when copying from the same document (it's not necessary for numbering to be unique). So, the ignore mode has 2 benefits: it is faster, and it guarantees the exact copy of the original.
In the second example, it is not necessary because editor.InsertRVFFromStreamEd supports styles. But... In the ignore mode, the i-th style in RVF is mapped to the i-th style of document. In the merge mode, the component first tries to find the existing style equal to the style from RVF. If all styles are unique (which is normal), the i-th style will be mapped to the i-th style. But if, for some reason, they are not unique, it will be mapped to another style (visually the same, though). Exception: list styles are mapped to the same list styles when copying from the same document (it's not necessary for numbering to be unique). So, the ignore mode has 2 benefits: it is faster, and it guarantees the exact copy of the original.