Introduction
Applications like Word and Excel let you copy some text or tabular data to the clipboard in HTML-format, so that the formatting and visual style doesn't change when pasted. At work, I had to do something similar: our application uses a lot of grid-controls to display data, and we wanted the users to be able to select data from a grid, and copy it to the clipboard, in a format that would keep the tabular structure of the data. After some research, I found out that you can copy data to the clipboard in HTML-format, and I thought: this is it. Piece of cake. But it wasn't. Apparently, you have to pass a bit more information than just the HTML-code. Googling around gave me some hints how it should be done, but nothing really specific. So I started experimenting, until it worked correctly.Tip: use a StringBuilder to build the HTML-code, instead of concatenating strings. StringBuilders are very efficient for building long strings (hence the name StringBuilder): they are a lot faster than strings, and allocate much less memory.
Possible applications
There are a lot of situations where you could use this:- Copying tabular data (and pasting it in Excel, Word or Outlook).
- Copying formatted, visually styled data.
- ...
The Code
using System; using System.Text; using System.Windows.Forms; class Test { public static void CopyHtmlToClipBoard(string html) { Encoding enc = Encoding.UTF8; string begin = "Version:0.9\r\nStartHTML:{0:000000}\r\nEndHTML:{1:000000}" + "\r\nStartFragment:{2:000000}\r\nEndFragment:{3:000000}\r\n"; string html_begin = "<html>\r\n<head>\r\n" + "<meta http-equiv=\"Content-Type\"" + " content=\"text/html; charset=" + enc.WebName + "\">\r\n" + "<title>HTML clipboard</title>\r\n</head>\r\n<body>\r\n" + "<!--StartFragment-->"; string html_end = "<!--EndFragment-->\r\n</body>\r\n</html>\r\n"; string begin_sample = String.Format(begin, 0, 0, 0, 0); int count_begin = enc.GetByteCount(begin_sample); int count_html_begin = enc.GetByteCount(html_begin); int count_html = enc.GetByteCount(html); int count_html_end = enc.GetByteCount(html_end); string html_total = String.Format( begin , count_begin , count_begin + count_html_begin + count_html + count_html_end , count_begin + count_html_begin , count_begin + count_html_begin + count_html ) + html_begin + html + html_end; DataObject obj = new DataObject(); obj.SetData(DataFormats.Html, new System.IO.MemoryStream( enc.GetBytes(html_total))); Clipboard.SetDataObject(obj, true); } }
Example: copying a DataTable
StringBuilder html = new StringBuilder(); html.Append("<table>"); foreach ( DataRow row in table.Rows ) { html.Append("<tr>"); foreach ( object o in row ) html.AppendFormat("<td>{0}</td>", o); html.Append("</tr>"); } html.Append("</table>"); Test.CopyHtmlToClipboard(html.ToString());
15 comments:
very useful !!!
bye
xrado
Worked a treat!
Thx
Perfect! Just what I was looking for. I am amazed that more people haven't come across this problem and posted their own solutions.
Brilliant! Just what I was looking for.
Thanks!
Thanks dude - just what I needed.
Very good. Give us more
Thanks
definitely useful!!!
msdn documentation sucks in this!
I was able to use Clipboard.setText( str, TextDataFormats.Html ) to paste html fragments into Outlook express, but not outlook. This method did the trick though! Good work Tommy!
Ditto on the last comment with respect to Outlook. Thanks very much!
Absolutely brilliant.
thx, it's the very thing that I need.
Thank you
Absolutely useful
Thanks, I used your code in my project.
You saved me on this one. From one techie to another thanks!
This is very similar to code in msdn
http://msdn.microsoft.com/en-us/library/ms649015(v=vs.85).aspx
...but your actually works!
This works great in Windows 7, though when trying to run on Windows 2008 R2 the clipboard remains empty.
I've tried using a Clipboard Inspector (On Win7), but nothing appears when doing this in code, although I can still paste into Outlook.
Any Ideas?
Post a Comment