I have a List View with eight columns and a popup menu. [ScreenShot]
I have this code which is work great to copy into clipboard all items and sub items when a row or all rows selected.
procedure TForm1.CopyURL1Click(Sender: TObject);
var
lv : TbsSkinListView;
s : string;
c,f,k : integer;
begin
lv := bsSkinListView1;
Clipboard.Clear;
s := '';
for f := 0 to lv.Items.Count - 1 do
begin
k := 0;
if lv.Items[f].Selected then
begin
s := s + Format('%s : %s, ',[lv.Columns[k].Caption, lv.Items[f].Caption]);
for c := 0 to lv.Items[f].SubItems.Count - 1 do
begin
Inc(k);
s := s + Format('%s : %s, ',[lv.Columns[k].Caption, lv.Items[f].SubItems[c]]);
end;
SetLength(s, Length(s) - 2);
s := s + #$D#$A;
end;
end;
clipboard.AsText := s;
end;
What i need is I'd like to copy only the caption of column one (column "Title") with it's sub items [0], and copy the column 8 caption (column "URL") with it's sub items [7] into clipboard, when a row or all rows selected.
Also sometime sub items[7] is empty, and it shouldn't get index out of bounds (7) error message.
From my screenshot above, when i copy the 1st row, the result should return like this
Title : 10 Things You Didn't Know... URL : <=== this is an empty sub items [7]
when 2nd row copied:
Title : 10 Things You Didn't Know... URL : http://www.example.com
All rows selected :
Title : 10 Things You Didn't Know... URL :
Title : 10 Things You Didn't Know... URL : http://www.example.com
i have try this link but it doesn't meet or not work as i need. I'm using Delphi XE 4. How do i achieve this? Any help would be highly appreciated.
Your clipboard text contains all of the column values because you are looping through all of the TListItem.SubItems
values. If you don't want all of the values, simply don't loop anymore. Just access the specific items you want.
Try something more like this:
procedure TForm1.CopyURL1Click(Sender: TObject);
var
s : string;
item: TListItem;
begin
s := '';
item := bsSkinListView1.GetNextItem(nil, sdAll, [isSelected]);
while item <> nil do
begin
s := s + Format('Title : %s, ', [item.Caption]);
if item.SubItems.Count > 7 then
s := s + Format('URL : %s, ', [item.SubItems[7]]);
s[Length(s)-1] := #$D;
s[Length(s)] := #$A;
item := bsSkinListView1.GetNextItem(item, sdAll, [isSelected]);
end;
Clipboard.Open;
try
Clipboard.Clear;
Clipboard.AsText := s;
finally
Clipboard.Close;
end;
end;
With that said, an alternative option would be to use the TListView
in virtual mode instead (OwnerData=True
), where you store all of your data in a separate list. Then you can access your data list directly without having to touch the TListView
at all. For example:
type
PMyData = ^TMyData;
TMyData = record
Selected: Boolean;
Title: String;
...
URL: string;
end;
TForm1 = class(TForm)
...
private
MyData: TList;
...
end;
...
procedure TForm1.FormCreate(Sender: TObject);
begin
MyData := TList.Create;
end;
procedure TForm1.FormDestroy(Sender: TObject);
var
I: Integer;
begin
for I := 0 to MyData.Count-1 do
Dispose(PMyData(MyData[I]));
MyData.Free;
end;
procedure TForm1.bsSkinListView1Data(Sender: TObject; Item: TListItem);
var
Data: PMyData;
begin
Data := PMyData(MyData[Item.Index]);
Item.Caption := Data.Title;
Item.SubItems.Add(...);
...
Item.SubItems.Add(Data.URL);
Item.Data := Data;
end;
procedure TForm1.TForm1.bsSkinListView1SelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
var
I: Integer;
begin
if Item <> nil then
Item.Selected := Selected
else
begin
for I := 0 to MyData.Count-1 do
PMyData(MyData[I]).Selected := Selected;
end;
end;
procedure TForm1.TForm1.bsSkinListView1DataStateChange(Sender: TObject; StartIndex, EndIndex: Integer; OldState, NewState: TItemStates);
var
I: Integer;
begin
if (OldState * [isSelected]) <> (NewState * [isSelected]) then
begin
for I := StartIndex to EndIndex do
PMyData(MyData[I]).Selected := (isSelected in NewState);
end;
end;
procedure TForm1.AddItem1Click(Sender: TObject);
var
Data: PMyData;
begin
New(Data);
try
Data.Selected := False;
Data.Title := ...;
...
Data.URL := ...;
MyData.Add(Data);
except
Dispose(Data);
raise;
end;
bsSkinListView1.Items.Count := MyData.Count;
end;
procedure TForm1.CopyURL1Click(Sender: TObject);
var
s : string;
Data: PMyData;
I: Integer;
begin
s := '';
for I := 0 to MyData.Count-1 do
begin
Data := PMyData(MyData[I]);
if Data.Selected then
begin
s := s + Format('Title : %s, ', [Data.Title]);
if item.URL <> '' then
s := s + Format('URL : %s, ', [Data.URL]);
s[Length(s)-1] := #$D;
s[Length(s)] := #$A;
end;
end;
Clipboard.Open;
try
Clipboard.Clear;
Clipboard.AsText := s;
finally
Clipboard.Close;
end;
end;