Sunday, June 17, 2007

Copy ListView to Clipboard in VB.NET, C#, and VB6

It is often useful to be able to copy the contents of a ListView to the Windows Clipboard. I have written a function for VB.NET, C#, and VB6 called CopyListViewToClipboard that will copy the contents of a ListView (in Details mode) to the Windows Clipboard. Additional functions are also available for a ListBox control here. The column headers will be the first row and the items in the listview will be the remaining rows. To make the copied data more compatible with applications like Excel, a tab character is placed between items in a row and a carriage return/linefeed is placed at the end of the row.

Here is an example ListView with some data in it:



Here is what is copied to the clipboard and then to Excel:




VB.NET:

Imports System.text

...


Public Sub CopyListViewToClipboard(ByVal lv As ListView)

Dim buffer As New StringBuilder

For i As Integer = 0 To lv.Columns.Count - 1
buffer.Append(lv.Columns(i).Text)
buffer.Append(vbTab)
Next

buffer.Append(vbCrLf)

For i As Integer = 0 To lv.Items.Count - 1
For j As Integer = 0 To lv.Columns.Count - 1
buffer.Append(lv.Items(i).SubItems(j).Text)
buffer.Append(vbTab)
Next
buffer.Append(vbCrLf)
Next

My.Computer.Clipboard.SetText(buffer.ToString)

End Sub


C#

using System.Text;

...


public void CopyListViewToClipboard(ListView lv)
{
StringBuilder buffer = new StringBuilder();

for (int i = 0; i < lv.Columns.Count; i++)
{
buffer.Append(lv.Columns[i].Text);
buffer.Append("\t");
}

buffer.Append("\n");

for (int i = 0; i < lv.Items.Count; i++)
{
for (int j = 0; j < lv.Columns.Count; j++)
{
buffer.Append(lv.Items[i].SubItems[j].Text);
buffer.Append("\t");
}

buffer.Append("\n");
}

Clipboard.SetText(buffer.ToString());
}


VB6


Public Sub CopyListViewToClipboard(lv As ListView)

Dim buf As String
Dim i As Integer
Dim j As Integer

For i = 1 To lv.ColumnHeaders.count

buf = buf + lv.ColumnHeaders.Item(i).Text + vbTab

Next


buf = buf + vbCrLf

For i = 1 To lv.ListItems.count

buf = buf + lv.ListItems(i).Text

For j = 1 To lv.ColumnHeaders.count - 1
buf = buf + vbTab + lv.ListItems(i).SubItems(j)
Next

buf = buf + vbCrLf

Next

buf = buf + vbCrLf

Clipboard.Clear
Clipboard.SetText buf

End Sub

27 comments:

GrayFox said...

Thanks. Just what I needed. Works very nicely!

Anonymous said...

There is no Clipboard.SetText in C#

srego said...

There is a SetText method on the Clipboard object in C#. Please refer to the Microsoft Documentation below:

http://msdn2.microsoft.com/en-us/library/ydby206k.aspx

Anonymous said...

Just what I needed - you might like to cache the columns count into a variable to save recounting for every row - don't know whether it's much of a performance issue.

Anonymous said...

thanx a lot! this worked perfectly!

Anonymous said...

Thanks! I learned something from this. BTW, for C# I had to change "\n" to Environment.NewLine to get it to paste properly.

Jari (Finland) said...

Hi,
Found this from Google. I was searching for clipboard copying from listview object. Very helpful. Thanks.

Chad said...

This is the sweetest sub ever! works perfectly.

Almost immediately came up on google for terms "listview clipboard"

Thanks!

Anonymous said...

Sweeeeeet!

Anonymous said...

Thanks for the method.

Given I had a ListView that did not always have the same number of sub items as the column count, I had to update the code to handle that to prevent an index out of range exception:


private void CopyListViewToClipboard(ListView lv)
{
StringBuilder buffer = new StringBuilder();

foreach (ColumnHeader header in lv.Columns)
{
buffer.Append(header.Text);
buffer.Append('\t');
}
buffer.Append(Environment.NewLine);

foreach (ListViewItem item in lv.Items)
{
foreach (ListViewItem.ListViewSubItem subItem in item.SubItems)
{
buffer.Append(subItem.Text);
buffer.Append('\t');
}
buffer.Append(Environment.NewLine);
}

Clipboard.SetText(buffer.ToString());
}

Mr. Anxiety said...

Awesome - thanks!!!

Anonymous said...

Add

StringBuilder buffer = new StringBuilder();

buffer.Append(" ");//Include this incase the ListView is empty

Incase the ListView is empty, this will prevent the ClipBoard.SetText from throwing an exception.

JAJG said...

Great Work.

I found an error. If subitem has a space at the end or beginning, it will cause a problem with the tab (\ t) and the information is not copied correctly. The code would be as follows:

private void CopyListViewToClipboard(ListView lv)
{
StringBuilder buffer = new StringBuilder();

foreach (ColumnHeader header in lv.Columns)
{
buffer.Append(header.Text.Trim());
buffer.Append('\t');
}
buffer.Append(Environment.NewLine);

foreach (ListViewItem item in lv.Items)
{
foreach (ListViewItem.ListViewSubItem subItem in item.SubItems)
{
buffer.Append(subItem.Text.Trim());
buffer.Append('\t');
}
buffer.Append(Environment.NewLine);
}

Clipboard.SetText(buffer.ToString());
}


JAJG

Anonymous said...

Excelent

Kelly said...

Thanks, I found this right away and didn't have to waste time figuring it out... it works great. I added try/catches around it because it threw exceptions sometimes when there was no data in a column.

jin said...

Thanks for the useful method. Love it. :-)

HowitZer said...

Thank you this works great.

Anonymous said...

That was so nice at 12:37 w/ project due tommorow...ty. b

Anonymous said...

Thanks. Just what I needed.

Very Good

Anonymous said...

Works like a charm! Thank you.

Kamrul said...

thanks a lot

Kamrul said...

thanks a lot

Benek said...

Works perfectly! That was very helpful.

GoDaddy Promo Code said...

Thanks for the example code :)

Anonymous said...

That was just perfect! Thanks :)

Anonymous said...

C# ListView Control

Anonymous said...

Merci pour ce post qui marche très bien.