GridView export to Excel - c#

I have an asp.net page in which I have a gridview and a button.
On button click event I have wrote the code which exports the gridview to excel which is working very fine.
But when I try to open that exported excel file it shows a dialog box saying:
"The file you are trying to open is in a different format than
specified by the file extension.Verify that the file is not corrupted
and is from a trusted source before opening the file".
Not only that, i sent that excel file as attachment in gmail and tried to open it in mobile, at that time it opens as an html file.What can I do for this because my client will be using mobile to view mails.

I'd recommend creating an actual Excel file instead of a CSV or HTML using an Excel file name extension.
One easy way to accomplish this is using ClosedXML.
To do this, download the ClosedXML.dll and the DocumentFormat.OpenXml.dll from the codeplex site and add them as references in your ASP.NET project. Then, in your button click event, you can simply set up an Excel workbook, create a worksheet from the same DataTable that you are binding to the GridView, and save the workbook file in the HTTP response. Something like this:
var wb = new ClosedXML.Excel.XLWorkbook();
DataTable dt = GetTheDataTable();
dt.TableName = "This will be the worksheet name";
wb.Worksheets.Add(dt);
Response.Clear();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment;filename=\"FileName.xlsx\"");
using (var ms = new System.IO.MemoryStream()) {
wb.SaveAs(ms);
ms.WriteTo(Response.OutputStream);
ms.Close();
}
Response.End();
I'd go with ClosedXML over other alternatives because the license is less restrictive, the documentation is superb, the developer is helpful and friendly, and the project is currently very active.

In your button click event :
protected void btnExcel_Click(object sender, ImageClickEventArgs e)
{
//export to excel
Response.Clear();
Response.AddHeader("content-disposition", "attachment;filename=FileName.xls");
Response.Charset = "";
// If you want the option to open the Excel file without saving then
// comment out the line below
// Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.ContentType = "application/vnd.xls";
System.IO.StringWriter stringWrite = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter htmlWrite = new HtmlTextWriter(stringWrite);
//GV is the ID of gridview
GV.RenderControl(htmlWrite);
Response.Write(stringWrite.ToString());
Response.End();
}
and also override this method in your page code behind:
public override void VerifyRenderingInServerForm(Control control)
{
/* Confirms that an HtmlForm control is rendered for the specified ASP.NET
server control at run time. */
}

When I exported to excel, I simply created a comma separated file and gave it an excel file extension. That message went away when I started separating using commas with double quotes.
"one","two","three" rather than one,two,three

Related

ODT files not opened on button click in browser. How to open an ODT file using C# code?

I need to develop a web application to open an ODT file when I click an image button in the browser. Below is the code that I used to open the file on a button click. It works for a Word document but it is not working for an Open Office document. How can I do this?
<asp:ImageButton id="imagebutton1" runat="server"
AlternateText="ImageButton 1"
Image
ImageUrl="images/pict.jpg"
OnClick="imagebutton1_Click"/>
protected void imagebutton1_Click(object sender, ImageClickEventArgs e)
{
Response.Clear();
Response.ContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
Response.AddHeader("Content-disposition", "inline; filename=TestDoc.docx");
String path = Server.MapPath("TestDoc.docx");
Response.WriteFile(path);
Response.End();
}
Looking at the OpenOffice Reference for File MIME Types, it looks as if the MIME type you're sending back when you set your ContentType property is wrong.
In their reference they list the ODT MIME Type as application/vnd.oasis.opendocument.text
I would suggest setting this MIME Type in your Response Object.
Source: http://www.openoffice.org/framework/documentation/mimetypes/mimetypes.html

Chrome PDF Viewer "Save To Disk" feature - is it possible to control saved filename extension?

In an ASP.NET 2.0 application, using Google Chrome 13 on Windows.
My app dynamically generates a PDF report when the user browses to a particular aspx page. For the most part, things work fine on various browsers.
However, on Chrome, when Chrome's PDF viewer is being used, the following can happen :
- the user presses the floating diskette icon on the bottom right hand side of the viewer to save the PDF document. The file is saved with the aspx page's name. e.g. Report.aspx .
If I open that downloaded aspx file in Adobe Reader, it opens up ok as a PDF document. But is there a way to get chrome to default the name of the file to save to have a ".PDF" extension ?
EDIT :
The code for the report generation page looks something like this :
protected void Page_Load(object sender, EventArgs e)
{
Response.Clear();
Response.ContentType = "application/pdf";
byte[] data = GenerateReportHere(); // dynamically generate PDF report
Response.AddHeader("Content-Length", data.Length.ToString());
Response.BinaryWrite(data);
Response.Flush();
Response.End();
}
Note that I don't want to use a "Content-Disposition" header like :
Response.AddHeader("Content-Disposition", "attachment; filename=Report.pdf");
because that causes the browser to ask the user if they want to download the file. In Chrome it won't display it in its PDF viewer - just gives the user the chance after downloading to open the file using whatever program they have associated with the ".pdf" file extension.
You should try using content-disposition header while streaming the PDF file to the browser. For example,
HttpContext.Current.Response.AddHeader("content-disposition", "attachment; filename=[ReportName].pdf");
// Code to stream pdf file content to the client
...
For more info about content disposition, see
http://www.jtricks.com/bits/content_disposition.html
http://greenbytes.de/tech/webdav/draft-reschke-rfc2183-in-http-latest.html
Since chrome is up to date with HTML5, we can use the shiny new download attribute!
Works

Export to Excel - ThreadAbortException

I'm having a problem with the conversion to Excel code I'm finding. I am working on a website project in .NET 4.0, and I have created a class for this that does the following (based on
http://mattberseth.com/blog/2007/04/export_gridview_to_excel_1.html):
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.AddHeader("content-disposition",
string.Format("attachment; filename={0}", fileName)); HttpContext.Current.Response.ContentType = "application/ms-excel"; using (StringWriter sw = new StringWriter()) {
using (HtmlTextWriter htw = new HtmlTextWriter(sw)) {
//Create a table to contain the grid
//Add header row
//Add each data row
//Add Footer row
//Render the table into the htmlwriter
// render the htmlwriter into the response
HttpContext.Current.Response.Write(sw.ToString());
HttpContext.Current.Response.End();
}
}
I call this class from a usercontrol that contains a button that is added to a GridView displayed on the page. This works as expected - click the button, you are presented with a download option to either open or save the resulting excel spreadsheet containing the data from the GridView.
However, when I call this from a linkbutton inside a different GridView, I'd like to build a dynamic gridview to contain data and export that. When I do that, I get a ThreadAbortException from the Response.End call in the class.
Question 1: Why do I not get that ThreadAbortException when calling the same code from within a usercontrol? Do usercontrols get their own threads or some other kind of context?
Searching on the error I get when that ThreadAbortException occurs led me to attempt to replace it with ApplicationInstance.CompleteRequest(). When I do that I no longer get the ThreadAbortException, but this breaks the previously working usercontrol - instead of the resulting excel spreadsheet containing the data from the grid, it contains the HTML from the containing page, and at any rate it's easy enough to suppress that error with an empty catch. However, it doesn't fix the direct call with the dynamically generated GridView, that code renders a javascript error: "The message received from the server could not be parsed."
I would love to understand what exactly is going on here, but I'm at the point of needing results regardless of understanding. All the other approaches I've tried (datagrid instead of GridView, etc) run into the same problems, and are essentially the same when it comes down to "taking over"
the current response and using stringwriter and htmlwriter to render the data into a response with excel contentType. And since this demonstrably works in the context of a usercontrol, I am at my wit's end as to why it won't work when called directly...
The problem was actually completely unrelated to the excel export. The “…could not be parsed” error was the key. From these links I got the key, which was that the grid events cause only a partial postback event:
http://forums.asp.net/t/1392827.aspx
http://forums.aspfree.com/net-development-11/gridview-footer-template-button-in-updatepanel-not-posting-back-236087.html
This explains the ThreadAbortException and the “…could not be parsed” error. Adding this to the OnPreRender of the ImageButton was the solution:
protected void addTrigger_PreRender(object sender, EventArgs e)
{
if (sender is ImageButton)
{
ImageButton imgBtn = (ImageButton)sender;
ScriptManager ScriptMgr = (ScriptManager)this.FindControl("ScriptManager1");
ScriptMgr.RegisterPostBackControl(ImgBtn);
}
}
Try instead:
HttpApplication.CompleteRequest()
as per:
http://www.c6software.com/codesolutions/dotnet/threadabortexception.aspx
They discuss the additional html being flished
use this
Response.Clear()
Response.AddHeader("content-disposition", atchment;filename=fm_specification.xls")
Response.Charset = ""
Response.Cache.SetCacheability(HttpCacheability.NoCache)
Response.ContentType = "application/vnd.xls"
Dim stringWrite As System.IO.StringWriter = New System.IO.StringWriter
Dim htmlwrite As System.Web.UI.HtmlTextWriter = New HtmlTextWriter(stringWrite)
GridView1.RenderControl(htmlwrite)
Response.Write(stringWrite.ToString)
Response.End()
instead of gridview1 you can use div
dont forget to add this on your page
Public Overrides Sub VerifyRenderingInServerForm(ByVal control As Control)
End Sub
The event on which the Export to excel code is called, must make a full postback. the issue is because it does only a partial postback.
I had the same error and it got solved when i did a full postback.
Hope this helps someone.

Export ListView to Word

To export a gridview to Excel, the reponse content type can be changed to "application/vnd.xls" and then rendered using gridName.RenderControl. Is there any reason this same approach cannot/should not be taken for rendering a listview out to word?
Is there another preferred method for exporting a listview to word?
UPDATE: I have verified that this will work with Word; however, when opening the file, Word displays the html tags (along with the content) from the listview. Below is the code.
Response.Clear();
Response.AddHeader("content-disposition", "attachment;filename=test.doc");
Response.Charset = "";
Response.ContentType = "application/msword";
var stringWriter = new StringWriter();
var htmlWriter = new HtmlTextWriter(stringWriter);
listView.RenderControl(htmlWriter);
Response.Write(stringWriter.ToString());
Response.End();
The same technique will also work for Microsoft Word. The reason this works the way it does, it that both applications will open and read HTML as the source document format. The filename and the content type are set by the website so that the browser knows the application needed to open the file.

Issues exporting datagridview to excel

I'm trying to do an export of a datagrid to excel. For some reason, known working methods aren't working. The export is done from a user control. My page (default.aspx) uses a master page and the page has a user control that actually has the datagrid I'm trying to export.
Here's my code on the ascx:
Response.ClearContent();
Response.AddHeader("content-disposition", "attachment; filename=MyExcelFile.xls");
Response.ContentType = "application/excel";
StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
_gvwResults.RenderControl(htw);
Response.Write(sw.ToString());
Response.End();
On my default.aspx (page the holds the ascx) is this code:
public override void VerifyRenderingInServerForm(Control control)
{
/* Confirms that an HtmlForm control is rendered for the specified ASP.NET
server control at run time. - required to export file */
}
Here's the error I receive:
Sys.Webforms.pagerequestmanagerparsererrorexception. The message received from the server could ot be parsed. Common causes for this error are when the response is modified by calls to Response.Write(), response filters, httpmodules or server trace is enabled.
Any ideas? This code should work but it's almost as if the response object is not being cleared. Ideas?
Turns out that the since the combobox was ajaxified, the export was not happening. The event was firing but, as the error message says, it was response.writing onto the existing page, thus throwing the error, which would not allow for a new document (xls in this case) to be rendered. After setting the combobox to do a postback on the page and un-ajaxifying it, the export started working..

Categories