如何把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應用程序中,能創建計算器、動態交互式儀表盤和樣式豐富的報表。

源碼下載

Win32ClipboardHelper.zip


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM