项目需要,最近一直在弄WEB报表方面的东西。在做的时候。根据用户需求。做了一个表格数据(DataGrid)导出到Excel。在做的时候发现了个问题。
由于数据量比较大。势必要做分页。如此这样。利用最简单的属性生成器。给DataGrid分页。然后写导出到Excel的代码。代码如下:
private
void
ExportExcelFromDataGrid(
string
filename , System.Web.UI.WebControls.DataGrid ToExcelGrid )
...
{ Response.Clear(); Response.Buffer=true; Response.Charset="utf-8"; Response.AppendHeader("Content-Disposition","attachment;filename="+Server.UrlEncode ( filename ) ); Response.ContentEncoding=System.Text.Encoding.Default;//设置输出流为简体中文 Response.ContentType = "application/ms-excel";//设置输出文件类型为excel文件。 this.EnableViewState = false; System.Globalization.CultureInfo myCItrad = new System.Globalization.CultureInfo("ZH-CN",true); System.IO.StringWriter oStringWriter = new System.IO.StringWriter(myCItrad); System.Web.UI.HtmlTextWriter oHtmlTextWriter = new System.Web.UI.HtmlTextWriter(oStringWriter); ToExcelGrid.RenderControl(oHtmlTextWriter); Response.Write(oStringWriter.ToString()); Response.End(); }
然后在一个按钮事件中。调用下。代码如下
private
void
Button3_Click(
object
sender, System.EventArgs e)
...
{ string filename = "test.xls"; this.ExportExcelFromDataGrid ( filename , this.DataGrid1 ); }
结果程序给报错。如下:
“/Web_DVBAres_C2.2”应用程序中的服务器错误。
--------------------------------------------------------------------------------
类型“DataGridLinkButton”的控件“DataGrid1__ctl5__ctl1”必须放在具有 runat=server 的窗体标记内。
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。
异常详细信息: System.Web.HttpException: 类型“DataGridLinkButton”的控件“DataGrid1__ctl5__ctl1”必须放在具有 runat=server 的窗体标记内。
源错误:
行 61: System.IO.StringWriter oStringWriter = new System.IO.StringWriter(myCItrad);
行 62: System.Web.UI.HtmlTextWriter oHtmlTextWriter = new System.Web.UI.HtmlTextWriter(oStringWriter);
行 63: ToExcelGrid.RenderControl(oHtmlTextWriter);
行 64: Response.Write(oStringWriter.ToString());
行 65: Response.End();
源文件: c:/inetpub/wwwroot/web_dvbares_c2.2/webform3.aspx.cs 行: 63
堆栈跟踪:
[HttpException (0x80004005): 类型“DataGridLinkButton”的控件“DataGrid1__ctl5__ctl1”必须放在具有 runat=server 的窗体标记内。]
System.Web.UI.Page.VerifyRenderingInServerForm(Control control) +152
System.Web.UI.WebControls.LinkButton.AddAttributesToRender(HtmlTextWriter writer) +38
System.Web.UI.WebControls.WebControl.RenderBeginTag(HtmlTextWriter writer) +17
System.Web.UI.WebControls.DataGridLinkButton.Render(HtmlTextWriter writer) +25
System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +243
System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +72
System.Web.UI.WebControls.TableCell.RenderContents(HtmlTextWriter writer) +55
System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer) +29
System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +243
System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +72
System.Web.UI.WebControls.WebControl.RenderContents(HtmlTextWriter writer) +7
System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer) +29
System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +243
System.Web.UI.WebControls.Table.RenderContents(HtmlTextWriter writer) +99
System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer) +29
System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +243
System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +72
System.Web.UI.WebControls.WebControl.RenderContents(HtmlTextWriter writer) +7
System.Web.UI.WebControls.BaseDataList.Render(HtmlTextWriter writer) +27
System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +243
Web_DVBAres_C2._2.WebForm3.ExportExcelFromDataGrid(String filename, DataGrid ToExcelGrid) in c:/inetpub/wwwroot/web_dvbares_c2.2/webform3.aspx.cs:63
Web_DVBAres_C2._2.WebForm3.Button3_Click(Object sender, EventArgs e) in c:/inetpub/wwwroot/web_dvbares_c2.2/webform3.aspx.cs:132
System.Web.UI.WebControls.Button.OnClick(EventArgs e) +108
System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +57
System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +18
System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +33
System.Web.UI.Page.ProcessRequestMain() +1277原想“DataGridLinkButton”的控件“DataGrid1__ctl5__ctl1”必须放在具有 runat=server 的窗体标记内。 既然这么提示。最BC的做法。就是“DataGrid1__ctl5__ctl1”这个“控件“加上runat=server。结果在项目一搜。压根就没发现这个控件。既然这样。没办法。只有合理利用资源。Google下了。看了一些文章。发现是由于在DataGrid控件上。利用属性生成器。添加了分页“控件”。导致报错。去掉自带的分页功能。势必要写分页程序,而且还有可能要改动数据结构。得不偿失。没办法只好继续找办法。后面看到木野狐兄写的一个导出Excel的帮助类。直接资源利用。问题解决。附上野狐兄的代码(如果野狐兄不希望被转的话.麻烦说声.立马删*_*)
//
===============================================================================
//
//
从 DataGrid 或数据源中导出数据到 Excel 并提示下载的帮助类。
//
//
Author: Roger Chen (木野狐)
//
Date: 2005-1-27
//
Version: 1.22
//
History:
//
v1.00 使用静态方法的形式实现该类,提供多种重载方式。
//
v1.01 添加了对 DevExpress.Web.ASPxGrid.ASPxGrid 的直接导出支持。
//
v1.20 改写为实体类。 减少了重复代码。
//
v1.21 2005-2-1
//
修改了一个构造函数的重载形式中异常检测的代码。延迟到 Export() 方法。
//
v1.22 2005-2-3
//
1. 修正了 Export() 方法中缺少 _titles != null 判断的 bug.
//
2. 修正了长的数字被 Excel 自动转换为科学计数法的毛病。
//
(修改的办法来自
http://dotnet.aspx.cc
)
//
//
===============================================================================
namespace
Web_DVBAres_C2._2
...
{ using System; using System.IO; using System.Data; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Text; using System.Globalization; using System.Collections; //using DevExpress.Web.ASPxGrid; public class ExcelHelper ...{ Fields#region Fields string _fileName; DataTable _dataSource; string[] _titles = null; string[] _fields = null; int _maxRecords = 1000; #endregion Properties#region Properties /**//// <summary> /// 限制输出到 Excel 的最大记录数。超出则抛出异常 /// </summary> public int MaxRecords ...{ set ...{ _maxRecords = value; } get ...{ return _maxRecords; } } /**//// <summary> /// 输出到浏览器的 Excel 文件名 /// </summary> public string FileName ...{ set ...{ _fileName = value; } get ...{ return _fileName; } } #endregion .ctor#region .ctor /**//// <summary> /// 构造函数 /// </summary> /// <param name="titles">要输出到 Excel 的列标题的数组</param> /// <param name="fields">要输出到 Excel 的字段名称数组</param> /// <param name="dataSource">数据源</param> public ExcelHelper(string[] titles, string[] fields, DataTable dataSource): this(titles, dataSource) ...{ if (fields == null || fields.Length == 0) throw new ArgumentNullException("fields"); if (titles.Length != fields.Length) throw new ArgumentException("titles.Length != fields.Length", "fields"); _fields = fields; } /**//// <summary> /// 构造函数 /// </summary> /// <param name="titles">要输出到 Excel 的列标题的数组</param> /// <param name="dataSource">数据源</param> public ExcelHelper(string[] titles, DataTable dataSource): this(dataSource) ...{ if (titles == null || titles.Length == 0) throw new ArgumentNullException("titles"); //if (titles.Length != dataSource.Columns.Count) // throw new ArgumentException("titles.Length != dataSource.Columns.Count", "dataSource"); _titles = titles; } /**//// <summary> /// 构造函数 /// </summary> /// <param name="dataSource">数据源</param> public ExcelHelper(DataTable dataSource) ...{ if (dataSource == null) throw new ArgumentNullException("dataSource"); // maybe more checks needed here (IEnumerable, IList, IListSource, ) ??? // 很难判断,先简单的使用 DataTable _dataSource = dataSource; } public ExcelHelper() ...{} #endregion public Methods#region public Methods /**//// <summary> /// 导出到 Excel 并提示下载 /// </summary> /// <param name="dg">DataGrid</param> public void Export(DataGrid dg) ...{ if (dg == null) throw new ArgumentNullException("dg"); if (dg.AllowPaging || dg.PageCount > 1) throw new ArgumentException("paged DataGrid can't be exported.", "dg"); // 添加标题样式 dg.HeaderStyle.Font.Bold = true; dg.HeaderStyle.BackColor = System.Drawing.Color.LightGray; RenderExcel(dg); } /**//// <summary> /// 导出到 Excel 并提示下载 /// </summary> /// <param name="xgrid">ASPxGrid</param> /// <summary> /// 导出到 Excel 并提示下载 /// </summary> public void Export() ...{ if (_dataSource == null) throw new Exception("数据源尚未初始化"); if (_fields == null && _titles != null && _titles.Length != _dataSource.Columns.Count) throw new Exception("_titles.Length != _dataSource.Columns.Count"); if (_dataSource.Rows.Count > _maxRecords) throw new Exception("导出数据条数超过限制。请设置 MaxRecords 属性以定义导出的最多记录数。"); DataGrid dg = new DataGrid(); dg.DataSource = _dataSource; if (_titles == null) ...{ dg.AutoGenerateColumns = true; } else ...{ dg.AutoGenerateColumns = false; int cnt = _titles.Length; System.Web.UI.WebControls.BoundColumn col; if (_fields == null) ...{ for (int i=0; i<cnt; i++) ...{ col = new System.Web.UI.WebControls.BoundColumn(); col.HeaderText = _titles[i]; col.DataField = _dataSource.Columns[i].ColumnName; dg.Columns.Add(col); } } else ...{ for (int i=0; i<cnt; i++) ...{ col = new System.Web.UI.WebControls.BoundColumn(); col.HeaderText = _titles[i]; col.DataField = _fields[i]; dg.Columns.Add(col); } } } // 添加标题样式 dg.HeaderStyle.Font.Bold = true; dg.HeaderStyle.BackColor = System.Drawing.Color.LightGray; dg.ItemDataBound += new DataGridItemEventHandler(DataGridItemDataBound); dg.DataBind(); RenderExcel(dg); } #endregion private Methods#region private Methods private void RenderExcel(Control c) ...{ // 确保有一个合法的输出文件名 if (_fileName == null || _fileName == string.Empty || !(_fileName.ToLower().EndsWith(".xls"))) _fileName = GetRandomFileName(); HttpResponse response = HttpContext.Current.Response; response.Charset = "GB2312"; response.ContentEncoding = Encoding.GetEncoding("GB2312"); response.ContentType = "application/ms-excel/msword"; response.AppendHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(_fileName)); CultureInfo cult = new CultureInfo("zh-CN", true); StringWriter sw = new StringWriter(cult); HtmlTextWriter writer = new HtmlTextWriter(sw); writer.WriteLine("<meta http-equiv="Content-Type" content="text/html;charset=GB2312">"); DataGrid dg = c as DataGrid; if (dg != null) ...{ dg.RenderControl(writer); } else ...{ response.Write("OMG"); } c.Dispose(); response.Write(sw.ToString()); response.End(); } /**//// <summary> /// 得到一个随意的文件名 /// </summary> /// <returns></returns> private string GetRandomFileName() ...{ Random rnd = new Random((int) (DateTime.Now.Ticks)); string s = rnd.Next(Int32.MaxValue).ToString(); return DateTime.Now.ToShortDateString() + "_" + s + ".xls"; } private void DataGridItemDataBound(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e) ...{ if(e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) ...{ e.Item.Attributes.Add("style", "vnd.ms-excel.numberformat:@"); //e.Item.Cells[3].Attributes.Add("style", "vnd.ms-excel.numberformat:¥#,###.00"); } } #endregion } }
调用方法
//
1. 导出一个不分页的 DataGrid 到 Excel.
ExcelHelper helper
=
new
ExcelHelper();
//
设置文件名(可省。省略则自动生成一个随机的文件名)
helper.FileName
=
"
xxx.xls
"
;helper.Export(dg);
//
2. 导出分页的 DataGrid,需要同时指定他的数据源(DataTable)
DataTable dt
=
;ExcelHelper helper
=
new
ExcelHelper(dt);
//
最大导出条数(可省)
helper.MaxRecords
=
2000
;helper.Export();
//
3. 如果要指定列标题,这样调用:
DataTable dt
=
;ExcelHelper helper
=
new
ExcelHelper(
new
string
[]
...
{"列标题1", "列标题2", }
, dt);helper.Export();
//
4. 如果还要指定字段名称, 这样调用(因为输出的字段名称不一定要和 DataTable 里字段名称的次序相同。
DataTable dt
=
;ExcelHelper helper
=
new
ExcelHelper(
new
string
[]
...
{"列标题1", "列标题2", }
,
new
string
[]
...
{"字段名1", "字段名2", }
, dt);helper.Export();
转载请注明原文地址: https://ibbs.8miu.com/read-24489.html