Reputation: 4726
I've spent the last two days trying to get some bloody data to export to Excel. After much research I determined that the best and most common way is using HttpResponse
headers as shown in my code below. After stepping through countless times in debug mode, I have confirmed that the data is in fact there and both filtered and sorted the way I want it. However, it does not download as an Excel file, or do anything at all for that matter.
I suspect this may have something to do with my UpdatePanel
or perhaps the ImageButton
not posting back properly, but I'm not sure. What am I doing wrong? Please help me to debug this issue. I will be eternally grateful. Thank you. :)
Markup
<asp:UpdatePanel ID="statusUpdatePanel" runat="server" UpdateMode="Conditional">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnExportXLS" EventName="Click" />
</Triggers>
<ContentTemplate>
<asp:GridView ID="GridView1" runat="server" AllowPaging="True" PageSize="10"
AllowSorting="True" DataSourceID="GridView1SDS" DataKeyNames="ID">
</asp:GridView>
<span><asp:ImageButton ID="btnExportXLS" runat="server" /></span>
</ContentTemplate>
</asp:UpdatePanel>
Codebehind
Protected Sub ExportToExcel() Handles btnExportXLS.Click
Dim dt As New DataTable()
Dim da As New SqlDataAdapter(SelectCommand, ConnectionString)
da.Fill(dt)
Dim gv As New GridView()
gv.DataSource = dt
gv.DataBind()
Dim sw As New IO.StringWriter()
Dim hw As New System.Web.UI.HtmlTextWriter(sw)
Response.ContentType = "application/vnd.ms-excel"
Response.AddHeader("content-disposition", "attachment;filename=Report.xls")
Response.Charset = String.Empty
gv.RenderControl(hw)
Response.Write(sw.ToString()) 'sw is a valid html table, but no Excel file downloads. :(
Response.End()
End Sub
Upvotes: 0
Views: 16448
Reputation: 1
My solution is to follow these steps:
Step 1 (In Design Page)
SET EnableEventValidation ="false"
in "%@ Page"
<%@ Page Title="" Language="VB" MasterPageFile="~/Aroghyam.master" EnableEventValidation ="false" AutoEventWireup="false" CodeFile="Search_IncidentStatus.aspx.vb" Inherits="Search_IncidentStatus" %>
Step 2 (In Design Page)
If there is an update panel then add an Export button, which, when clicked will export grid data to Excel format asp:PostBackTrigger
(don't put this in asp:AsyncPostBackTrigger
`<asp:PostBackTrigger ControlID="btnExportToExcel" />`
Step 3 (In Code)
Add the following:
Public Overloads Overrides Sub VerifyRenderingInServerForm(ByVal control As Control)
' no implementation necessary,used just to handle error (just paste this to your code)
End Sub
Step 4 (In Code)
Generate the Excel content:
'-------------------GETTING THE DATATABLE------------------
Dim searchResultTable as new Datatable = // GET TABLE FROM DATABASE
'----------------------------------------------------------
'-------------------ASSIGNING TABLE TO GRID----------------
GvIncidentStatus.DataSource = SearchResultTable
GvIncidentStatus.DataBind()
'-----------------CODE FOR GENERATION TO EXCEL
Response.Clear()
GvIncidentStatus.AllowPaging = False
Response.Buffer = True
Me.EnableViewState = False
Response.AddHeader("content-disposition", String.Format("attachment;filename=MyExcelfile.xls"))
Response.Charset = ""
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
Dim sw As New StringWriter()
Dim hw As New HtmlTextWriter(sw)
GvIncidentStatus.RenderControl(hw)
Response.Output.Write(sw.ToString())
Response.End()
'-----------------
Clicking the export button will now download an Excel document.
Upvotes: 0
Reputation: 460228
Response.Clear
at the beginning. GridView.RenderControl(htmlTextWriter)
, hence the page raises an exception that a Server-Control was rendered outside of a Form. Try to execute it in the debugger and i'm fairly sure that you'll see that exception.You could avoid this exception by overriding VerifyRenderingInServerForm
Public Overrides Sub VerifyRenderingInServerForm(control As Control)
' Confirms that an HtmlForm control is rendered for the specified ASP.NET '
' server control at run time. '
End Sub
Edit: I've only just seen that you're using an UpdatePanel
. Make sure that you've created a (Full-)PostBackTrigger
for that button:
<asp:UpdatePanel ID="UpdGridInfo" runat="server" >
<ContentTemplate>
<asp:ImageButton ToolTip="export to Excel" ID="BtnExcelExport" ImageUrl="~/images/excel2007logo.png" runat="server" />
</ContentTemplate>
<Triggers>
<asp:PostBackTrigger ControlID="BtnExcelExport" />
</Triggers>
</asp:UpdatePanel>
But instead of creating a html-table that can be interpreted by excel, i would use a Excel Library like EPPlus(GPL) which i can warmly recommend.
Then it is as easy as this to create Excel-Files from a DataTable and write it to the Response:
Dim pck = New ExcelPackage()
Dim ws = pck.Workbook.Worksheets.Add("Worksheet-Name")
ws.Cells("A1").LoadFromDataTable(dt, True, OfficeOpenXml.Table.TableStyles.Medium1)
Response.Clear()
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
Response.AddHeader("content-disposition", "attachment; filename=ExcelFileName.xlsx")
Response.BinaryWrite(pck.GetAsByteArray())
Response.End()
Here is another example: http://epplus.codeplex.com/wikipage?title=WebapplicationExample
Upvotes: 7