C#动态生成html数据并发送到本地剪贴板

  • Post author:
  • Post category:其他



我们都玩过Word,Excel,PowerPoint吧,不然你肯定进不了公司,面试一关都过不了当你将数据从一个位置复制到另一个位置时,复制除了文本之外,还会带有文本的格式,比如字体的颜色、大小、是否有下划线、是否有链接、是否有图片、表格等等…那么自然会引出一个问题,数据在剪贴板中到底如何储存的.以前大学在数学建模的时候做过将计算后的矩阵输出到本地剪贴板,其实就调用了clipboard函数,可以通过预处理改变数据的格式,比如在每一行的数据之间加逗号或固定长度空格等等,但仅仅是在字符串的基础上做的处理,并不能像Word一样,直接复制一个带颜色的文本,或图像(matlab帮助文档一定要会用)。


1


2

图片

经过一天的摸索过后,终于弄懂了数据保存在剪贴板的格式、如何获取剪贴板的数据格式以及如何通过编程将带有格式化的数据写入剪贴板。


获取剪贴板的数据格式


通过C#的System.Windows.Forms.Clipboard.GetDataObject()方法可以获取到剪贴板数据对象,它是一个IDataObject类,如图


图片


这个类里包含许多属性和方法,可以通过它的GetFormats方法获取当前剪贴板所有的数据格式,上面的内容我是从OneNote笔记本复制来的,包含了文字图像和表格,


图片


剪贴板包含了7种数据格式,其中System.String、UnicodeText、Text都是一样的内容,它保存了剪贴板上的全部文本,粘贴下来就是这样:





"以前大学在数学建模的时候做过将计算后的矩阵输出到本地剪贴板,其实就调用了clipboard函数,可以通过预处理改变数据的格式,比如在每一行的数据之间加逗号或固定长度空格等等,但仅仅是在字符串的基础上做的处理,并不能像Word一样,直接复制一个带颜色的文本,或图像(matlab帮助文档一定要会用)。\r\n1\t2\r\n\r\n\r\n经过一天"



OneNote 2010 Internal是OneNote自定义的数据格式,它应该会定位到剪贴板的具体位置吧,它是以缓存数据流的形式保存的


图片

DeviceIndependentBitmap就代表了图片格式,可以通过GetData方法获取到获取到图像RGB数据,如图:

图片


也就是说,只要将图像写成byte的格式以DeviceIndependentBitmap的格式调用方法System.Windows.Forms.Clipboard.SetData(‘数据格式’,’值’)就可以将图像保存到剪贴板啦(上一次在写截图程序时,知道了QQ截图打开画图工具是先将图像保存到本地相册,然后再将图像的地址作为传入参数打开画图工具的;知道如何将图像放到剪贴板后,可以先将画图工具放入一个进程中,调用系统命名打开画图工具,并监测画图工具是否为已经完全开启,如果开启。就将画图工具窗口激活为当前窗口,然后发送’Ctrl+V’的按键消息触发系统粘贴事件来达到同样的效果,而不需要保存到本地相册.)



现在看HTML Format格式,获取数据之后,它是一个html字符串



“Version:1.0\r\nStartHTML:0000000105\r\nEndHTML:0000002752\r\nStartFragment:0000000527\r\nEndFragment:0000002712\r\n\r\n<htmlxmlns:o=\”urn:schemas-microsoft-com:office:office\”\r\nxmlns:dt=\”uuid:C2F41010-65B3-11d1-A29F-00AA00C14882\”\r\nxmlns=\”

http://www.w3.org/TR/REC-html40

\”>\r\n\r\n<head>\r\n<metahttp-equiv=Content-Type content=\”text/html;charset=utf-8\”>\r\n<meta name=ProgIdcontent=OneNote.File>\r\n<meta name=Generator content=\”MicrosoftOneNote 15\”>\r\n</head>\r\n\r\n<body lang=zh-CNstyle=’font-family:Calibri;font-size:11.0pt’>\r\n<!–StartFragment–>\r\n\r\n<pstyle=’margin:0in;font-family:\”Microsoft YaHei\”;font-size:10.5pt;color:black’><span\r\nlang=zh-CN>以前大学在数学建模的时候做过将计算后的矩阵输出到本地剪贴板,其实就调用了</span><spanlang=en-US>clipboard</span><span\r\nlang=zh-CN>函数,可以通过预处理改变数据的格式,比如在每一行的数据之间加逗号或固定长度空格等等,但仅仅是在字符串的基础上做的处理,并不能像</span><span\r\nlang=en-US>Word</span><spanlang=zh-CN>一样,直接复制一个带颜色的文本,或图像(</span><span\r\nlang=en-US>matlab</span><spanlang=zh-CN>帮助文档一定要会用)。</span></p>\r\n\r\n<divstyle=’direction:ltr’>\r\n\r\n<table border=1 cellpadding=0 cellspacing=0valign=top style=’direction:ltr;\r\nborder-collapse:collapse;border-style:solid;border-color:#A3A3A3;border-width:\r\n1pt’ title=\”\” summary=\”\”>\r\n <tr>\r\n  <tdstyle=’border-style:solid;border-color:#A3A3A3;border-width:1pt;\r\n  vertical-align:top;width:.6673in;padding:4pt4pt 4pt 4pt’>\r\n  <pstyle=’margin:0in;font-family:Calibri;font-size:10.5pt;color:black’\r\n  lang=en-US>1</p>\r\n  </td>\r\n  <tdstyle=’border-style:solid;border-color:#A3A3A3;border-width:1pt;\r\n  vertical-align:top;width:.5548in;padding:4pt4pt 4pt 4pt’>\r\n  <pstyle=’margin:0in;font-family:Calibri;font-size:10.5pt;color:black’\r\n  lang=en-US>2</p>\r\n  </td>\r\n </tr>\r\n</table>\r\n\r\n</div>\r\n\r\n<imgsrc=\”

file:///C:/Users/

陈鹏/AppData/Local/Temp/msohtmlclip1/02/clip_image001.png\”\r\nwidth=628height=445\r\nalt=\”Command Window &#10;clipboard &#10;Error usi&#10;Not enoug &#10;doc &#10;clipboard &#10;Copy and pastestrings to and from system clipboard &#10;Syntax &#10;clipboard ( ‘copy’ , data) &#10;clipboard ( ‘paste ‘ ) &#10;clipboard ( ‘pastespeczal ‘ &#10;Description &#10;expand all in page&#10;clipboard ( ‘ copy’, data) sets the clipboard contents to data. If&#10;data is not a character array, the clipboard uses mat2str to convertta to &#10;a string. &#10;O.en &#10;nft’u &#10;F I to togglefm; to \”>\r\n\r\n<pstyle=’margin:0in;font-family:Calibri;font-size:11.0pt’>&nbsp;</p>\r\n\r\n<pstyle=’margin:0in;font-family:微软雅黑;font-size:11.0pt’>经过一天</p>\r\n\r\n<!–EndFragment–>\r\n</body>\r\n\r\n</html>\r\n”



可以通过HTML可视化工具将其转换正常人能够看懂的格式


图片

图片


看到没有,VS还可以直接对图像进行文字识别,简直是意外中的惊喜哇!


也可以用文本可视化工具转化为程序员容易看懂的格式



Version:1.0
StartHTML:0000000105
EndHTML:0000002752
StartFragment:0000000527
EndFragment:0000002712
 
<htmlxmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"
xmlns="http://www.w3.org/TR/REC-html40">
 
<head>
<metahttp-equiv=Content-Type content="text/html; charset=utf-8">
<meta name=ProgIdcontent=OneNote.File>
<metaname=Generator content="Microsoft OneNote 15">
</head>
 
<body lang=zh-CNstyle='font-family:Calibri;font-size:11.0pt'>
<!--StartFragment-->
 
<pstyle='margin:0in;font-family:"MicrosoftYaHei";font-size:10.5pt;color:black'><span
lang=zh-CN>以前大学在数学建模的时候做过将计算后的矩阵输出到本地剪贴板,其实就调用了</span><spanlang=en-US>clipboard</span><span
lang=zh-CN>函数,可以通过预处理改变数据的格式,比如在每一行的数据之间加逗号或固定长度空格等等,但仅仅是在字符串的基础上做的处理,并不能像</span><span
lang=en-US>Word</span><spanlang=zh-CN>一样,直接复制一个带颜色的文本,或图像(</span><span
lang=en-US>matlab</span><spanlang=zh-CN>帮助文档一定要会用)。</span></p>
 
<divstyle='direction:ltr'>
 
<table border=1cellpadding=0 cellspacing=0 valign=top style='direction:ltr;
 border-collapse:collapse;border-style:solid;border-color:#A3A3A3;border-width:
 1pt' title=""summary="">
 <tr>
  <tdstyle='border-style:solid;border-color:#A3A3A3;border-width:1pt;
  vertical-align:top;width:.6673in;padding:4pt4pt 4pt 4pt'>
  <pstyle='margin:0in;font-family:Calibri;font-size:10.5pt;color:black'
  lang=en-US>1</p>
  </td>
  <tdstyle='border-style:solid;border-color:#A3A3A3;border-width:1pt;
  vertical-align:top;width:.5548in;padding:4pt4pt 4pt 4pt'>
  <pstyle='margin:0in;font-family:Calibri;font-size:10.5pt;color:black'
  lang=en-US>2</p>
  </td>
 </tr>
</table>
 
</div>
 
<imgsrc="file:///C:/Users/陈鹏/AppData/Local/Temp/msohtmlclip1/02/clip_image001.png"
width=628 height=445
alt="CommandWindow 
clipboard 
Error usi 
Not enoug 
doc
clipboard 
Copy and paste strings to and from system clipboard
Syntax 
clipboard ( ' copy' , data) 
clipboard ( 'paste' ) 
clipboard ( ' pastespeczal ' 
Description 
expandall in page 
clipboard ( ' copy', data) sets the clipboard contents todata. If 
data is not a character array, the clipboard uses mat2str toconvert ta to 
a string. 
O.en 
nft'u 
F I totoggle fm; to ">
 
<pstyle='margin:0in;font-family:Calibri;font-size:11.0pt'> </p>
 
<pstyle='margin:0in;font-family:微软雅黑;font-size:11.0pt'>经过一天</p>
 
<!--EndFragment-->
</body>
 
</html>


相信大部分搞过前端的人都看懂了吧,我就不想多说什么,不懂的到w3school补脑一波


看到木有,剪贴板的图片地址为”

file:///C:/Users/

陈鹏/AppData/Local/Temp/msohtmlclip1/02/clip_image001.png”,刚才意外出现的文字识别消息,就是img标签的alt属性带出的,也就是说,VS的html可视化工具支持动图,javascrip;并且说明你在复制图片的时候,系统对图像进行了文字识别了一波,然后生成了一个包含识别文本的html数据文件;


当复制图片的时候,图片的地址保持在C:\Users\陈鹏\AppData\Local\Temp\msohtmlclip1\01文件夹下,这样以后复制了图片,只需打开这个文件夹,粘贴文件就方便多了


如果你是直接查看复制office2016内容的html数据,你会感到非常恶心,既然恶心到这个程度了,再恶心一下也不要紧


图片

后来经过我仔细分析,发现都他娘的都是注释,最后得到的结果如图

图片


有没有感觉整个世界都清净了


用到的查询替换通配符:\<\!–*–\>,\\[nr]  ,

\\r\\n|[\u4e00-\u9fa5],\\s+,(在SAP中有一个FIND操作符可以用RegEx来查询字符串,幸亏我上次研究了一波,,不然会烦死)



剪贴板html数据解析


抬头部分是五个必输字段Version、StartHTML、EndHTML、StartFragment、EndFragment、SourceURL,以下是我分析的结果:


Version: 版本号,浮点型格式数据


StartHTML:(长度10) html字符串中<html>前的字符数,转义字符\r、\n、\0只记一个,中文记两个字符数,下同,


EndHTML:(长度10) html字符串前到包含</html>在内所有字符数


StartFragment:(长度10)html字符串前到包含<!–StartFragment–>在内所有字符数


EndFragment:(长度10)html字符串中<!–EndFragment–>前的字符数


SourceURL:(地址,可以为空)


遇到<!—打头和—>结束的内容为注释,可以直接删除,注意不要删除<!–StartFragment–>和<!–EndFragment–>,因为它可以直接通过程序来确定StartFragment、EndFragment的值


<!–StartFragment–>、<!–EndFragment–>在<body></body>内部,如果不写,StartFragment和EndFragment的值也可以通过<body></body>来读.



既然对剪贴板有了这么多的认识,那么只要通过编程根据数据动态生成一个html字符串,就可以实现最初想要的功能



下面我做了一个程序,可以将一个数组动态生成html并传入到剪贴板



数据存放地址:C:\Users\陈鹏\Desktop\\测试数据.txt


内容:


图片

程序结构:包含三个类,分别处理数据,处理html,和主类

图片


读取文件数据就不讲了,不然就跑题了


动态生成html的函数:


private static voidhtmlprocess()
        {
            intstartHTML,endHTML,startFragment,endFragment;
            //头数据
            htmlstring ="Version:1.0\r\nStartHTML:0000000000\r\nEndHTML:0000000000\r\nStartFragment:0000000000\r\nEndFragment:0000000000\r\nSourceURL:\r\n";
            //主体部分头部
            htmlstring +="<html>\r\n<body>\r\n";
            //加载表数据
            htmlstring += "<tableborder=1 cellspacing=0 cellpadding=0style='border-collapse:collapse;border:none;mso-border-alt:solid windowtext.5pt; mso-yfti-tbllook:1184;mso-padding-alt:0cm 5.4pt 0cm 5.4pt'>\r\n";
            for (int i = 0; i < lines.Count;i++)
            {
                //行
                htmlstring += "<trstyle='mso-yfti-irow:0;mso-yfti-firstrow:yes;mso-yfti-lastrow:yes'>\r\n";
                for (int j = 0; j <lines.ElementAt(i).Length; j++)
                {
                    //列
                    htmlstring += "<tdwidth=277 valign=top style='width:207.4pt;border:solid windowtext 1.0pt;  mso-border-alt:solid windowtext.5pt;padding:0cm 5.4pt 0cm 5.4pt'>\r\n";
                    //文本
                    htmlstring +="<p>\r\n<span lang=EN-USstyle='font-size:9.0pt;font-family:\"Segoe UI\",sans-serif;  color:#A31515;mso-font-kerning:0pt'>";
                    //值
                    htmlstring +=lines.ElementAt(i)[j];
                    htmlstring +="<o:p></o:p></span></p>\r\n";
                    htmlstring +="</td>\r\n";
                }
                htmlstring +="</tr>\r\n";
            }
            htmlstring +="</table>\r\n";
            //主体部分尾部
            htmlstring +="</body>\r\n</html>\0";
            //头部处理
            //MatchCollection matchCollection =
            //matchCollection.Count
            string _string = htmlstring;
            Regex regex = newRegex("\\r\\n|[\u4e00-\u9fa5]");//转移字符占一个字符数,汉字占两个字符数
            _string=regex.Replace(_string,"==");
            startHTML =_string.IndexOf("<html>");
            endHTML =_string.IndexOf("</html>") + 7;
            startFragment =_string.IndexOf("<body>") + 6;
            endFragment =_string.IndexOf("</body>");
           htmlstring=htmlstring.Replace("StartHTML:0000000000","StartHTML:" + startHTML.ToString().PadLeft(10, '0'));
            htmlstring =htmlstring.Replace("EndHTML:0000000000", "EndHTML:" +endHTML.ToString().PadLeft(10, '0'));
            htmlstring =htmlstring.Replace("StartFragment:0000000000","StartFragment:" + startFragment.ToString().PadLeft(10, '0'));
            htmlstring =htmlstring.Replace("EndFragment:0000000000", "EndFragment:"+ endFragment.ToString().PadLeft(10, '0'));
        }


就是把数据转换成了表格,可以向其中添加更多的元素标签,这里为了演示起见就简化了一波


执行ReadData.formfile静态方法后获取到源数据


图片

然后将源数据动态生成为html数据

图片

图片

然后将html数据发送到剪贴板,粘贴到Word文件中就是这个样子

图片


厉害了我的哥,基本上能做到想变什么样子就变什么样子,可以在SourceURL中参考一些css或javascript来远程获取对象的属性和方法.这样最初的设想已经完成!



版权声明:本文为qq_16635325原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。