zoukankan      html  css  js  c++  java
  • ASP.NET 中 DataGrid 导出到 Excel 的封装实现 (转)

    ASP.NET 中 DataGrid 导出到 Excel 的封装实现

    文章类型:Asp.Net  作者:木野狐
    最近的项目中要大量用到 DataGrid 中的数据导出到 Excel 的方法,且数据量比较大。针对这个我做了一个导出 Excel 的帮助类。
    之前在网上我搜索到很多导出 Excel 的代码,但是都不尽如人意。一般有下列几种方法:

    1. 用 Excel.Application 对象逐单元格的填充数据。
    这个办法由于是操作 COM 组件来进行,而 .NET 调用 COM 是要经过一层 wrapper 的,必然导致效率不高。还有一个原因是, Excel 不是针对多线程而设计的, 在大的并发需求下,可能会出现问题。因此一般这个方法只推荐适用于 Intranet.

    2.  用 DataGrid 的 RenderControl 方法直接输出到一个 HtmlTextWriter 对象。 这个办法比较简单,因为是输出纯 html, 不涉及服务端 Excel 对象的初始化带来的开销。所以性能应该是比较好的。但是我看了现有的一些例子都是只能输出一页的, 也就是说不适用于分页的 DataGrid.

    3. 用 OWC, 同样,由于是 COM 组件,存在性能问题。

    针对这个情况我决定采用 2 作为最终输出的方法,在内存中构造不分页的 DataGrid, 然后 RenderControl 的方法。(要传入数据源作为参数)。
    因为我加了自定义列标题和字段列表的功能,所以目前的数据源只能是类似 DataTable 这样的,至于一些其他可以绑定到 DataGrid 的类型比如 IListSource, IEnumerable, 由于内部不带有字段名称,标题信息等内容,分析起来非常复杂。简单起见,我忽略了这些,而仅仅接收 DataTable 作为数据源。

    代码在这里:
    //=============================================================================== 
    // 
    // 从 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 RChen.Demos 
        
    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> 

            public void Export(DevExpress.Web.ASPxGrid.ASPxGrid xgrid) {  
                
    if (xgrid == null
                    
    throw new ArgumentNullException("xgrid"); 
                
    if (xgrid.PageCount > 1
                    
    throw new ArgumentException("paged xgird not can't be exported.""xgrid"); 
     
                
    // 添加标题样式 
                xgrid.HeaderStyle.Font.Bold = true
                xgrid.HeaderStyle.BackColor 
    = System.Drawing.Color.LightGray; 
     
                RenderExcel(xgrid); 
            }
     
     
            
    /**//// <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 
                    ASPxGrid xgrid 
    = c as ASPxGrid; 
     
                    
    if (xgrid != null
                        xgrid.RenderControl(writer); 
                    
    else 
                        
    throw new ArgumentException("only supports DataGrid or ASPxGrid.""c");     
                }
     
                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
     
        }
     
    }
     


    代码就是页面里这些了。不过忘记了写调用的例子,现在补上:
    以下例子实际调用时需要在外面用 try 块捕获并处理异常。可能抛出的异常有 ParameterException, ParameterNullException, Exception 等。
    // 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();
    原文:http://www.soft123.com/news/html/2005-03/2005327110552.htm
  • 相关阅读:
    (CS模式)大学计算机基础考试系统
    四叶草的祝福
    做人的小故事!
    前天晚上回到北京了
    人生活的三种状态
    松口气了!
    Mysql一些基础用法
    云计算随想
    对vector与deque插值与遍历的性能数据
    gdb命令的常用调试选项
  • 原文地址:https://www.cnblogs.com/dagon007/p/216559.html
Copyright © 2011-2022 走看看