天天看點

Silverlight 4中把DataGrid資料導出Excel—附源碼下載下傳

Silverlight中常常用到DataGrid來展示密集資料. 而常見應用系統中我們需要把這些資料導入導出到固定Office套件中例如常用的Excel表格. 那麼在Silverlight 中如何加以實作?

在參考大量資料後 提供參考思路如下:

A:純用戶端導出處理.利用Silverlight 與Javascript 進行互動實作導出Excel.

B:伺服器端導出.獲得DataGrid資料源. 傳遞給WCF Service到伺服器端. 然後把傳回資料通過Asp.net中通用處理導出Excel方法加以實作.

方法A實作導入導出核心在JS腳本中. 屬于純用戶端互動. 簡潔實用. 但問題也正是源自于JS腳本. 如果對Excel資料格式進行變動. 大家都應該知道JS支援的調試時不容易控制的. 是以很容易出現腳本錯誤. 而且每次修改起來都很麻煩費時.

方法B也算是各位非常熟悉一種方式. 獲得資料把資料傳入Asp.net中通用實作導出Excel方法. 加以實作. 大部分編碼都在伺服器端. 比JS要容易控制. 是以方法B相比方法A而要效率更高, 且更容易移植 修改控制.

Silverlight中有沒有其他方式來實作? 答案是有的.Silverlight當在使用進階權限運作Out-Of-Broswer[OOB]浏覽器外應用時. Silverlight 4版本中微軟為了支援企業使用者提供類似Office自動化功能,引入Com+自動化. COM+自動化僅支援有進階信任許可的OOB Silverlight應用,進階信任許可意味着操作者可以在少許限制的條件下,在Windows計算機上執行幾乎所有的指令,這就對Silverlight 實作Excel導出提供了可能.

先看看實作效果.

<a href="http://blog.51cto.com/attachment/201201/174042474.jpg" target="_blank"></a>

注意:當直接點選導出按鈕時.會提示異常:"目前上下文不支援此操作."因使用Com+自動化需要在OOB應用模式才具有權限操作.是以右鍵點選程式選擇程式安裝:

<a href="http://blog.51cto.com/attachment/201201/174048254.png" target="_blank"></a>

安裝本地後.自動打開:

<a href="http://blog.51cto.com/attachment/201201/174053541.png" target="_blank"></a>

點選導出到Excel按鈕 導出效果[有點粗糙].:

<a href="http://blog.51cto.com/attachment/201201/174104226.png" target="_blank"></a>

A:如何實作

頁面XAML布局:為了示範目的隻有個Datagrid和一個Button按鈕如下.

&lt;Grid x:Name="LayoutRoot" Background="White" Height="500" Width="707"&gt;  

         &lt;sdk:DataGrid AutoGenerateColumns="False"  Margin="24,61,191,207" Name="dataGrid1"&gt;  

             &lt;sdk:DataGrid.Columns &gt;  

                 &lt;sdk:DataGridTextColumn Header="編     号" Binding="{Binding Id}"&gt;&lt;/sdk:DataGridTextColumn&gt;  

                 &lt;sdk:DataGridTextColumn Header="顧客姓名" Binding="{Binding CustomerName}"&gt;&lt;/sdk:DataGridTextColumn&gt;  

                 &lt;sdk:DataGridTextColumn Header="地               址" Binding="{Binding Address}"&gt;&lt;/sdk:DataGridTextColumn&gt;  

                 &lt;sdk:DataGridTextColumn Header="電話号碼" Binding="{Binding Telephone}"&gt;&lt;/sdk:DataGridTextColumn&gt;  

             &lt;/sdk:DataGrid.Columns&gt;  

         &lt;/sdk:DataGrid&gt;  

         &lt;Button Content="導出到Excel中"   Background="Red" Height="34"  Margin="24,21,550,445" Name="button1"  Width="133" Click="button1_Click" /&gt;  

     &lt;/Grid&gt; 

DataGrid資料綁定. 一個Customer類提供一個List集合實作簡單資料源:

public class Customer  

     {  

         public int Id { get; set; }  

         public string CustomerName { get; set; }  

         public string Address { get; set; }  

         public string Telephone { get; set; }  

         /// &lt;summary&gt;  

         /// 擷取一個批量資料用來綁定DataGrid中 示範由DataGrid 導出到資料庫中  

         /// Author:chenkai Date:2010年6月9日16:25:25  

         /// &lt;/summary&gt;  

         public static List&lt;Customer&gt; GetCustomerListBind()  

         {  

             List&lt;Customer&gt; getcuslist = new List&lt;Customer&gt;();  

             Random getdom = new Random();  

             for (int count = 0; count &lt; 12; count++)  

             {  

                 getcuslist.Add(new Customer {  Id=count, CustomerName=count.ToString()+"陳凱", Address=getdom.Next(15,200).ToString()+"中國", Telephone=getdom.Next(0,230000).ToString()});  

             }  

             return getcuslist;  

         }  

     } 

背景操作示範:

public partial class MainPage : UserControl  

         public MainPage()  

             InitializeComponent();  

             //綁定資料  

             List&lt;Customer&gt; getcuslist = Customer.GetCustomerListBind();  

             if (getcuslist.Count &gt; 0)  

                 this.dataGrid1.ItemsSource = getcuslist;  

             //綁定Button事件  

             this.button1.Click += new RoutedEventHandler(ExpertDataToExcel);  

         void ExpertDataToExcel(object sender, RoutedEventArgs e)  

             int rowIndex = 1;  

             int coulmnIndex = 1;  

             try  

                 dynamic excel = AutomationFactory.CreateObject("Excel.Application");  

                 excel.workbooks.Add();  

                 dynamic sheet = excel.ActiveSheet;  

                 //加載Excel表頭資料  

                 for (int i = 0; i &lt; this.dataGrid1.Columns.Count; ++i)  

                 {  

                     dynamic headerCell = sheet.Cells[rowIndex, coulmnIndex + i];  

                     //把目前Grid中表頭資訊指派給Excel表頭.  

                     headerCell.Value = this.dataGrid1.Columns[i].Header;  

                     headerCell.Font.Bold = true;//加粗  

                     headerCell.Interior.Color = 0xFF00;//設定背景顔色  

                 }  

                 //加載展示資料  

                 foreach (Customer customer in this.dataGrid1.ItemsSource)  

                     rowIndex++;  

                     //column 1  

                     dynamic cellFirstName = sheet.Cells[rowIndex, 1];  

                     cellFirstName.Value = customer.Id;  

                     cellFirstName.Font.Color = 003399;  

                     //column 2  

                     dynamic cellLastName = sheet.Cells[rowIndex, 2];  

                     cellLastName.Value = customer.CustomerName;  

                     cellLastName.Font.Color = 003399;  

                     //column 3  

                     dynamic cellAge = sheet.Cells[rowIndex, 3];  

                     cellAge.Value = customer.Address;  

                     cellAge.Font.Color = 003399;  

                     //column 4  

                     dynamic cellSubscribed = sheet.Cells[rowIndex, 4];  

                     cellSubscribed.Value = customer.Telephone;  

                     cellSubscribed.Font.Color = 003399;  

                 excel.Visible = true;  

                 MessageBox.Show("導出成功Excel中!");  

             catch (Exception ex)  

                 MessageBox.Show("Error generating excel: " + ex.Message);  

如上已經實作導出Excel功能. 但不要忘了設定Silverlight Application 支援OOB.選擇Silverlight項目屬性. 在屬性Silverlight分欄設定:OOB可用

右鍵菜單可見Install Menu選項:

<a href="http://blog.51cto.com/attachment/201201/174110275.png" target="_blank"></a>

如上即簡單實作Silverlight直接從DataGrid導出Excel表格效果. 仔細分析一下背景代碼: 應該發現我使用Silverlight 4和.NET 4版本共有的一個新特性dynamic object.

在Silverlight 4 和.NEt 4引入Dynamic關鍵字.讓我們可以在不引用MS Office DllS情況下直接操作使用MS Office Com.在.NET 4中建立一個Excel Document如下編碼:

dynamic excel = Microsoft.VisualBasic.Interaction.CreateObject("Excel.Application", string.Empty); 

在Silverlight 4中:

dynamic excel = AutomationFactory.CreateObject("Excel.Application"); 

using System.Runtime.InteropServices.Automation;  

using System.Runtime.InteropServices;  

對于Dynamic關鍵字現在在.NET去年還是Beta版本很多人對此有些微詞,依然還處在一個争論之中.

Dynamic編碼時沒有智能提示, 無法再編譯時做靜态類型檢查等.這對于使用慣了.NET 确實讓我感到很不舒服. 不過在使用Dynamic時最想讓我想到.NET 3.5版本中Var,

當var在C#3.0中剛剛出現的時候就引起了一些人的質疑,後來微軟解釋var隻是隐含類型聲明符,并且隻能用作局部變量,它其實仍然是強類型,隻不過是編譯器由初始化結果推斷而來,是以對這個變量仍然可以可以使用VS的隻能提示。現在dynamic則真正往動态特性邁進了一大步,根據Anders的解釋,dynamic是指動态的靜态類型,也就是說它本質上仍然是靜态類型,隻不過它告訴編譯器忽略對它的靜态類型檢查,它會在運作時才進行類型檢查,它可以應用在基本上所有的C#類型上面,如方法,操作符,索引器,屬性,字段,它其實是通過統一的方式來調用方法、屬性等操作

另外一個很重要地方Anders提到C#的未來時候指出C#4.0的特點是動态程式設計.在一定程度上Dynamic超越了Var. Var 相當于從3.0 到4.0版本一個過渡品.雖然二者使用方法有很多相似之處. 關于Dynamic更多資訊 .Net4.0新特性資料有所說明.

B:一點疑問

運作指令或者可執行(EXE)檔案

讀系統資料庫

通路本地ODBC

讀/寫硬碟(在上文提到的限制條件下)

自動化Office

Shawn Wildermuth說:我不想過多地争論。我了解為什麼微軟這樣做,但是我還是認為這樣做很不妥。恕我直言,COM隻能在Windows下運作對其他平台來說很不爽。

Marlon Grech,微軟用戶端應用的MVP說:我很贊同Shawn所說的,為SL增加COM+支援違反了跨平台和一次編寫處處運作的主張。即使他們為AppleScript增加支援,對我們來說也是噩夢一場。另外……我要說,武器本身沒什麼問題,關鍵是使用這些武器的人。對吧?:)

Jeremiah Morrill:在我看來,主要的“概念上”的安全問題是“信任級别”。CoreCLR也還沒有授予“完全信任”模式,但這些COM執行個體,按照定義,是運作在沙箱之外的。我想這會讓那些期望或設想得到A,卻拿到B的開發者和使用者都很迷糊……一般來說,在讨論安全問題時,這是不妥的。 

對于一些人來說,COM+自動化和在進階信任許可下運作Silverlight應用并不是什麼安全問題,因為使用者需要先安裝才能運作OOB應用,他們也被明顯警告說應用将會通路他們的硬碟。理論上,這會像其他應用一樣,運作一個桌面應用——但是,恐懼恐怕來自于Silverlight被假設成一個運作在沙箱裡的絕對安全的浏覽器應用,而不是一個桌面應用。

另外一個問題是移植性。對于缺少COM+的Mac機而言,這個功能有什麼用嗎?Angel提到說,微軟正在調查通過AppleScript在Mac機上支援COM的可能性,并說“如果微軟最終沒有決定在Mac機上支援Silverlight 4 RTM,那麼,并不是因為它不能做到”。對于Moonlight,Angel說:

Moonlight在一開始建立時,就有超級安全的模式。Mono支援在有着完全信任能力的GtkWidget中運作Moonlight。是以,在Silverlight有進階權限模式時,Mono确實完全信任模式。  

Silverlight 4增加Com應用 雖然在一定程度滿足企業級使用者對Silverlight 更為具體需要. 但在一定程度上颠覆Silverlight 在原始設計初衷.

Silverlight 4 從DataGrid導出EXcel示範Demo:源碼下載下傳見附件。

<a href="http://down.51cto.com/data/2359688" target="_blank">附件:http://down.51cto.com/data/2359688</a>

本文轉自chenkaiunion 51CTO部落格,原文連結:http://blog.51cto.com/chenkai/764898

繼續閱讀