Monday, February 1, 2010

Export gridview data to excel and word


Every software has a common requirement to export data to Microsoft Excel or Word format. I saw multiple on this topic in asp.net forum.  Here I will explain a simple way of exporting your gridview data to excel (.xls) or word (.doc) format when used with master page and updatepanel.  
Firstly we will write html codes:



<table style="width: 100%;">
                                    <tr>
                                        <td>
                                            <asp:Label ID="Label3" runat="server" Text="Export to: "></asp:Label>
                                            <asp:LinkButton ID="lnkExportToExcel" runat="server"
                                                OnClick="lnkExportToExcel_Click">Excel</asp:LinkButton>
                                            &nbsp;<asp:LinkButton ID="lnkExportToWord" runat="server"
                                                onclick="lnkExportToWord_Click">Word</asp:LinkButton>
                                            &nbsp;<asp:DropDownList ID="ddlExportOption" runat="server">
                                                <asp:ListItem Value="0">This Page</asp:ListItem>
                                                <asp:ListItem Value="1">All Page</asp:ListItem>
                                            </asp:DropDownList>
                                            &nbsp;</td>
                                    </tr>
                                </table>
Code behind:
Now we will write lnkExportToExcel and lnkExportToWord click event handler code:
protected void lnkExportToExcel_Click(object sender, EventArgs e)
        {
            if (ddlExportOption.SelectedIndex == 0)
            {
                Helper.Export("excel", gvHrEmploye, this.Page);
            }
            else
            {
                int pageNo = gvHrEmploye.PageIndex;
                gvHrEmploye.AllowPaging = false;
                BindList();
                Helper.Export("excel", gvHrEmploye, this.Page);
                gvHrEmploye.AllowPaging = true;
                gvHrEmploye.PageIndex = pageNo;
                BindList();
            }
        }

protected void lnkExportToWord_Click(object sender, EventArgs e)
        {
            if (ddlExportOption.SelectedIndex == 0)
            {
                Helper.Export("word", gvHrEmploye, this.Page);
            }
            else
            {
                int pageNo = gvHrEmploye.PageIndex;
                gvHrEmploye.AllowPaging = false;
                BindList();
                Helper.Export("word", gvHrEmploye, this.Page);
                gvHrEmploye.AllowPaging = true;
                gvHrEmploye.PageIndex = pageNo;
                BindList();
            }
        }


Here notice that we are currently displaying data or all data based on users choice.


Then we will look at export method which actually does the job:
public static void Export(string type, GridView gv, Page page)
    {
        if (type == "excel")
        {
            page.Response.AddHeader("content-disposition", "attachment;filename=EmployeeList.xls");
            page.Response.ContentType = "application/vnd.xls";
        }
        else if (type == "word")
        {
            page.Response.AddHeader("content-disposition", "attachment;filename=EmployeeList.doc");
            page.Response.ContentType = "application/msword";
        }
        page.Response.Charset = String.Empty;
        System.IO.StringWriter sw = new System.IO.StringWriter();
        System.Web.UI.HtmlTextWriter hw = new HtmlTextWriter(sw);
        gv.RenderControl(hw);
        page.Response.Write(sw.ToString());
        page.Response.End();
    }
You can use this code to export gridview data to excel and word format. This method works fine when working with pages that does not have update panel and have no master page. But when used with master page and update panel it gives an error while executing RenderControl()method.
Error:
"Control of type GridView must be placed inside form tag with runat = server"
To solve this error you have to override VerifyRenderingInServerForm method:
public override void VerifyRenderingInServerForm(Control control)
        {
            return;
        }
This method confirms that HtmlForm control is rendered for specified ASP.Net server control at runtime.
If you run this time you will get another error:
RegisterForEventValidation can only be called during Render()


To solve this problem add EnableEventValidation = "false" page tag of .aspx page.
<%@ Page Language="C#" MasterPageFile="~/Master/MasterPage.master" AutoEventWireup="true"
    MaintainScrollPositionOnPostback="true" CodeFile="HrEmployeeForm.aspx.cs" Inherits="ERP.Web.UI.HrEmployeeForm"
    EnableEventValidation="false" %>


This time your code should work properly. Have a nice feature working properly in your asp.net application. Thanks.

Monday, January 25, 2010

Master Detail representation using Nested Gridview




Introduction
A recurring task in software development is representing tabular data in master detail format. ASP.Net provides a number of tools for performing this task.  Here I will show how to use nested grid view to show detail data related to master table on asp.net web page.
Technique
Take a grid view that display data from master table. Create last column of this grid as TemplateField. Inside this TemplateField, take another girdview to display data from detail table. Bind detail grid view in OnRowDataBound event of master grid view with related data of respective row.
Defining Task
We will bind departments of a company in a CheckedList box. We want to display employee information of selected departments to gridview. Master grid will bind department names and Detail grid will display employee information of respective department.
Expected Output:



Writing HTML code:
HTML codes should look like following:
<table border="0" cellpadding="0" cellspacing="0" width="100%">
                <tr>
                    <td align="center" colspan="3">
                        <asp:Label ID="lblTableHeader" runat="server" CssClass= "TableHeader" >asp:Label>
                    td>
                tr>
<tr>
                    <td align="right">
                        <asp:Label ID="lblDept" runat="server" Text="Select Department:" Font-Bold="True">asp:Label>
                    td>
                    <td align="left">
                        <asp:CheckBoxList ID="lstDepartmentName" runat="server" Height="100px" RepeatColumns="4">
                            <asp:ListItem>DepartmentNameasp:ListItem>
                        asp:CheckBoxList>
                    td>
                    <td>
                         
                    td>
                tr>
<tr>
                    <td align="right">
                        <asp:Label ID="lblEmptype" runat="server" Font-Bold="True" Text="Select Employee Type:">asp:Label>
                    td>
                    <td>
                         
                        <asp:DropDownList ID="ddlEmpType" runat="server">
                        asp:DropDownList>
                    td>
                    <td>
                         td>
                tr>
<tr>
                    <td align="right">
                        <asp:Button ID="btnPreview" runat="server" CssClass="Button" OnClick="btnPreview_Click"
                            Text="Preview" Width="105px" />
                    td>
                    <td>
                         
                    td>
                    <td>
                         td>
                tr>
<tr>
                    <td align="center" colspan="3">
                        <asp:GridView ID="gvDeptNameList" runat="server" AutoGenerateColumns="False" BackColor="White"
                            BorderColor="#CCCCCC" BorderStyle="Solid" BorderWidth="1px" CellPadding="3" EmptyDataText="No rows returned"
                            OnRowDataBound="gvDeptNameList_RowDataBound" Width="100%">
                            <RowStyle ForeColor="#000066" />
                            <Columns>
                                <asp:BoundField DataField="DepartmentName" HeaderText="Department" SortExpression="DepartmentName">
                                    <ItemStyle VerticalAlign="Top" />
                                asp:BoundField>
                                <asp:TemplateField HeaderText="Employee Inforamtion">
                                    <ItemTemplate>
                                        <asp:GridView ID="gvEmpLstByDeptAndEmpType" runat="server" AutoGenerateColumns="False" BackColor="White" BorderColor="#CCCCCC" BorderStyle="Solid" BorderWidth="1px" CellPadding="3" EmptyDataText="No Employees"
Width="100%">
                                            <RowStyle ForeColor="#000066" />
                                            <Columns>
                                                <asp:BoundField DataField="StaffCode" HeaderText="Staff Code" SortExpression="StaffCode">
                                                    <ItemStyle Width="100px" />
                                                asp:BoundField>
                                                <asp:BoundField DataField="LastName" HeaderText="Employee Name" SortExpression="Name">
                                                    <ItemStyle Width="200px" />
                                                asp:BoundField>
                                                <asp:BoundField DataField="DesignationName" HeaderText="Designation" SortExpression="Designation">
                                                    <ItemStyle Width="400px" />
                                                asp:BoundField>
                                                <asp:BoundField DataField="GradeName" HeaderText="Grade" SortExpression="GradeName">
                                                    <ItemStyle Width="100px" />
                                                asp:BoundField>
                                            Columns>
                                            <HeaderStyle BackColor="#D6E6EB" Font-Bold="True" ForeColor="Black" />
                                        asp:GridView>
                                    ItemTemplate>
                                asp:TemplateField>
                            Columns>
                            <FooterStyle BackColor="White" ForeColor="#000066" />
                            <HeaderStyle BackColor="#006699" Font-Bold="True" ForeColor="White" />
                            <PagerStyle BackColor="White" ForeColor="#000066" HorizontalAlign="Left" />
                            <SelectedRowStyle BackColor="#669999" Font-Bold="True" ForeColor="White" />
                        asp:GridView>
                        <asp:HiddenField ID="hfSortExp" runat="server" />
                        <asp:HiddenField ID="hfWhereCondition" runat="server" />
                        <asp:HiddenField ID="hfddlEmpType" runat="server" />
                    td>
                tr>
table>

Notice in above HTML code I have taken gvDeptNameList to display department list.  Here I have taken two columns. First one to display department name and second on to display related employee information of the department. Second column is TempalteField and contain Detail grid.
Code:
Now we will see back end C# code step by step:
Step1: Populate departments on Page_Load
protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                BindDepartmnets();
                lblTableHeader.Text = "Departemt Wise Employee List";
            }
            SetPageTitle("Departemt Wise Employee List");

        }
public void BindDepartmnets()
        {
            lstDepartmentName.DataSource = oHR_ReportBLL.EmployeeList_GetDistinctDepartments(CustomQueries.VW_EMPLOYEELIST_GETDDISTINCT_DEPARTMENTS);
            lstDepartmentName.DataTextField = "DepartmentName";
            lstDepartmentName.DataValueField = "DepartmentName";
            lstDepartmentName.DataBind();
        }

Step2: Populate Department on btnPreview_Click
protected void btnPreview_Click(object sender, EventArgs e)
        {
            //Get list of selected departments
            List<Department> departmentList = new List<Department>();

            for (int i = 0; i <= lstDepartmentName.Items.Count - 1; i++)
            {
                Department department = new Department();
                ListItem lst = lstDepartmentName.Items[i];
                if (lst.Selected)
                {
                    if (departmentList.Count == 0)
                    {
                        department.DepartmentName = lst.Text;
                        departmentList.Add(department);
                    }
                    else
                    {
                        department.DepartmentName = lst.Text;
                        departmentList.Add(department);
                    }
                }
            }


            gvDeptNameList.DataSource = departmentList;
            gvDeptNameList.DataBind();

        }
Step3: Populate gvEmpLstByDeptAndEmpType on gvDeptNameList_RowDataBound
protected void gvDeptNameList_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowType == System.Web.UI.WebControls.DataControlRowType.DataRow)
            {
                Department department = (Department)e.Row.DataItem;
                GridView gvEmpLstByDeptAndEmpType = (GridView)e.Row.FindControl("gvEmpLstByDeptAndEmpType");

                WhereCondition = " DepartmentName in('" + department.DepartmentName + "') ";
                if (ddlEmpType.SelectedIndex > 0)
                {
                    WhereCondition += " and EmployeeTypeName='" + ddlEmpType.SelectedItem.Text + "'";
                }
                OrderbyClause = " DesignationGroupRank ";
                BindListEmpByDeptAndEmpType(WhereCondition, OrderbyClause, gvEmpLstByDeptAndEmpType);
            }
        }
public void BindListEmpByDeptAndEmpType(string WhereCondition, string orderByExpression, GridView gv)
        {
            List<Hr_GetEmployeesByDeartmentAndEmployeeType> lstHr_GetEmployeesByDeartmentAndEmployeeType = oHR_ReportBLL.Report_Hr_GetEmployeesByDeartmentAndEmployeeType(WhereCondition, orderByExpression);
            gv.DataSource = lstHr_GetEmployeesByDeartmentAndEmployeeType;
            gv.DataBind();
        }
Here notice that I find gridview gvEmpLstByDeptAndEmpType inside row of gvDeptNameList that is binding its row data. Then bind related employee information to gvEmpLstByDeptAndEmpType.

Conclusion
Here I have illustrated how you can extend the functionality of GridView control to display related data by using nested GridView controls on an ASP.NET Web page. You can also extend your application to enable data to be updated and deleted or enable users to insert new records.