ASP.NET中GridView數(shù)據(jù)導(dǎo)出EXCEL小結(jié)
時間:2010-12-13 11:26來源:未知 作者:admin 點擊:480次我要投稿 高質(zhì)量的ASP.NET空間,完美支持1.0/2.0/3.5/4.0/MVC等
本周按業(yè)務(wù)部門的要求,做一個客戶拜訪登記管理的小程序(B/S模式),在這里面用到了GridView來顯示根據(jù)條件查詢到的數(shù)據(jù),但業(yè)務(wù)部門同時要求數(shù)據(jù)要導(dǎo)出為EXCEL方面使用,在網(wǎng)上查找了很多資料,匯總并根據(jù)自己的實際情況編寫使用,效果不錯,現(xiàn)記下以備忘并與大家分享。(開發(fā)環(huán)境:Windows 2003/VS 2005/SQL SERVER 2005)
導(dǎo)出為EXCEL的代碼網(wǎng)上有很多,分析后選擇了最簡單的直接用流方法導(dǎo)出,文件類型為XLS文件,但實際上是一個文本文件(HTML格式),這樣的優(yōu)點是1、服務(wù)器本身不需要安裝OFFICE組件,有很好的通用性;2、導(dǎo)出文件為直接生成直接下載,不需要預(yù)先保存在服務(wù)器上,對空間大小沒有需求;3、控制簡單,代碼容易理解。缺點是有一些EXCEL特有的功能可能無法實現(xiàn)吧。
先將代碼貼出,再一步步的講一下當(dāng)時遇到的問題和處理方法吧:
GridView導(dǎo)出到EXCEL
Protected Sub btn_export_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btn_export.Click
Response.Clear()
Response.Buffer = True
Response.Charset = "utf-8"
Dim FileName As String
If Session("branch_no") = "" Then
lbl_inputlist.Text = "登錄已超時,請重新登錄后再導(dǎo)出!"
Exit Sub
End If
FileName = Session("branch_no") & "_" & DateTime.Now.ToString("yyyyMMddHHmmssfff") & ".xls"
'FileName = Session("branch_no") & Path.GetRandomFileName() & ".xls"
Response.AddHeader("Content-Disposition", "attachment;filename=" & FileName)
Response.ContentType = "application/ms-excel"
Dim strWriter As New StringWriter()
Dim htw As New HtmlTextWriter(strWriter)
GV_list.BackColor = System.Drawing.Color.White
GV_list.ForeColor = System.Drawing.Color.Black
GV_list.BorderWidth = 1
GV_list.RowStyle.BackColor = System.Drawing.Color.White
GV_list.RowStyle.ForeColor = System.Drawing.Color.Black
GV_list.AlternatingRowStyle.BackColor = System.Drawing.Color.White
GV_list.BorderStyle = BorderStyle.Solid
GV_list.BorderWidth = 1
GV_list.AlternatingRowStyle.ForeColor = System.Drawing.Color.Black
GV_list.HeaderStyle.BackColor = Drawing.Color.White
GV_list.HeaderStyle.ForeColor = Drawing.Color.Black
GV_list.AllowPaging = False
GV_list.AllowSorting = False
GV_list.DataBind()
GV_list.RenderControl(htw)
Response.Write(strWriter.ToString)
Response.End()
GV_list.AllowPaging = True
GV_list.DataBind()
End Sub
Public Overrides Sub VerifyRenderingInServerForm(ByVal control As Control)
End Sub
Protected Sub GV_list_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GV_list.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
e.Row.Cells(0).Attributes.Add("style", "vnd.ms-excel.numberformat:@;")
e.Row.Cells(4).Attributes.Add("style", "vnd.ms-excel.numberformat:@;")
e.Row.Cells(5).Attributes.Add("style", "vnd.ms-excel.numberformat:@;")
End If
End Sub
遇到的問題:
一、將網(wǎng)上找到的代碼放到相應(yīng)的地方后,直接運行,程序中斷在“GV_list.RenderControl(htw)”處,提示“類型“GridView”的控件“GV_list”必須放在具有 runat=server 的窗體標(biāo)記內(nèi)。”,查看了半天也沒有找到原因,再次上網(wǎng)搜索,得到結(jié)果,在代碼中要加上一個阻止系統(tǒng)自動調(diào)用檢查的過程才能避免這種情況,將過程加上后,果然正常。分析后認(rèn)為出現(xiàn)問題的原理是這樣的,當(dāng)點擊導(dǎo)出按鈕時,因為已將返回的文件類型改成了EXCEL文件而非標(biāo)準(zhǔn)的ASPX返回文件(Response.ContentType = "application/ms-excel"),調(diào)用VerifyRenderingInServerForm方法進(jìn)行檢查的時候,控件當(dāng)然不可能在任何一個Form的runat=server中了,因此報錯,加上這個空過程后正常。
Public Overrides Sub VerifyRenderingInServerForm(ByVal control As Control)
'空過程
End Sub
二、導(dǎo)出的EXCEL表,打開后會根據(jù)GridView的設(shè)定,有不同的前景色和背景色,不利于查看、打印。分析GirdView的各參數(shù),將表格、行、列及表頭標(biāo)題行的顏色全部設(shè)為黑白的,解決了這個問題。
導(dǎo)出外觀
'表格外觀(前景色、背景色)
GV_list.BackColor = System.Drawing.Color.White
GV_list.ForeColor = System.Drawing.Color.Black
'表格線
GV_list.BorderWidth = 1
'數(shù)據(jù)行外觀
GV_list.RowStyle.BackColor = System.Drawing.Color.White
GV_list.RowStyle.ForeColor = System.Drawing.Color.Black
'數(shù)據(jù)交替行外觀
GV_list.AlternatingRowStyle.BackColor = System.Drawing.Color.White
GV_list.AlternatingRowStyle.ForeColor = System.Drawing.Color.Black
'控件外觀
GV_list.BorderStyle = BorderStyle.Solid
GV_list.BorderWidth = 1
'表頭標(biāo)題行外觀
GV_list.HeaderStyle.BackColor = Drawing.Color.White
GV_list.HeaderStyle.ForeColor = Drawing.Color.Black
三、數(shù)據(jù)較多時,GridView設(shè)定了分頁查看及排序,但在導(dǎo)出時,只導(dǎo)出第一頁的內(nèi)容及頁碼鏈接,標(biāo)題行還帶有排序鏈接,實際上在需要導(dǎo)出數(shù)據(jù)的時候,我們需要的是一次獲得所有數(shù)據(jù),EXCEL也有自己的排序等功能,只需要導(dǎo)出一個純粹的數(shù)據(jù)就可以了,因此,需要將分頁及排序功能屏蔽。
'屏蔽分頁
GV_list.AllowPaging = False
'屏蔽排序
GV_list.AllowSorting = False
四、一開始,我的導(dǎo)出文件的文件名是固定的,后來發(fā)現(xiàn)在實際使用過程中,如果一個操作人員做了多次導(dǎo)出操作的話,如果不小心可能會將原來的導(dǎo)出文件覆蓋,因此就使用當(dāng)前時間加操作機構(gòu)號的方式來得到一個唯一文件名,防止這種情況發(fā)生,在實際使用中,還可以再加上報表的名稱。
微軟自己也為這種情況提供了一個方法,獲取一個隨機的文件名(Path.GetRandomFileName()),但我感覺這種方法可能用于生成臨時文件更好一些,而下載文件的話,用日期時間做文件名最好。
獲取隨機文件名
Dim FileName As String
FileName = Session("branch_no") & "_" & DateTime.Now.ToString("yyyyMMddHHmmssfff") & ".xls"
'下面這種方法用來獲取臨時文件名比較合適
'FileName = Session("branch_no") & Path.GetRandomFileName() & ".xls"
Response.AddHeader("Content-Disposition", "attachment;filename=" & FileName)
五、在導(dǎo)出后,發(fā)現(xiàn)在生成的文件中,大于11位的數(shù)字都被EXCEL顯示成了科學(xué)計數(shù)法,如果是校驗位不為X的18位身份證號碼的話,最后三位還會被設(shè)為“0”,手機號雖然可以正確顯示,但如果是座機的話,區(qū)號的第一位0也會被自動抹掉,使用起來十分的不方便。
以前在使用一些程序時也遇到過這種情況,當(dāng)時開發(fā)人員的處理辦法是在這些字段前面或最后加一個空格、下劃線或者單引號等等,但這樣也會造成不便,比如在EXCEL表中對這些數(shù)據(jù)對比、排序、操作時也會有問題,如果將空格或下劃線刪除,又會馬上變?yōu)榭茖W(xué)計數(shù)法,十分不方便。
感謝互聯(lián)網(wǎng),呵呵,馬上找到了合適的辦法,在導(dǎo)出時就指定了該列為文本格式,這樣的話,用EXCEL打開文件也就是正常的了。
在下面的代碼中,我的0、4、5列分別是工號(14位數(shù)字)、身份證號碼、聯(lián)系電話,已被指定為文本格式,在實際使用中,可根據(jù)自己的數(shù)據(jù)情況進(jìn)行修改,但要記住第一列是Cells(0),以此類推。
指定文本格式
Protected Sub GV_list_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GV_list.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
e.Row.Cells(0).Attributes.Add("style", "vnd.ms-excel.numberformat:@;")
e.Row.Cells(4).Attributes.Add("style", "vnd.ms-excel.numberformat:@;")
e.Row.Cells(5).Attributes.Add("style", "vnd.ms-excel.numberformat:@;")
End If
End Sub
如果數(shù)據(jù)量很大,而你又是一個注重細(xì)節(jié)的人(在乎文件大小和數(shù)據(jù)流量的人)的話,也可以定義一個style為文本格式,然后將相應(yīng)的列指定為此style,下面就是一個例子,而且我對日期格式也進(jìn)行了指定,這樣的話日期看起來也好看一些。
style方式
'下面的代碼是在導(dǎo)出事件中的
GV_list.RenderControl(htw)
'將css代碼加在此處
response.Write("<style> .text { vnd.ms-excel.numberformat:@; } .cndate {vnd.ms-excel.numberformat:yyyy年m月d日} </style>")
Response.Write(strWriter.ToString)
'下面是一個單獨的過程
Protected Sub GV_list_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GV_list.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
e.Row.Cells(0).Attributes.Add("class", "text")
e.Row.Cells(4).Attributes.Add("class", "text")
e.Row.Cells(5).Attributes.Add("class", "text")
e.Row.Cells(6).Attributes.Add("class", "cndate")
End If
End Sub
邊學(xué)邊做,花了半天的時間,將整個GridView導(dǎo)出數(shù)據(jù)到EXCEL的功能了解了一個大概,現(xiàn)匯總一下和大家一起分享,因為這次的數(shù)據(jù)基本可以肯定沒有超過六萬條的可能,就沒有考慮OFFICE2003無法打開的情況,而且如果數(shù)據(jù)超過了最大允許條數(shù),因為生成并下載的實際上文本格式,也可以直接使用OFFICE2007來打開操作,關(guān)于多個工作表導(dǎo)出及導(dǎo)出為“真正”的EXCEL文件的。