NPOI讓ASP.NET網頁簡單輸出Native的Excel

NPOI官網: http://npoi.codeplex.com/

下載最新的「NPOI」 x.x.x binary and examples,裏面包含了許多範例程式。簡單的複製範例程式片段,往自已的程式貼上就可以跑了當然要使用NPOI函式庫囉。

會使用NPOI最主要原因,是因為ASP.NET GridView 輸出的Excel基本上是Html的Table。要拿來給某此資料匯入工具吃,可能無法使吃下去。

GridView的DataFormatString參考

GridView的DataFormatString參考

GridView 在DataFormatString屬性 中的 {0} 表示資料本身,而在冒號後面的格式字符串代表所們希望資料顯示的格式; 例如 {0:d} ==> 2009/3/11

GridView DataFormatString屬性 數字、貨幣格式
在指定的格式符號後可以指定小數所要顯示的位數。例如原來的數據為「1.56」,若格式設定為 {0:N1},則輸出為「1.5」。其常用的數值格式如下表所示:

格式字串輸入結果
“{0:C}" 12345.6789 ==> $12,345.68
“{0:C}" -12345.6789 ==>($12,345.68)
“{0:D}" 12345 ==>12345
“{0:D8}" 12345 ==>00012345
“{0:E}" 12345.6789 ==>1234568E+004
“{0:E10}" 12345.6789 ==>1.2345678900E+004
“{0:F}" 12345.6789 ==>12345.68
“{0:F0}" 12345.6789==> 12346
“{0:G}" 12345.6789==> 12345.6789
“{0:G7}" 123456789 ==>1.234568E8
“{0:N}" 12345.6789 ==>12,345.68
“{0:N4}" 123456789 ==>123,456,789.0000
“Total: {0:C}" 12345.6789 ==>Total: $12345.68

GridView DataFormatString屬性 常用的日期時間格式:

格式 說明 輸出格式
d 精簡日期格式 MM/dd/yyyy
D 詳細日期格式 dddd, MMMM dd, yyyy
f 完整格式 (long date + short time) dddd, MMMM dd, yyyy HH:mm
F 完整日期時間格式 (long date + long time) dddd, MMMM dd, yyyy HH:mm:ss
g 一般格式 (short date + short time) MM/dd/yyyy HH:mm
G 一般格式 (short date + long time) MM/dd/yyyy HH:mm:ss
s 適中日期時間格式 yyyy-MM-dd HH:mm:ss
t 精簡時間格式 HH:mm
T 詳細時間格式 HH:mm:ss

所以不一定要記,只要跟程式一樣 yyyy ==> 年 ,MM==>月,dd==>日,HH==>時,mm==>分,ss==>秒

用 jQuery 將 GridView 改成固定欄位名稱的樣式

先講述一下設定值 GridView’s table-layout:fixed width:900px ,固定 GridView 寬度。其中每個欄位的寬度也都有指定寬度。

//檢查目標元素是否有scrollbar的函式
(function ($) {
    $.fn.hasScrollBar = function () {
        return this.get(0).scrollHeight > this.height();
    }
})(jQuery);
var edit_row_top=0;//編輯列的高度位置標記
$(document).ready(function () {
    //寫出一串標籤物件這是為了給thead插入用的並將它加到body下
    $("<div id='float_table_wrapper'><table id='float_table' rules='all' style='table-layout:fixed;width:900px;border:1px solid gray;padding:0px;border-spacing:0px;margin-bottom:5px;'><thead></thead></table></div>").appendTo("body");
    //複製欄位名稱資料列,並將它附加到剛新增的網頁元素中
    $("table#GridView1 tr:first").clone().appendTo("#float_table thead");
    //將固定的欄位名稱資料列table插到,原來gridview父元素之前
    $("#float_table_wrapper").insertBefore($("#GridView1").parent());
    //移除gridview第一列資料(欄位名稱資料列)
    $("table#GridView1 tr:first").remove(); //.css({ display: "none" });
    //指定Gridview的高度,並設定overflow:auto
    $("#GridView1").parent().css({ height: "350px", overflow: "auto" });
    //如果gridview有scrollbar出現,gridview的寬度+15
    if ($("#GridView1").parent().hasScrollBar()) {
        $("#GridView1").parent().css({ "width": "915px" });
    }

    //處於編輯狀態,將編輯資料列置頂
    $("table#GridView1 tr").each(function () {
        if ($(this).find("input").length > 0) {
            normal_row_height = $(this).prev("tr").height();
            edit_row_top = $(this).index() * normal_row_height;
        }
    });
    $("#GridView1").parent().animate({ scrollTop: edit_row_top }, 10);
});

固定名稱欄位的成果

Postback後,自動滾動到編輯中的資料列

Asp.net GridView 使用 jQuery-plugin tablescroll 固定欄位名稱

Gridview 呈現的資料列太多可以用分頁來顯示,但如何固定標頭的方式來顯示呢?可能大家都有自已的一套方法吧。而使用 jquery-plugin:tablescroll 也許是個簡單又快速的方法。它可以很快的就將你GridView所生出來的tableb分出table-head(固定的欄位名稱)和table-body(可以捲動的資料列)。但首先必需要將gridview寫出前端網頁時能分出「thead」和「tbody」,如此tablescroll才能發揮它的作用固定欄位名稱。

如何讓Gridview產出thead標籤,可以在GirdView_PreRender的事件中設定。
範例如下:

Protected Sub GridView1_PreRender(sender As Object, e As System.EvenArgs) Handles GridView1.PreRender
    GridView1.UseAccessibleHeader = True
    GridView1.HeadRow.TableSection = TableRowSection.TableHeader
End Sub

至於tableScroll的部份設定超簡單的,就像下面這樣:

$(function(){
    $("#GridView1").tableScroll({height:300});
});

完成以上的步驟,應該是可以讓 GridView 固定欄位名稱標頭列了。除非是Gridview加了太多的樣式在裏面,不然tableScroll處理過後看起來都還算正常。

Asp.net 的 GridView 使用 table-layout:fixed 樣式 固定寬度

設置表格樣式style="table-layout:fixed;width:800px;",也就是GridView的樣式。

HeaderStyle:控制欄位的樣式,Gridview表頭的樣式。
ControlStyle:控制儲存內容控件的樣式,例如input標籤。
ItemStyle:通用樣式,這個就不常用到了。

範例說明(aspx)

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" 
                CellPadding="4" DataKeyNames="MV001" DataSourceID="SqlDataSource1" 
                BackColor="White" BorderColor="#CC9966" BorderStyle="None" BorderWidth="1px" Width="100%" style="table-layout:fixed;" >
                <Columns>
                    <asp:CommandField ShowEditButton="True" CancelText="☆" EditText="△" 
                        UpdateText="★" >
                    </asp:CommandField>
                    <asp:BoundField DataField="MV001" HeaderText="工號" ReadOnly="True" SortExpression="MV001">
                    <HeaderStyle Width="50px" />
                    <ItemStyle  width="50px" />
                    </asp:BoundField>
                    <asp:BoundField DataField="NAME" HeaderText="姓名" SortExpression="NAME">
                    <HeaderStyle Width="60px" />
                    <ItemStyle  width="60px" />
                    <ControlStyle Width="60px" />
                    </asp:BoundField>
                    <asp:BoundField DataField="MV004" HeaderText="ISO" SortExpression="MV004" >
                    <HeaderStyle Width="30px" />
                    <ItemStyle  width="30px" />
                    <ControlStyle Width="30px" />
                    </asp:BoundField>
<!-- 
######################################################################
######################################################################
######################################################################
-->
                </Columns>
                <EditRowStyle BackColor="#FFFF66" />
                <FooterStyle BackColor="#FFFFCC" ForeColor="#330099" />
                <HeaderStyle BackColor="#990000" Font-Bold="True" ForeColor="#FFFFCC" 
                    Width="50px" HorizontalAlign="Center" Wrap="True" />
                <PagerStyle BackColor="#FFFFCC" ForeColor="#330099" HorizontalAlign="Center" />
                <RowStyle BackColor="White" ForeColor="#330099" HorizontalAlign="Center" 
                    Wrap="True" />
                <SelectedRowStyle Font-Bold="True" ForeColor="#663399" />
                <SortedAscendingCellStyle BackColor="#FEFCEB" />
                <SortedAscendingHeaderStyle BackColor="#AF0101" />
                <SortedDescendingCellStyle BackColor="#F6F0C0" />
                <SortedDescendingHeaderStyle BackColor="#7E0000" />
            </asp:GridView>

參考來源:DataGrid屬性

Asp.NET 為何 GridView 手動更新資料列起不了任何作用

手動更新 GridView 的資料列,為何就是無法更新剛剛輸入上去的值呢?

簡單的說,就是「DataBinding的時間、時機,對不對?恰不恰當?」。

在更新資料列時會 PostBack > Pageload > 之後才會執行 GridView updating

重點在於有時我們會在Pageload的時機,就給它做一次GridView的databind。而我們剛剛輸入的新資料就這樣的被重置了,因此我們會認為 GridView updating 起不了任何作用。

通常只要IsPostBack加以利用,讓 GridView.databind 僅於第一次載入頁面時執行就能避免此一類的狀況發生。

資料來源:[FAQ]自己動手寫 GridView的編輯/更新程式,但抓不到修改後的資料?(兼論DataBinding的時機)

如何使用 GridView 的分頁功能

ASP.NET 2.0 的 GridView 控制項具有內建的分頁功能,只要透過 DataSourceID 屬性,指定支援直接分頁功能的資料來源控制項(如 SqlDataSource),並將 AllowPaging 屬性設定為 true,即可啟用分頁功能,而不需撰寫任何程式碼。

當使用 DataSourceID 屬性指定資料來源時,則資料控制項(Data-bound Control)就會在執行階段 (Run-Time)自動繫結資料來源控制項。相較於使用 DataSource 屬性,最大的不同就是你就必須明確呼叫 DataBind 方法來繫結資料來源。

所以,如果你是透過 GridView 控制項的 DataSource 屬性繫結資料來源,則當你移動 GridView 控制項的分頁時,便會引發如下的錯誤: 由 GridView ‘GridView1′ 引發但尚未處理的事件 PageIndexChanging。

這時你必須建立 GridView 控制項的 PageIndexChanging 事件處理常式,為 GridView 控制項指定使用者所選取之頁面的索引,並呼叫 DataBind 方法:

protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e) {
    GridView1.PageIndex = e.NewPageIndex;
    GridView1.DataBind(); }

資料來源:如何使用 GridView 的分頁功能