对于Excel中的很多对象,比如单元格(Cell),图形(shape),图表(chart)等等,有时需要将它们保存成一张图片。就像截图一样。 
最近做一个Excel相关的项目,项目中遇到一个很变态的需求, 需要对Excel中的一些对象进行拍图,比如,对一个单元格设置一些颜色之后拍图,或者对一个图表,报表拍成图片。经过比较曲折的经历,终于还是完成了。拿出来分享一下。 
要做Excel,首先当然是查看Excel的com对象模型。地址在这里: 
http://msdn.microsoft.com/en-us/library/bb149081(v=office.12).aspx 
这里说明一下: 
官方的Excel2010对象参考没有找到,点进去就是死循环,点来点去就是找不到,哪位神人找到了麻烦回复告知一下。  
Excel2003的对象模型,需要下下来安装,比较麻烦,我也是安装了之后才知道的,这里推荐大家就通过上面的网址查看Excel2007的模型就可以了。    实际上按照微软的兼容惯例,Excel2010和Excel2003的差别应该不大(是吗?)。 
然后是查看Range对象的成员,期待它有没有什么现成的方法就爽了:http://msdn.microsoft.com/en-us/library/bb225606(v=office.12).aspx 
查看了一圈,也没发现类似什么 ExportImage,SaveImage之类的方法。表示沮丧,不过也是情理之中。 
绝望之中发现了一个亮点,一个方法名字叫做CopyPicture。 看了一下方法说明,是要把对象当作图片拷到剪贴板里面。    呵呵,一个比较扭曲的想法诞生了,既然能拷到剪贴板里面,我再从剪贴板里面把图片抠出来不就行了吗。  
好,就这么定了,说干就干。 
…… 
此处省略200字(怎么创建excel的com对象, 怎么取到Range对象就不说了,不知道的自己查,也可以回复提问。) 
…… 
拿到Range对象之后。调用CopyPicture方法,需要两个参数。第一个参数是XlPictureAppearance枚举,1表示按照屏幕的样子拷贝,2表示按照打印时的样子拷贝。 第二个参数是XlCopyPictureFormat枚举,2表示拷贝成位图,-4147表示拷贝成矢量图片。 
于是乎,我写了大概类似如下的代码。

Range cell = excel.Activesheet.Cells[1,1];
cell.CopyPicture(1,2);
Bitmap image = Clipboard.GetImage() as Bitmap;
if(image != null)
{
//可以在这里为所欲为。
}

调试,运行,一切Ok,完全没问题,提交代码(期间还做了无数额外代码,此处不提。)。(嘿嘿,这种小事能难得到楼主吗,得意的笑。) 
然后24小时过去了,话说第二天到了。 
刚一上班,楼主就兴冲冲的发邮件告诉大家:恭喜大家,excel的拍图功能完成啦,大家赶快享用(是enjoy)吧。 
大家也都很配合,纷纷发来贺电:“楼主Nb啊”之类的。 
楼主的虚荣心得到了极大的满足,表示很开心。沉浸在自我陶醉之中。。。 
不多时,同组一MM惊呼楼主的名字,“楼主,楼主,你快来看看吧,你的拍图功能真的太……”。 在最后还有两个字没说出来的时候,楼主已经飞奔到MM的身边。话说此MM那可真是。。(嗯,先不说吧),“太给力吗”,楼主很自信的补充了剩下的几个字。 MM手指屏幕,“你的拍图怎么崩掉了。”, 果然,屏幕上一个NullReferenceException嚣张的躺在屏幕中央。 楼主果断调试代码,跟踪发现,确实是拍图出了问题,上面的Clipboard.GetImage() 返回了null。 怎么会呢, 楼主又反复运行了几次,结果一样,都是返回null。 楼主表示鸭梨很大。 
不过,鸭梨归鸭梨,楼主是个不轻易服输的人,口头禅是:我就不信这个邪了。 这次也是,楼主一边说着口头禅,一边继续跟踪。 
首先当然是要看看剪贴板的数据,看拷贝成功了没, 
Clipboard.GetDataObject().GetFormats() 方法返回: 
  [0]: "EnhancedMetafile" 
    [1]: "MetaFilePict" 
    [2]: "Link" 
看样子,应该是拷出来了。然后楼主通过这几个format来get数据,发现还是不成功。  这就奇怪了。 
楼主很受打击,回到座位上继续调试。 
相同的代码,在楼主的机器上就是好好的,为什么在MM的机器上就是null呢。 
楼主在自己的机器上再次查看剪贴板数据。 
用Clipboard.GetDataObject().GetFormats() 方法返回: 
[0]: "System.Drawing.Bitmap" 
    [1]: "Bitmap" 
    [2]: "DeviceIndependentBitmap" 
    [3]: "Format17" 
    [4]: "Link" 
咦,怎么和上面的不一样呢。楼主很果断的发现,楼主的机器上安装的是Excel2010,而mm的机器上安装的是Excel2007. 原来是它们考出来的数据不一样。 
果断Google之。  于是,经过若干次失败和跳转,楼主来到这里:http://support.microsoft.com/kb/323530/en-us/ 
方才恍然大悟,这里的大概意思是说,由于.Net的一些限制,一些旧的程序(比如这里遇到的Excel2007)复制到剪贴板的数据可能不可用,需要通过本地Api来使用。 我去。。。 msdn上也没见半个字的提醒。 
楼主是个比较勤快的人,知道了这个,那还不赶快动手。 
于是楼主写下了大概类似如下的代码:

IntPtr hwnd = excel.Hwnd;
try             
{
                 if (OpenClipboard(hwnd))
                 {
                     IntPtr data = GetClipboardData(14); // CF_ENHMETAFILE      14
                     if (data != IntPtr.Zero)
                     {
                         using (Metafile mf = new Metafile(data, true))
                         {
//这里有点多余,不过因为需要的是bitmap格式。就忍了。
                             Bitmap b = new Bitmap(mf);
                             return b;
                         }
                     }
                 }
             }
             finally
             {
                 CloseClipboard();
             }
 
 
 
[DllImport("User32.dll")]         [return: MarshalAs(UnmanagedType.Bool)]         public static extern bool OpenClipboard(IntPtr hWndNewOwner);
 
[DllImport("User32.dll")]         [return: MarshalAs(UnmanagedType.Bool)]         public static extern bool CloseClipboard();     [DllImport("User32.dll")]         public static extern IntPtr GetClipboardData(System.UInt32 uFormat);

调试,运行,成功。呵呵,又是得意的笑。提交代码(期间省略若干额外代码)。 
楼主又一次兴冲冲的发邮件给大家:excel的拍图可以用啦,大家快来享用吧。 
然后,大家很配合纷纷发来贺电,然后。。。。 
然后。。。。 
然后什么,然后没了,很抱歉让大家失望了,这次没出问题。搞定。得意的笑。 
总结一下吧: 
1. 第一点要注意的是,Excel2007和Excel2010的拷贝数据格式不一样,要特别注意。 
2. 很显然,excel里面凡是带有CopyPIcture方法的对象,都可以这样拍图。 粗略的看了一下,很多对象 都有这个方法,Range,Shape,Chart等等。 
3. 另外,对于Chart对象,它还有一个Export方法,可以直接导出成图片。 
4. 辛勤的楼主把上面的方法稍稍包装了一个Win32ClipboardHelper, 使用其中的GetImage传入excel的hwnd,就可以从剪贴板里面取出图片了。  上传到附件中,供大家享用。 
5. 最后,友情提醒,由于某些原因,上文中出现的代码都是示意代码,与真实项目无关,也不保证上面的代码能编译通过,大家领会精神,不可较真。

在以上如何把Excel中的单元格等对象保存成图片的学习中,我们又增加了对Excel使用的认识。如果在项目中需要集成Excel的功能,还可以利用一下开发工具。SpreadJS 是企业级JavaScript电子表格控件,能将电子表格、数据可视化及计算功能集成在JavaScript Web应用程序中,能创建计算器、动态交互式仪表盘和样式丰富的报表。

源码下载

Win32ClipboardHelper.zip

如何把Excel中的单元格等对象保存成图片的更多相关文章

  1. [转载]Java读取Excel中的单元格数据

    目前网上能找到的读取Excel表格中数据的两种比较好的方案:PageOffice好用开发效率高:POI免费.供大家参考,针对具体情况选择具体方案. 1. PageOffice读取excel impor ...

  2. EXCEL中统计单元格内容出现次数

    参考网站: https://jingyan.baidu.com/article/7c6fb428dfcc9580642c90ae.html 统计单元格内容出现次数是工作中经常会涉及到的问题. 那么,如 ...

  3. 最近开发的项目,遇到用户上传excel文件并导入数据到系统这个需求,而有excel中有的单元格是日期格式,本文介绍怎么从excel中读取日期格式的数据。

    可以先判断单元格的类型,有的日期是字符串存储的,有的是按日期存储的(单元格按数字解析),代码如下: Cell cell = row.getCell(); Date date = null; if (c ...

  4. C#中怎么在EXCEL中的单元格中画斜线啊 ??

    Code Snippet 做法: 1,先添加引用COM,找 Excel 2,using Excel = Microsoft.Office.Interop.Excel; 3, 代码 private Ex ...

  5. NPOI设置Excel中的单元格识别为日期

    只有月/日/年的格式,才能显示为Date 其他的,都是显示为Custom

  6. PHP Excel导入日期单元格处理

    PHPExcel导入Excel文件,对Excel中日期单元格处理 /** * 判断字符串是否是日期格式 * @param $date * @param $format * @return bool * ...

  7. BitmapUtil【缩放bitmap以及将bitmap保存成图片到SD卡中】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 用于缩放bitmap以及将bitmap保存成图片到SD卡中 效果图 代码分析 bitmapZoomByHeight(Bitmap s ...

  8. 读取Excel文件中的单元格的内容和颜色

    怎样读取Excel文件中的单元格的内容和颜色 先创建一个Excel文件,在A1和A2中随意输入内容,设置A1的字体颜色为红色,A2的背景为黄色.需要 using Excel = Microsoft.O ...

  9. 在Excel工作表单元格中引用当前工作表名称

    在Excel工作表单元格中引用当前工作表名称 有多份Excel表格表头标题都为"××学校第1次拉练考试××班成绩表",由于工作表结构都是一样的,所以我每次都是复制工作表然后编辑修改 ...

随机推荐

  1. oracle和mysql几点差异对比

    Oracle与mysql差异性总结 之前有个项目是用oracle数据库进行开发,需要把数据库改成mysql,遇到了一些地方需要注意的,就简单记了下来. 备注: 再把oracle转成mysql的时候,表 ...

  2. codeforge免费下载账号 积分账号 共享账号

    codeforge网站下载代码很好,没有积分怎么办?那么多好的matlab代码,matlab程序,C,JAVA等等,都要充值啊!!! 请用下面共享的codeforge账号密码========> ...

  3. C# TreeView设置SelectedNode设置无效的问题

    在设置Treeview.SelectedNode = newTreeNode(找到的TreeNode)时,界面上没呈现选择状态. 此时可能是treeview没有获取焦点,但是即使没有焦点,也可以让选中 ...

  4. Effective Java 第三版——1. 考虑使用静态工厂方法替代构造方法

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  5. Windows_server_2012-r2_x64安装教程

    版本: Windows_server_2012-r2_x64 工具: VMware vSphere Client 镜像地址: http://www.xpgod.com/soft/10718.html( ...

  6. Java 模拟栈结构

    栈和队列: 通常是作为程序猿的工具,用于辅助构思算法.生命周期较短,执行时才被创建 訪问受限.在特定时刻,仅仅有一个数据可被读取或删除 是一种抽象的结构.内部的实现机制.对用户不可见.比方用数组.链表 ...

  7. XMPP学习及使用1

    XMPP 简单介绍 本小节将简要介绍 XMPP,它的起源.以及为何它是一个适合实时 web 通信的协议.您将检查 XMPP 通信设置的组件,并查看展示这些组件怎样使用的演示样例. Web 标准和 XM ...

  8. Docker for Windows 使用入门

    欢迎来到Docker for Windows! Docker是用于创建Docker应用程序的完整开发平台,Docker for Windows是在Windows系统上开始使用Docker的最佳方式. ...

  9. XMind常用快捷方式汇总

    快捷键(Windows) 快捷键(Mac) 描述 Ctrl+N Command+N 建立新工作簿 Ctrl+O Command+O 开启工作簿 Ctrl+S Command+S 储存目前工作簿 Ctr ...

  10. map对象拷贝问题

    map对象赋值: HashMap<String,Object> hm = new HashMap(); HashMap<String,Object> hmCopy = new ...