esk
asked on
copy,paste in listview
i know this is difficult question.
But i tray ask.
my Delphi app has listview and i want to be able to copy paste
( with multivalues to )
ESK
But i tray ask.
my Delphi app has listview and i want to be able to copy paste
( with multivalues to )
ESK
Listening
also listening..
Go to bed Barry!!!! :-)
if the list view is to contain files i can point you toward:
http://ftp/d20free/fileexpl.zip
copy/cut/paste etc..
for not files then i have no idea...
http://ftp/d20free/fileexpl.zip
copy/cut/paste etc..
for not files then i have no idea...
Hmm, for Copy you could create a TStringList. Loop through all items. For those that are selected construct a string like [Caption]#9[SubItem1]#9[Su bItem2]...
and add it to the TStringList.
Then throw it on the clipboard like so:
Clipboard.Text := StringList.Text;
For paste, create a TStringList and set it's Text property from the clipboard. Now loop through the stringlist, and add a TListItem for each item in the stringlist. You'll need Pos, Copy and Delete to pull each string apart.
Cheers,
Phil.
and add it to the TStringList.
Then throw it on the clipboard like so:
Clipboard.Text := StringList.Text;
For paste, create a TStringList and set it's Text property from the clipboard. Now loop through the stringlist, and add a TListItem for each item in the stringlist. You'll need Pos, Copy and Delete to pull each string apart.
Cheers,
Phil.
ASKER
example? philipleighs
It all depends on what needs to be copied and pasted and which customers will also use the clipboard data. If only the listview is producer and consumer then pick any comfortable format (Phil has suggested one). In any other case you should go with the default formats like CF_TEXT, CF_HDROP etc.
Please tell me how you would like to have it implemented.
Ciao, Mike
Please tell me how you would like to have it implemented.
Ciao, Mike
ASKER
Adjusted points to 300
ASKER
i want to be able to choose more than one line
(Multiselect) and press CTRL-C or popupmenu to choose copy , after that i want to select where i want to paste this line(s) thats all -- thanks. 300 points
(Multiselect) and press CTRL-C or popupmenu to choose copy , after that i want to select where i want to paste this line(s) thats all -- thanks. 300 points
Well, here's code to collect a string of all selected items and their subitems and send them to clipboard.
procedure TMainForm.CopyClick(Sender : TObject);
var
Item: TListItem;
Count: Integer;
S: String;
begin
with ListView1 do
if SelCount > 0 then
begin
Item := Selected;
Count := SelCount;
S := '';
while Count > 0 do
begin
S := S + Item.Caption + #9 + Item.SubItems.CommaText + #13;
Dec(Count);
end;
Clipboard.SetTextBuf(PChar (S));
end;
end;
If you simply want the lines (as you wrote at last) then this is all you need. Just paste the clipboard where ever you like.
Ciao, Mike
procedure TMainForm.CopyClick(Sender
var
Item: TListItem;
Count: Integer;
S: String;
begin
with ListView1 do
if SelCount > 0 then
begin
Item := Selected;
Count := SelCount;
S := '';
while Count > 0 do
begin
S := S + Item.Caption + #9 + Item.SubItems.CommaText + #13;
Dec(Count);
end;
Clipboard.SetTextBuf(PChar
end;
end;
If you simply want the lines (as you wrote at last) then this is all you need. Just paste the clipboard where ever you like.
Ciao, Mike
Well, here's code to collect a string of all selected items and their subitems and send them to clipboard.
procedure TMainForm.CopyClick(Sender : TObject);
var
Item: TListItem;
I, Count: Integer;
S: String;
begin
with ListView1 do
if SelCount > 0 then
begin
Count := SelCount;
S := '';
I := 0;
while (I < Items.Count) and (Count > 0) do
begin
Item := Items[I];
if Item.Selected then
begin
S := S + Item.Caption + #9 + Item.SubItems.CommaText + #13;
Dec(Count);
end;
Inc(I);
end;
Clipboard.SetTextBuf(PChar (S));
end;
end;
If you simply want the lines (as you wrote at last) then this is all you need. Just paste the text from the clipboard whereever you like.
Ciao, Mike
procedure TMainForm.CopyClick(Sender
var
Item: TListItem;
I, Count: Integer;
S: String;
begin
with ListView1 do
if SelCount > 0 then
begin
Count := SelCount;
S := '';
I := 0;
while (I < Items.Count) and (Count > 0) do
begin
Item := Items[I];
if Item.Selected then
begin
S := S + Item.Caption + #9 + Item.SubItems.CommaText + #13;
Dec(Count);
end;
Inc(I);
end;
Clipboard.SetTextBuf(PChar
end;
end;
If you simply want the lines (as you wrote at last) then this is all you need. Just paste the text from the clipboard whereever you like.
Ciao, Mike
Mmmh, I don't know why the first post went through, but you should ignore it as it doesn't advance in the items list.
Ciao, Mike
Ciao, Mike
ASKER
what type "Clipboard" uses ? to assign, undeclare intentifier, can you give me paste code to?
Clipboard is a global object defined in the unit Clipbrd.pas. You need to add it to the uses clause of the form where the code is in.
For the paste code: How would you like to have the stuff pasted? Do want to paste it into the listview back (creating so new items) or would you like to have it in a memo or similar control which can hold text?
Ciao, Mike
For the paste code: How would you like to have the stuff pasted? Do want to paste it into the listview back (creating so new items) or would you like to have it in a memo or similar control which can hold text?
Ciao, Mike
ASKER
paste it into listview back, i choose lets say three
items and select copy and go anywhere in the listview and paste other three lines in ( anywhere i like )
i have three lines of text and want to make ten copyes quickly i choose copy , paste*10
Esk
items and select copy and go anywhere in the listview and paste other three lines in ( anywhere i like )
i have three lines of text and want to make ten copyes quickly i choose copy , paste*10
Esk
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
paste it into listview back, i choose lets say three
items and select copy and go anywhere in the listview and paste other three lines in ( anywhere i like )
i have three lines of text and want to make ten copyes quickly i choose copy , paste*10
Esk
items and select copy and go anywhere in the listview and paste other three lines in ( anywhere i like )
i have three lines of text and want to make ten copyes quickly i choose copy , paste*10
Esk
ASKER
this work, but there are some bugs left.
i choose many items and do copy - paste some text came as &/&%/%$
i want to select where i want to paste the texts ( choose any item and the text will be addedd one down , not the bottom
Esk
i choose many items and do copy - paste some text came as &/&%/%$
i want to select where i want to paste the texts ( choose any item and the text will be addedd one down , not the bottom
Esk
ASKER
Adjusted points to 400
ASKER
Increase To 400
:-) DOn't do a refresh with the explorer refresh button or it will resend the last comment. Use the link in the upper right corner (Reload Question).
Ciao, Mike
Ciao, Mike
Sorry fogot to adjust the code for insertion. Replace the line:
Item := Items.Add;
with
Item := Items.Insert(Selected.Inde x + 1);
This should do the job. For the bug: Is there a way you can surely reproduce it (exact steps)?
Ciao, Mike
Item := Items.Add;
with
Item := Items.Insert(Selected.Inde
This should do the job. For the bug: Is there a way you can surely reproduce it (exact steps)?
Ciao, Mike
ASKER
when i copy more than 4 lines the code always add "," this char. and more to.
can you fix this problem?
do you have to copy the data to clipboard?
can't you just copy the data to array?
Esk
can you fix this problem?
do you have to copy the data to clipboard?
can't you just copy the data to array?
Esk
ASKER
when i copy more than 4 lines the code always add "," this char. and more to.
can you fix this problem?
do you have to copy the data to clipboard?
can't you just copy the data to array?
Esk
can you fix this problem?
do you have to copy the data to clipboard?
can't you just copy the data to array?
Esk
Esk, sorry when I was to stupid to understand your true problem. I read copy and paste and automatically involved the clipboard. Of course you don't need the clipboard at all when you just want to copy items within the list view. Here's the code:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, ComCtrls;
type
TForm1 = class(TForm)
ListView1: TListView;
procedure ListView1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
private
FCache: array of TListItem;
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.ListView1KeyDown(Se nder: TObject; var Key: Word;
Shift: TShiftState);
var
I,
Count: Integer;
Item: TListItem;
begin
if Shift = [ssCtrl] then
begin
case Key of
Ord('C'):
with ListView1 do
if SelCount > 0 then
begin
Count := SelCount;
SetLength(FCache, Count);
I := 0;
while (I < Items.Count) and (Count > 0) do
begin
if Items[I].Selected then
begin
Dec(Count);
FCache[Count] := Items[I];
end;
Inc(I);
end;
end;
Ord('V'):
with ListView1 do
begin
for I := 0 to High(FCache) do
begin
if Assigned(Selected) then Item := Items.Insert(Selected.Inde x)
else Item := Items.Add;
Item.Assign(FCache[I]);
end;
end;
end;
end;
end;
end.
Ciao, Mike
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, ComCtrls;
type
TForm1 = class(TForm)
ListView1: TListView;
procedure ListView1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
private
FCache: array of TListItem;
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.ListView1KeyDown(Se
Shift: TShiftState);
var
I,
Count: Integer;
Item: TListItem;
begin
if Shift = [ssCtrl] then
begin
case Key of
Ord('C'):
with ListView1 do
if SelCount > 0 then
begin
Count := SelCount;
SetLength(FCache, Count);
I := 0;
while (I < Items.Count) and (Count > 0) do
begin
if Items[I].Selected then
begin
Dec(Count);
FCache[Count] := Items[I];
end;
Inc(I);
end;
end;
Ord('V'):
with ListView1 do
begin
for I := 0 to High(FCache) do
begin
if Assigned(Selected) then Item := Items.Insert(Selected.Inde
else Item := Items.Add;
Item.Assign(FCache[I]);
end;
end;
end;
end;
end;
end.
Ciao, Mike
ASKER
i have checked = true for all items, but if i have the checked = false, can you fix this?
Huh, what do you have now: checked = True or checked = False? In the case you want to tell me that the check state is not copied I can tell you it is! I just set TListView.CheckBoxes := True and copied a few items. Some of them are checked. After pasting them back all check states reflect the original state. So what is your problem?
Ciao, Mike
Ciao, Mike
ASKER
Adjusted points to 500
ASKER
you are a genius, this all works
you get 500 points
Esk
you get 500 points
Esk
Thank you very much :-) Raising the points while working on a problem significantly raises motivation.
Have a good day and
Ciao, Mike
Have a good day and
Ciao, Mike
ASKER
do you only get 50 points or 500?
Esk
Esk
I got 500 * 4 (for the A grading). After the answer has been accepted other can buy it for a tenth of its original value (here 50 points), if that's what you are wondering about.
Ciao, Mike
Ciao, Mike
ASKER
i forgot one thing, how do i copy from listview1 and goto another listview in another form in same project and paste?
Many thanks
Esk
Many thanks
Esk
That is easy to do. Just replace:
with ListView1 do
with
with Sender as TListView do
Ciao, Mike
with ListView1 do
with
with Sender as TListView do
Ciao, Mike
ASKER
i do that and doesn't working
Please esk, try harder before you ask again. The code *does* work as I described:
procedure TMainForm.ListView2KeyDown (Sender: TObject; var Key: Word; Shift: TShiftState);
var
I,
Count: Integer;
Item: TListItem;
begin
if Shift = [ssCtrl] then
begin
case Key of
Ord('C'):
with Sender as TListView do
if SelCount > 0 then
begin
Count := SelCount;
SetLength(FCache, Count);
I := 0;
while (I < Items.Count) and (Count > 0) do
begin
if Items[I].Selected then
begin
Dec(Count);
FCache[Count] := Items[I];
end;
Inc(I);
end;
end;
Ord('V'):
with Sender as TListView do
begin
for I := 0 to High(FCache) do
begin
if Assigned(Selected) then Item := Items.Insert(Selected.Inde x)
else Item := Items.Add;
Item.Assign(FCache[I]);
end;
end;
end;
end;
end;
Ciao, Mike
procedure TMainForm.ListView2KeyDown
var
I,
Count: Integer;
Item: TListItem;
begin
if Shift = [ssCtrl] then
begin
case Key of
Ord('C'):
with Sender as TListView do
if SelCount > 0 then
begin
Count := SelCount;
SetLength(FCache, Count);
I := 0;
while (I < Items.Count) and (Count > 0) do
begin
if Items[I].Selected then
begin
Dec(Count);
FCache[Count] := Items[I];
end;
Inc(I);
end;
end;
Ord('V'):
with Sender as TListView do
begin
for I := 0 to High(FCache) do
begin
if Assigned(Selected) then Item := Items.Insert(Selected.Inde
else Item := Items.Add;
Item.Assign(FCache[I]);
end;
end;
end;
end;
end;
Ciao, Mike
ASKER
sorry, i know this works if i have two listview on same form. But if i have
listview in another form and opens it and try to paste it doesn't work
Esk
listview in another form and opens it and try to paste it doesn't work
Esk
Maybe you should be using the clipboard after all.
The cache is currently local to the form. If you want to have it accessible from other forms as well then make it a global variable.
Ciao, Mike
Ciao, Mike
ASKER
Lischke, it doesn't work if i make global variable
Esk
Esk
ASKER
Do you have any solutions for me Lischke?
Mmmh, possibly. Can you tell me what exactly does not work. Or even better can you send me a small example program where this error occurs (public@lischke-online.de) ?
Ciao, Mike
Ciao, Mike
ASKER
Sending......
Esk
Esk
Okay I got it and despite the trouble we had here's another (and final) solution.
Create an action list and add two standard actions (via Ctrl + Ins or the menu): TEditCopy and TEditPaste. Insert this code in your first unit:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ComCtrls, StdCtrls, StdActns, ActnList;
type
TForm1 = class(TForm)
ListView1: TListView;
Button1: TButton;
ActionList1: TActionList;
EditCopy1: TEditCopy;
EditPaste1: TEditPaste;
procedure Button1Click(Sender: TObject);
procedure EditCopy1Execute(Sender: TObject);
procedure EditPaste1Execute(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
ItemCache: array of TListItem;
procedure CopyToClipboard(Sender: TListView);
procedure PasteFromClipboard(Receive r: TListView);
implementation
uses Unit2;
{$R *.DFM}
procedure CopyToClipboard(Sender: TListView);
var
I,
Count: Integer;
begin
with Sender do
if SelCount > 0 then
begin
Count := SelCount;
SetLength(ItemCache, Count);
I := 0;
while (I < Items.Count) and (Count > 0) do
begin
if Items[I].Selected then
begin
Dec(Count);
ItemCache[Count] := Items[I];
end;
Inc(I);
end;
end;
end;
procedure PasteFromClipboard(Receive r: TListView);
var
I: Integer;
Item: TListItem;
begin
with Receiver do
begin
for I := 0 to High(ItemCache) do
begin
if Assigned(Selected) then Item := Items.Insert(Selected.Inde x)
else Item := Items.Add;
Item.Assign(ItemCache[I]);
end;
end;
end;
procedure TForm1.Button1Click(Sender : TObject);
begin
Form2.Show;
end;
procedure TForm1.EditCopy1Execute(Se nder: TObject);
begin
if ActiveControl is TListView then CopyToClipboard(ActiveCont rol as TListView)
else Beep;
end;
procedure TForm1.EditPaste1Execute(S ender: TObject);
begin
if ActiveControl is TListView then PasteFromClipboard(ActiveC ontrol as TListView)
else Beep;
end;
end.
Note: Although the procedures are named with ...Clipboard they don't use the clipboard in reality. It's just how one would name them if they would...
In your second (and every other) form you have to insert the same actions and assign the same calls in the execute handlers which refer then to the methods stored in form1:
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ComCtrls, StdActns, ActnList;
type
TForm2 = class(TForm)
ListView1: TListView;
ActionList1: TActionList;
EditCopy1: TEditCopy;
EditPaste1: TEditPaste;
procedure EditCopy1Execute(Sender: TObject);
procedure EditPaste1Execute(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
uses Unit1;
{$R *.DFM}
procedure TForm2.EditCopy1Execute(Se nder: TObject);
begin
if ActiveControl is TListView then CopyToClipboard(ActiveCont rol as TListView)
else Beep;
end;
procedure TForm2.EditPaste1Execute(S ender: TObject);
begin
if ActiveControl is TListView then PasteFromClipboard(ActiveC ontrol as TListView)
else Beep;
end;
end.
Cioa, Mike
Create an action list and add two standard actions (via Ctrl + Ins or the menu): TEditCopy and TEditPaste. Insert this code in your first unit:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ComCtrls, StdCtrls, StdActns, ActnList;
type
TForm1 = class(TForm)
ListView1: TListView;
Button1: TButton;
ActionList1: TActionList;
EditCopy1: TEditCopy;
EditPaste1: TEditPaste;
procedure Button1Click(Sender: TObject);
procedure EditCopy1Execute(Sender: TObject);
procedure EditPaste1Execute(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
ItemCache: array of TListItem;
procedure CopyToClipboard(Sender: TListView);
procedure PasteFromClipboard(Receive
implementation
uses Unit2;
{$R *.DFM}
procedure CopyToClipboard(Sender: TListView);
var
I,
Count: Integer;
begin
with Sender do
if SelCount > 0 then
begin
Count := SelCount;
SetLength(ItemCache, Count);
I := 0;
while (I < Items.Count) and (Count > 0) do
begin
if Items[I].Selected then
begin
Dec(Count);
ItemCache[Count] := Items[I];
end;
Inc(I);
end;
end;
end;
procedure PasteFromClipboard(Receive
var
I: Integer;
Item: TListItem;
begin
with Receiver do
begin
for I := 0 to High(ItemCache) do
begin
if Assigned(Selected) then Item := Items.Insert(Selected.Inde
else Item := Items.Add;
Item.Assign(ItemCache[I]);
end;
end;
end;
procedure TForm1.Button1Click(Sender
begin
Form2.Show;
end;
procedure TForm1.EditCopy1Execute(Se
begin
if ActiveControl is TListView then CopyToClipboard(ActiveCont
else Beep;
end;
procedure TForm1.EditPaste1Execute(S
begin
if ActiveControl is TListView then PasteFromClipboard(ActiveC
else Beep;
end;
end.
Note: Although the procedures are named with ...Clipboard they don't use the clipboard in reality. It's just how one would name them if they would...
In your second (and every other) form you have to insert the same actions and assign the same calls in the execute handlers which refer then to the methods stored in form1:
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ComCtrls, StdActns, ActnList;
type
TForm2 = class(TForm)
ListView1: TListView;
ActionList1: TActionList;
EditCopy1: TEditCopy;
EditPaste1: TEditPaste;
procedure EditCopy1Execute(Sender: TObject);
procedure EditPaste1Execute(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
uses Unit1;
{$R *.DFM}
procedure TForm2.EditCopy1Execute(Se
begin
if ActiveControl is TListView then CopyToClipboard(ActiveCont
else Beep;
end;
procedure TForm2.EditPaste1Execute(S
begin
if ActiveControl is TListView then PasteFromClipboard(ActiveC
else Beep;
end;
end.
Cioa, Mike
ASKER
uff, thank you very much "Lischke", this works very well but one thing
if i do copy and try paste into another listview, then item will will "rewerse"
Maybe you can fix this later?
Thanks
Esk
if i do copy and try paste into another listview, then item will will "rewerse"
Maybe you can fix this later?
Thanks
Esk
you probably can just change the order of the paste
change the line:
for I := 0 to High(ItemCache) do
to:
for I := High(ItemCache) downto 0 do ..
something like that should do it in right order..
change the line:
for I := 0 to High(ItemCache) do
to:
for I := High(ItemCache) downto 0 do ..
something like that should do it in right order..
ASKER
yes!!!
this works. Thanks Barry.
this works. Thanks Barry.