2010年2月5日 星期五

找出指定年度的每個月天數之 T SQL


如何找出上個月的最後一天
declare @dt datetime

set @dt='2009/02/15'

--找出上個月最後一天

select convert(datetime,convert(char(7),@dt,111)+'/01')-1

--找出該月第一天

select convert(char(7),@dt,111)+'/01'


如何找出指定年度的每個月天數
declare @year varchar(4) --假設年度

declare @month int --計算月份之用

declare @dt1 datetime --計算該月第一天

declare @dt2 datetime --計算該月最後一天

set @year='2007'

set @month=1

while @month<=12

 begin

  select @dt1=convert(datetime,@year+'/'+convert(varchar(2),@month)+'/01') --找出該月第一天

  set @dt2=DateAdd(mm,1,@dt1)-1 --找出該月最後一天

  select @year '年份',@month '月份',datediff(dd,@dt1,@dt2)+1 '天數' --輸出結果

  set @month=@month+1

 end


2010年2月4日 星期四

實作ASP.NET MVC SendMail功能


今天研究在ASP.NET MVC於Action作完後,發mail到指定之User的方法,
在網路上Google一下,參考此篇文章:如何發送內嵌圖片的 E-mail ( Inline Attachment ) ,將其實作出來。

1.實作一個SendMail類別,程式碼如下:
using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Net.Mail;

using System.IO;



namespace IPRO.Ext

{

    public class SendMail

    {

        #region private fields

        private string _fromName;

        private string _fromAddress;

        private string _toName;

        private string _toAddress;

        private string _smtpServer;

        private int _smtpPort;

        private string _subject;

        private string _body;

        private string[] _filePath;

        private string _mailEncoding = "utf-8";

        #endregion



        #region construtor

        public SendMail(string fromName, string fromAddress, string toName,

                        string toAddress, string subject, string body,

                        string[] filePath, string smtpServer, int smtpPort)

        {

            this._fromName = fromName;

            this._fromAddress = fromAddress;

            this._toName = toName;

            this._toAddress = toAddress;

            this._subject = subject;

            this._body = body;

            this._filePath = filePath;

            this._smtpServer = smtpServer;

            this._smtpPort = smtpPort;

        }

        #endregion



        #region public method

        public void Send()

        {

            MailAddress from;

            MailAddress to;

            if (string.IsNullOrEmpty(_fromName))

            {

                from = new MailAddress(_fromAddress);

            }

            else

            {

                from = new MailAddress(_fromAddress, _fromName, Encoding.GetEncoding(_mailEncoding));

            }



            if (string.IsNullOrEmpty(_toName))

            {

                to = new MailAddress(_toAddress);

            }

            else

            {

                to = new MailAddress(_toAddress, _toName, Encoding.GetEncoding(_mailEncoding));

            }



            MailMessage message = new MailMessage(from, to);

            if(string.IsNullOrEmpty(_subject))

            {

                _subject = "郵件主旨";

            }

            message.Subject = _subject;

            message.SubjectEncoding = Encoding.GetEncoding(_mailEncoding);



            if(string.IsNullOrEmpty(_body))

            {

                _body = "郵件內容";

            }

            message.Body = _body;

            message.BodyEncoding = Encoding.GetEncoding(_mailEncoding);

            message.IsBodyHtml = true;

            message.Priority = MailPriority.High;



            //設定附件檔案(Attachment)

            if (_filePath.Length > 0)

            {

                for (int i = 0; i < _filePath.Length; i++)

                {

                    Attachment attachment = new Attachment(_filePath[i]);

                    attachment.Name = Path.GetFileName(_filePath[i]);

                    attachment.NameEncoding = Encoding.GetEncoding(_mailEncoding);

                    attachment.TransferEncoding = System.Net.Mime.TransferEncoding.Base64;

                    // 設定該附件為一個內嵌附件(Inline Attachment)

                    attachment.ContentDisposition.Inline = true;

                    attachment.ContentDisposition.DispositionType = System.Net.Mime.DispositionTypeNames.Inline;

                    message.Attachments.Add(attachment);

                }

            }



            if (_smtpPort == 0)

            {

                _smtpPort = 25;

            }



            if (string.IsNullOrEmpty(_smtpServer))

            {

                _smtpServer = "";

            }



            SmtpClient smtpClient = new SmtpClient(_smtpServer, _smtpPort);

            try

            {

                smtpClient.Send(message);

                System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + " 寄信成功!!!");

            }

            catch

            {

                System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + " 寄信失敗!!!");

            }

        }

        #endregion

    }

}


2.於Action中加入SendMail功能:
                SendMail mail = new SendMail("haha", "haha@gmail.com",
                                             "haha", "haha@yahoo.com.tw", "主旨",
                                             "內容", new string[] { },
                                             "smtp.gmail.com", 25);
                mail.Send();

ASP.NET MVC Ajax.ActionLink with Image

2010年1月31日 星期日

在ASP.NET中觀察LINQ to SQL所產生的T-SQL語法


接連在好幾個小專案裡用了LINQ to SQL,慢慢掌握要領,煎、煮、炒、炸查詢、新增、修改、刪除,各種料理操作都已能手到擒來,就愈發感受到它的便利性。

說穿了,LINQ to SQL只不過是ORM的一種具體實踐,並無深奧學問,之所以用來得心應手、讓人驚豔,不外乎是在與Visual Studio 2008整合深度上佔了優勢。以一個開發者的角度而言,我不在乎這對其他解決方案是否公允? 也不關心這類綁標圖利是否會有爭議? 給我方便的開發工具,其餘免談。

過去曾用ADO/ADO.NET開發過很長一段時間,在效能議題上下過一些功夫。切換到LINQ to SQL後,完全不沾SqlConnection、SqlCommand、SqlParameter就能搞定與資料庫相關的大小事,固然讓人心曠神怡;但過去對效能斤斤計較,換到LINQ,我還是常常懷疑LINQ所自動轉譯成的T-SQL到底長得什麼德性,會不會荒腔走板、效能低落?

要解除疑慮,最直接有效的方法就是檢查LINQ to SQL所產出的T-SQL語法,沒有什麼比眼見為憑更具說服力了! System.Data.Linq.DataContext類別有個屬性叫Log,我們可以接上一個TextWriter,DataContext會在執行T-SQL指令時,輸出實際使用的T-SQL語法、參數細節,提供極佳的觀察與偵錯資訊。

不過,如MSDN文件所示,能找到的Log應用範例幾乎都是接上Console.Out適用於Console Application,如果我們是在網頁中執行,想要如同System.Diagnositcs.Debug.WriteLine一般輸出在 VS2008的偵錯輸出視窗,該怎麼做呢?

我找到了Kris Vadermotten寫的DebuggerWriter類別,可以滿足以上的需求:

using System;

using System.Diagnostics;

using System.Globalization;

using System.IO;

using System.Text;



    /// <summary>

    /// Original by Kris Vadermotten: http://www.u2u.info/Blogs/Kris/Lists/Posts/Post.aspx?ID=11 <br />

    /// Remixed by Jeffrey Lee, 2009-07-11 http://blog.darkthread.net<br />

    /// Implements a <see cref="TextWriter"/> for writing information to the debugger log. 

    /// </summary>

    /// <seealso cref="Debugger.Log"/>

    public class DebuggerWriter : TextWriter

    {

        private bool isOpen;

        private static UnicodeEncoding encoding =

            new UnicodeEncoding(false, false);

        public int Level { get; private set; }

        public string Category { get; private set; }



        /// <summary>

        /// Initializes a new instance of the <see cref="DebuggerWriter"/> class.

        /// </summary>

        public DebuggerWriter()



            : this(0, Debugger.DefaultCategory) { }



        /// <summary>

        /// Initializes a new instance of the <see cref="DebuggerWriter"/> class with the specified level and category.

        /// </summary>

        /// <param name="level">A description of the importance of the messages.</param>

        /// <param name="category">The category of the messages.</param>

        public DebuggerWriter(int level, string category)



            : this(level, category, CultureInfo.CurrentCulture) { }



        /// <summary>

        /// Initializes a new instance of the <see cref="DebuggerWriter"/> class with the specified level, category and format provider.

        /// </summary>

        /// <param name="level">A description of the importance of the messages.</param>

        /// <param name="category">The category of the messages.</param>

        /// <param name="formatProvider">An <see cref="IFormatProvider"/> object that controls formatting.</param>

        public DebuggerWriter(int level, string category, IFormatProvider formatProvider)

            : base(formatProvider)

        {

            Level = level;

            Category = category;

            this.isOpen = true;

        }



        protected override void Dispose(bool disposing)

        {

            isOpen = false;

            base.Dispose(disposing);

        }



        public override void Write(char value)



        {

            if (!isOpen)

                throw new ObjectDisposedException(null);

            Debugger.Log(Level, Category, value.ToString());

        }



        public override void Write(string value)



        {

            if (!isOpen)

                throw new ObjectDisposedException(null);

            if (value != null)

                Debugger.Log(Level, Category, value);

        }

        

        public override void Write(char[] buffer, int index, int count)



        {

            if (!isOpen)

                throw new ObjectDisposedException(null);

            if (buffer == null || index < 0 || count < 0 || buffer.Length - index < count)

                base.Write(buffer, index, count); // delegate throw exception to base class

            Debugger.Log(Level, Category, new string(buffer, index, count));

        }



        public override Encoding Encoding



        {

            get { return encoding; }

        }

    }


將以上的DebuggerWriter.cs放入App_Code,然後youDataContext.Log = new DebuggerWriter(),設定Breakpoint,再一列一列Debug,你就可以觀察到何時LINQ to SQL會執行什麼樣的T-SQL指令,甚至包含參數值等細節,很犀利吧?


以上的範例,其實會觸發兩次SQL查詢,若要再精簡,可以改寫成:

var q = (from o in db.Players
where o.ID < 20
select o).ToList();

大家實際動手玩玩便知。

【2009-07-12補充】艾小克提供可以整合在VS2008裡,在開發階段檢視查詢所對應T-SQL並可直接試連DB做查詢的工具一枚,十分實用,一併列出供大家參考。

【2009-07-13補充】本草綱目有記載,若要查Query對應的CommandText,可以用DataContext.GetCommand,Insert/Update/Delete的部分則還沒看到Log法的替代方案,如有線報,歡迎提供。

轉自:http://blog.darkthread.net/blogs/darkthreadtw/archive/2009/07/12/linq-to-sql-debugger.aspx

2010年1月28日 星期四

MEMO-使用LINQ to SQL直接執行SQL指令

使用LINQ to SQL時,難免會遇到基於簡潔效率考量需要直接下SQL指令的場合。依我的習慣,遇到這類情境我就不用LINQ寫法硬幹了。DataContext物件提供了ExecuteCommand及ExecuteQuery兩個方法,可以直接撰寫有效率的SQL語法,交給DB執行批次更新動作或取回複合式查詢的結果。

但切記!! 直接操控SQL語法並不代表用直接組裝SQL指令字串,這樣很容易產生SQL Injection漏洞。基於這條開發基本常識,ExecuteCommand當然也鼔勵大家用Parameter處理動態參數,Method的第一個參數是 CommandText,後續可再逐一傳入參數值。這裡CommandText的參數宣告寫法與傳統"@paramName"的格式不同,要透過{0}, {1}方式指定。實際執行時,冰雪聰明的DataContext會將{0}, {1}轉成@p0, @p1,並依傳入參數值物件的型別決定Parameter型別。

我寫了個簡單的程式,分別傳入字串、整數及日期做示範:

public static void Test3()
{

    using (MyLabDataClassesDataContext db = 

        new MyLabDataClassesDataContext())

    {

        db.Log = Console.Out;

        db.ExecuteCommand(@"

UPDATE HumanResources.Employee 

SET Title = {0}

WHERE EmployeeID = {1}

AND BirthDate = {2}",

             "Jedi Master",

             1,

             new DateTime(1972, 5, 15)

        );

        Console.Read();

    }

}


利用Log轉向,可以觀察實際被轉換成的SqlCommand資訊如下:

UPDATE HumanResources.Employee
SET Title = @p0
WHERE EmployeeID = @p1
AND BirthDate = @p2
-- @p0: Input NVarChar (Size = 11; Prec = 0; Scale = 0) [Jedi Master]
-- @p1: Input Int (Size = 0; Prec = 0; Scale = 0) [1]
-- @p2: Input DateTime (Size = 0; Prec = 0; Scale = 0) [1972/05/15 上午 12:00:00
]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.1

很簡便吧!

查詢時的處理方法也差不多,但ExecuteQuyer必須指定查詢結果要對應的物件型別,如果查詢結果來自JOIN或有另外組合欄位的話,就沒有現成的物件型別可用,要自行定義物件來承接查詢結果。如以下範例:
class ResultClass

{

    public int EmployeeId { get; set; }

    public string Title { get; set; }

}

public static void Test4() 

{

    using (MyLabDataClassesDataContext db =

        new MyLabDataClassesDataContext())

    {

        db.Log = Console.Out;

        var q = db.ExecuteQuery<ResultClass>(@"

SELECT EmployeeID,Title 

FROM HumanResources.Employee 

WHERE Title LIKE '%' + {0} + '%'",

                             "Manager");

        foreach (ResultClass x in q)

        {

            Console.WriteLine("{0}-{1}",

                x.EmployeeId,

                x.Title

                );

        }

        Console.Read();

    }

}


執行結果如下:

SELECT EmployeeID,Title
FROM HumanResources.Employee
WHERE Title LIKE '%' + @p0 + '%'
-- @p0: Input NVarChar (Size = 7; Prec = 0; Scale = 0) [Manager]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.1

3-Engineering Manager
6-Marketing Manager
21-Production Control Manager
30-Human Resources Manager
42-Information Services Manager
71-Finance Manager
90-Document Control Manager
139-Accounts Manager
150-Network Manager
158-Research and Development Manager
200-Quality Assurance Manager
217-Research and Development Manager
218-Facilities Manager
268-North American Sales Manager
274-Purchasing Manager
284-European Sales Manager
288-Pacific Sales Manager


轉自:http://blog.darkthread.net/blogs/darkthreadtw/archive/2009/11/13/dbcontext-executecommand.aspx

2010年1月23日 星期六

JQuery jqGrid Export to Excel Using ASP.NET MVC Framework


Abstract:
In this article we are going to demonstrate jqGrid, JQuery Grid plugin which is used to display tabular data on the form. The article will also discuss how to export the Grid to the Excel format.
Why JQuery Grid Plugin?

You can always use the plain vanilla HTML code to create your tables but JQuery Grid gives you the ability perform sorting, paging, searching and many other operations which are very cumbersome to write.

Setting Up the Project:

We are using ASP.NET MVC 1.0 for our demo. First, you can download the JQuery library and the JGrid library from the following URLs:

1) JQuery
2) JGrid

The JGrid documentation explains how and where to put all the .js files. If you find it hard to follow then just download the source code at the end of this article and set up your project similar to the download sample.

Populating Grid with Data:

Before we start retrieving products from the database we should make a reference to all the required scripts in our page. Since, we are using master pages we will include all the script and CSS references in the master page as shown below:
 <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />

    <link href="../../Content/ui.jqgrid.css" rel="stylesheet" type="text/css" />

    <script src="../Scripts/jquery-1.3.2.js" type="text/javascript"></script>

    <script src="../Scripts/jquery.jqGrid.js" type="text/javascript"></script>



    <script src="../../Scripts/Site.js" type="text/javascript"></script>


After creating all the references our next task is to populate the Grid with data. We will be using the Northwind database "Products" table. Here is our simple repository which returns all the products from the Products table as a List.
 public class ProductRepository : IProductRepository

    {

        public List<Product> GetAll()

        {

            using(var db = new NorthwindDataContext())

            {

                return (from p in db.Products

                       select p).ToList();

            }

        }

    }

The loadProducts JavaScript function is responsible for populating the View with the data.
<script language="javascript" type="text/javascript">



    // load the products

    loadProducts();



</script> 





<% using (Html.BeginForm(new { Action = "ExportToExcel" }))

 {%>

 

<table id="list"></table>



<input type="submit" value="Export to Excel" />



<%

      

 }%>

Let's take a look at the loadProducts method.
function loadProducts()

{

    jQuery(document).ready(function() {

        jQuery("#list").jqGrid({

            url: '/Home/GetProducts/',

            datatype: 'json',

            mtype: 'GET',

            colNames: ['Id', 'Name', 'QuantityPerUnit',"UnitPrice"],

            colModel: [

          { name: 'Id', index: 'Id', width: 40, align: 'left' },

          { name: 'Name', index: 'Name', width: 40, align: 'left' },

          { name: 'QuantityPerUnit', index: 'QuantityPerUnit', width: 200, align: 'left' },

          { name: 'UnitPrice', index: 'UnitPrice', width: 200, align: 'left' }],

            rowNum: 10,

            rowList: [5, 10, 20, 50],

            sortname: 'Id',

            sortorder: "desc",

            viewrecords: true,

            caption: 'My first grid'

        });

    });

}

The above code assigns different values to the jqGrid. The url attribute represents the controller action that will be fired. The colNames represent the header text of the table that will be displayed. The colModel refers to the individual grid columns as an array of properties.

Now, let's see what the controller looks like:
public ActionResult GetProducts(string sidx, string sord, int page, int rows)

        {

  var products = _productRepository.GetAll();



            var totalPages = 1; // we'll implement later

            var totalRecords = 3; // implement later



            var jsonData = new

                               {

                                   total = totalPages,

                                   page = page,

                                   records = totalRecords,

                                   rows = (from p in products

                                           select new

                                                      {

                                                          id = p.ProductID,

                                                          cell = new string[]

                                                                     {

                                                                         p.ProductID.ToString(), p.ProductName,

                                                                         p.ProductName

                                                                     }

                                                      }).ToArray()

                               };



            return Json(jsonData);

}

The _productRepository.GetAll() method is responsible for fetching all the products from the Products table. Finally, we created an Anonymous type jsonData which contains the properties required by the jqGrid. The rows collection contains an object with id property and cells collection.

When you run the above example you will see the following output:

The above image shows that Grid is rendered on the page successfully. There are few columns which are not displayed because they were not included in the jqGrid column collection.

The code in the GetProducts action of the HomeController is very nasty. We should move this code to a different place where it can be reused.

Creating ToJsonForjqGrid Extension Method:

The purpose of ToJsonForjqGrid extension method is to convert a List collection into a format supported by the jqGrid.
 public static object ToJsonForjqGrid<T>(this List<T> list,string primaryKey,string[] columnNames) where T : new()

        {

            if(list.Count() == 0)

                throw new ArgumentException("List does not contain any items!");



            var jsonData = new

                               {

                                 

                                   rows = (from p in list

                                          select new

                                        {

                                            id = p.GetPropertyValue(primaryKey),

                                            cell = p.GetPropertyValues(columnNames)       

                                        }).ToArray()                              



                               };



            return jsonData; 

        }

ToJsonForJqGrid takes two arguments. The first argument is the primary key of the object which will be assigned to the id property of the row. The second argument is the columnNames[] which contains the name of the columns to be included in the jqGrid.

And here is the GetProducts action using the ToJsonForJqGrid method.
 public ActionResult GetProducts(string sidx, string sord, int page, int rows)

        {



            var jsonData = _productRepository.GetAll().ToJsonForjqGrid("ProductID", new[] { "ProductID", "ProductName" });

            return Json(jsonData);



        }

And the result is shown below:

If we need to include a couple of more columns we can add the names in the string[] collection for the columnNames parameter to the ToJsonForjqGrid method.
public ActionResult GetProducts(string sidx, string sord, int page, int rows)

        {



            var jsonData = _productRepository.GetAll().ToJsonForjqGrid("ProductID", new[] { "ProductID", "ProductName", "QuantityPerUnit","UnitPrice" });

            return Json(jsonData);



        }

A little better!

And here is the result:

Exporting Grid to Excel:

When the export to excel button is clicked the form is submitted and "ExportToExcel" action is fired.
public ActionResult ExportToExcel()

        {

            var products = _productRepository.GetAll();



            var grid = new GridView();

            grid.DataSource = from p in products

                              select new

                                         {

                                             ProductName = p.ProductName,

                                             SomeProductId = p.ProductID

                                         };

            grid.DataBind();



            Response.ClearContent();

            Response.AddHeader("content-disposition", "attachment; filename=MyExcelFile.xls");



            Response.ContentType = "application/excel";



            StringWriter sw = new StringWriter();



            HtmlTextWriter htw = new HtmlTextWriter(sw);



            grid.RenderControl(htw);



            Response.Write(sw.ToString());



            Response.End();



            return View("Index");

        }

NOTE: You should not put the export to excel code right into the controller action. Create a ExportToExcel service and use that to perform the exportation task.

Inside the ExportToExcel action we simply retrieve the products from the database and creates an anonymous type collection and assign to the GridView control. Later the GridView control is rendered to the HtmlTextWriter and send as an attachement with the response.

Conclusion:

In this article we learned how to use jqGrid to display data from the database. We also learned how to export the grid to excel.

References:

1) Using JQuery Grid with ASP.NET MVC

[Download Sample]

中文問題可參考此篇文章:http://ccdccs0240.blogspot.com/2010/01/asp.html

轉自:http://www.highoncoding.com/Articles/566_JQuery_jqGrid_Export_to_Excel_Using_ASP_NET_MVC_Framework.aspx

[ASP.NET]將GridView內的資料匯出成Excel檔

有網友發問,要如何將 GridView 的 HTML內容的資料匯出成 Excel 檔,這部份的功能可以透過Control.RenderControl的方式
Control.RenderControl : 輸出伺服器控制項內容,並在啟用追蹤功能的情況下,儲存控制項的追蹤資訊。
http://msdn.microsoft.com/zh-tw/library/system.web.ui.control.rendercontrol(VS.80).aspx

將 GridView 內的資料匯出成 Excel 檔的程式碼
    protected void Button2_Click(object sender, EventArgs e) 

    { 

        Response.ClearContent(); 

        string excelFileName = "測試Excel檔案.xls"; 

        Response.AddHeader("content-disposition", "attachment;filename=" + Server.UrlEncode(excelFileName)); 

        Response.ContentType = "application/excel"; 

        System.IO.StringWriter stringWrite = new System.IO.StringWriter(); 

        System.Web.UI.HtmlTextWriter htmlWrite = new HtmlTextWriter(stringWrite); 

        GridView1.RenderControl(htmlWrite); 

        Response.Write(stringWrite.ToString()); 

        Response.End(); 

    } 

在這邊會遇到兩個問題


問題1. 產生 型別 'GridView' 的控制項 'GridView1' 必須置於有 runat=server 的表單標記之中 的問題


這個問題我在 topcat 大大的Bog得到解決方式,加上此段程式碼即可

public override void VerifyRenderingInServerForm(Control control)

{

// '處理'GridView' 的控制項 'GridView' 必須置於有 runat=server 的表單標記之中

}


關於此錯誤以及遇到網頁中有分頁時的處理方式,可以參考 topcat 大大的Blog

http://www.dotblogs.com.tw/topcat/archive/2008/03/14/1336.aspx

http://msdn.microsoft.com/zh-tw/library/system.web.ui.page.verifyrenderinginserverform.aspx


問題2. 當 GridView 中有中文字時,使用上述的程式碼所匯出的Excel會有中文亂碼,如下圖所示




解決此問題的方式參考 MSDN 論壇上 LOLOTA 大大的方法,加上這段程式碼解決轉碼問題即可

http://social.msdn.microsoft.com/forums/zh-TW/236/thread/fc860a06-bb14-40fd-bced-9d86af5d9653/

Response.Write("<meta http-equiv=Content-Type content=text/html;charset=utf-8>");


完整的程式碼如下 :
using System; 

using System.Data; 

using System.Configuration; 

using System.Collections; 

using System.Web; 

using System.Web.Security; 

using System.Web.UI; 

using System.Web.UI.WebControls; 

using System.Web.UI.WebControls.WebParts; 

using System.Web.UI.HtmlControls; 

 

public partial class _Default : System.Web.UI.Page  

{ 

    protected void Button2_Click(object sender, EventArgs e) 

    { 

        Response.ClearContent(); 


        Response.Write("<meta http-equiv=Content-Type content=text/html;charset=utf-8>"); 

        string excelFileName = "測試Excel檔案.xls"; 

        Response.AddHeader("content-disposition", "attachment;filename=" + Server.UrlEncode(excelFileName)); 

        Response.ContentType = "application/excel"; 

        System.IO.StringWriter stringWrite = new System.IO.StringWriter(); 

        System.Web.UI.HtmlTextWriter htmlWrite = new HtmlTextWriter(stringWrite); 

        GridView1.RenderControl(htmlWrite); 

        Response.Write(stringWrite.ToString()); 

        Response.End(); 

    } 

 

    public override void VerifyRenderingInServerForm(Control control)    

    { 

        // '處理'GridView' 的控制項 'GridView' 必須置於有 runat=server 的表單標記之中   

    }    

}

執行結果


範例下載

DataGridToExcel.rar

轉自:http://www.dotblogs.com.tw/chou/archive/2009/04/03/7831.aspx