如何把Excel中的单元格等对象保存成图片
对于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应用程序中,能创建计算器、动态交互式仪表盘和样式丰富的报表。
源码下载
如何把Excel中的单元格等对象保存成图片的更多相关文章
- [转载]Java读取Excel中的单元格数据
目前网上能找到的读取Excel表格中数据的两种比较好的方案:PageOffice好用开发效率高:POI免费.供大家参考,针对具体情况选择具体方案. 1. PageOffice读取excel impor ...
- EXCEL中统计单元格内容出现次数
参考网站: https://jingyan.baidu.com/article/7c6fb428dfcc9580642c90ae.html 统计单元格内容出现次数是工作中经常会涉及到的问题. 那么,如 ...
- 最近开发的项目,遇到用户上传excel文件并导入数据到系统这个需求,而有excel中有的单元格是日期格式,本文介绍怎么从excel中读取日期格式的数据。
可以先判断单元格的类型,有的日期是字符串存储的,有的是按日期存储的(单元格按数字解析),代码如下: Cell cell = row.getCell(); Date date = null; if (c ...
- C#中怎么在EXCEL中的单元格中画斜线啊 ??
Code Snippet 做法: 1,先添加引用COM,找 Excel 2,using Excel = Microsoft.Office.Interop.Excel; 3, 代码 private Ex ...
- NPOI设置Excel中的单元格识别为日期
只有月/日/年的格式,才能显示为Date 其他的,都是显示为Custom
- PHP Excel导入日期单元格处理
PHPExcel导入Excel文件,对Excel中日期单元格处理 /** * 判断字符串是否是日期格式 * @param $date * @param $format * @return bool * ...
- BitmapUtil【缩放bitmap以及将bitmap保存成图片到SD卡中】
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 用于缩放bitmap以及将bitmap保存成图片到SD卡中 效果图 代码分析 bitmapZoomByHeight(Bitmap s ...
- 读取Excel文件中的单元格的内容和颜色
怎样读取Excel文件中的单元格的内容和颜色 先创建一个Excel文件,在A1和A2中随意输入内容,设置A1的字体颜色为红色,A2的背景为黄色.需要 using Excel = Microsoft.O ...
- 在Excel工作表单元格中引用当前工作表名称
在Excel工作表单元格中引用当前工作表名称 有多份Excel表格表头标题都为"××学校第1次拉练考试××班成绩表",由于工作表结构都是一样的,所以我每次都是复制工作表然后编辑修改 ...
随机推荐
- linux配置分步安装lnmp环境----ghj
前台:nignx 后台:apache[linux命令]用户文件目录启动定时任务:[开启RZ命令]yum -y install lrzsz [防火墙]防火墙配置文件: /etc/sysconfig/ip ...
- Nginx动静分离实现
Nginx动静分离实现: Nginx是一种轻量级,高性能,多进程的Web服务器,非常适合作为静态资源的服务器使用,而动态的访问操作可以使用稳定的Apache.Tomcat及IIS等来实现,这里就以Ng ...
- Linux yum安装和源码安装
转载注明出处:原文地址 Linux Yum 在线安装 在线:Yum配置地址:/etc/yum.repos.d/CentOS-Base.repo 离线:光盘搭建Yum源 挂载光盘 使在线Yum源失效:m ...
- ArcGIS jsAPI (4.x)本地部署字体符号乱码
在下载了新版arcigs 的 JS API 后,每次部署在IIS中都会出现部件字体乱码的问题,需配置响应标头和添加文件映射 一. HTTP响应标头配置 在 IIS 中的 HTTP响应标头 中加入以下配 ...
- C# DateDateTimePicker设置属性ShowCheckBox为True
DateDateTimePicker的属性ShowCheckBox为True后,可以使用时间控件的复选框. 但是如果,你想设置CheckBox的选中状态为False的话,那么请注意赋时间值和赋状态值的 ...
- iscroll使用之页面卡顿问题
最近在开发项目时,遇到一个问题,使用iscroll实现的页面滚动,测试时发现在chrome浏览器中的模拟移动设备页面不能平滑滚动,有卡顿现象,在android手机端也有同样的问题. 在github上搜 ...
- python爬虫(六)_urllib2:handle处理器和自定义opener
本文将介绍handler处理器和自定义opener,更多内容请参考:python学习指南 opener和handleer 我们之前一直使用的是urllib2.urlopen(url)这种形式来打开网页 ...
- SharePoint Patterns and Practices 简介
作者:陈希章 发表于 2017年12月22日 SharePoint Patterns and Practices,以下简称PnP,是由微软的SharePoint产品组发起并主持的一个有关SharePo ...
- 学习customEvent
title: 认真学习customEvent tags: DOM date: 2017-7-22 23:20:57 --- 最近要实现一个模拟的select元素组件,所以好好看了这个自定义事件api, ...
- 如何导入外部的源码到eclipse中
用struts,spring等框架开发也有两年的时间了,一直很少去阅读其源码,每次在eclipse编码的过程中想要看某一个类的源码,ctrl点击总是出现source not found的提示,也没有去 ...