Best way to download excel sheet using ASP.Net - c#

I am using the below code to download the excel file:
Response.ClearContent();
Response.Buffer = true;
Response.AddHeader("content-disposition", string.Format("attachment; filename={0}", "MBQ.xls"));
Response.ContentType = "application/ms-excel";
DataTable dt = BindDatatable();
string str = string.Empty;
foreach (DataColumn dtcol in dt.Columns)
{
Response.Write(str + dtcol.ColumnName);
str = "\t";
}
Response.Write("\n");
foreach (DataRow dr in dt.Rows)
{
str = "";
for (int j = 0; j < dt.Columns.Count; j++)
{
Response.Write(str + Convert.ToString(dr[j]));
str = "\t";
}
Response.Write("\n");
}
Response.End();
In my case, the table has more than 800k records. I am applying more filters before downloading the excel sheet. What is the best way to download a excel sheet from the datatable which has hundreds of thousands of rows?

Firstly since that isn't an excel spreadsheet but a tab-separated-values file (which can be opened in excel and does what you want), then don't lie in the header as that can only bring confusion:
Response.AddHeader("content-disposition", string.Format("attachment; filename={0}", "MBQ.csv"));
Response.ContentType = "text/tab-separated-values";
(Strictly ".csv" is an extension normally defined as being for comma-separated-values rather than tab, but it's more commonly set up to open in Excel, LibreOffice Calc, or whatever spreadsheet program people have installed, and they'll generally consider CSV and TSV as variants of each other).
Secondly, don't buffer. You have Response.Buffer = true; set to explicitly make sure you keep masses of data in memory before sending it, you want to do the opposite, so Response.Buffer = false; is the way to go.
You might find it better still to explicitly call Response.Flush() every couple of hundred or thousand rows:
int rowCount = 0;
foreach (DataRow dr in dt.Rows)
{
str = "";
for (int j = 0; j < dt.Columns.Count; j++)
{
Response.Write(str + Convert.ToString(dr[j]));
str = "\t";
}
Response.Write("\n");
if (unchecked(++rowCount % 1024 == 0))
Response.Flush();
}
Experiment with higher or lower values than 1024. Higher sends larger chunks which is inefficient in needing more memory to hold it, but efficient in the actual sending of the chunk is snappier, so the optimal value will be a matter of finding the best balance between those two factors.

Related

Export large data to xls format: System out of memory Exception

I am exporting a large DataTable to an Excel sheet (.xls) format. I call stored procedure here, which returns the DataTable. The stored procedure used to return 7,50,000 rows with 93 columns.
In back end, if I pass the parameters for the stored procedure, it takes 8 mins to complete the process, since it is a long process.
But when I call the procedure from the front end, while assigning the records to the DataTable, "System Out Of Memory" exception occurring.
So When I google it, I came to know it is because the size exceeds the server RAM size, so it throws this exception.
When I export small DataTable it works fine.
What is the alternate way for this? Anyone suggest me. Below is my code,
C#:
DataTable dt = BindDatatable();
Response.ClearContent();
Response.Buffer = true;
Response.AddHeader("content-disposition", string.Format("attachment; filename={0}", "MBQ_Auto.xls"));
Response.ContentType = "application/ms-excel";
//Response.ContentType = "application/octet-stream";
//Response.ContentType = "text/tab-separated-values";
string str = string.Empty;
foreach (DataColumn dtcol in dt.Columns)
{
Response.Write(str + dtcol.ColumnName);
str = "\t";
}
Response.Write("\n");
int rowCount = 0;
foreach (DataRow dr in dt.Rows)
{
str = "";
for (int j = 0; j < dt.Columns.Count; j++)
{
Response.Write(str + Convert.ToString(dr[j]));
str = "\t";
}
Response.Write("\n");
if (unchecked(++rowCount % 1024 == 0))
Response.Flush();
}
Response.End();
You should not use DataTable for this kind of problem.
DataTable stores the entire data in memory.
You should use the DataReader to fetch rows from database.

NewLine on CSV export of datatable

I have a datatable in a .Net web app that my customers have the option to export to CSV. A few customers have complained that the CSV is not able to re-import to our application. after further review, I noticed that on some large exports, the file has line breaks in it. is there a way i can prevent this?
here is my export method
DataTable dt = (DataTable)Session["Findings"];
string fileName = "test.csv";
string delimiter = ",";
//prepare the output stream
Response.Clear();
Response.ContentEncoding = System.Text.Encoding.UTF8;
Response.ContentType = "application/octet-stream";
Response.AppendHeader("Content-Disposition",
string.Format("attachment; filename={0}", fileName));
//write the csv column headers
for (int i = 0; i < dt.Columns.Count; i++)
{
Response.Write(dt.Columns[i].ColumnName);
Response.Write((i < dt.Columns.Count - 1) ? delimiter : Environment.NewLine);
}
//write the data
foreach (DataRow row in dt.Rows)
{
for (int i = 0; i < dt.Columns.Count; i++)
{
Response.Write("\"" + row[i].ToString() + "\"");
Response.Write((i < dt.Columns.Count - 1) ? delimiter : Environment.NewLine);
}
}
Response.End();
any help would be appreciated.
thanks

error message after converting datatable to excel in asp.net c#

error message after converting datatable to excel in asp.net c#
below code i am using
Response.ClearContent();
Response.Buffer = true;
Response.AddHeader("content-disposition", string.Format("attachment; filename={0}", "Customers.xls"));
Response.ContentType = "application/ms-excel";
DataTable dt = ds.Tables[0];
string str = string.Empty;
foreach (DataColumn dtcol in dt.Columns)
{
Response.Write(str + dtcol.ColumnName);
str = "\t";
}
Response.Write("\n");
foreach (DataRow dr in dt.Rows)
{
str = "";
for (int j = 0; j < dt.Columns.Count; j++)
{
Response.Write(str + Convert.ToString(dr[j]));
str = "\t";
}
Response.Write("\n");
}
Response.End();
error message is
![Your trying to open different format or corrupted file ][2]
its opening after clicking ok but i dnt want showing this message ....
where i made error...
thank you...
Your content type is wrong. You are creating a CSV output, not Excel. Change content type to text/csv and file extension to .csv.
How to use the CSV MIME-type?
Link to OpenXML SDK which let's you create any Office format: http://msdn.microsoft.com/en-us/library/office/bb448854%28v=office.15%29.aspx

ASP.Net to Excel export - column width and alternate row coloring

I have the following method that eventually creates a CSV file and returns the file as a response to a client request.
How can I change the column width to autofit and have alternate coloring of rows?
public static void ExportToCSV(DataTable dt, HttpResponseBase response, string filename)
{
response.AddHeader("content-disposition", "attachment; filename=" + filename);
response.ClearContent();
response.ContentType = "application/vnd.ms-excel";
response.Charset = "UTF-8";
response.ContentEncoding = System.Text.Encoding.Unicode;
response.BinaryWrite(System.Text.Encoding.Unicode.GetPreamble());
string tab = "";
foreach (DataColumn dc in dt.Columns)
{
if (!dc.ColumnName.StartsWith("_"))
{
response.Write(tab + dc.ColumnName);
tab = "\t";
}
}
response.Write("\n");
int i;
foreach (DataRow dr in dt.Rows)
{
tab = "";
for (i = 0; i < dt.Columns.Count; i++)
{
if (!dr.Table.Columns[i].ColumnName.StartsWith("_"))
{
response.Write(Utils.StripHTML(tab + dr[i].ToString().Replace("\n", " ").Replace("\t", " ")));
tab = "\t";
}
}
response.Write("\n");
}
response.End();
}
CSV file is just plain text where values are separated by an agreed separator (usually comma, hence the name, in your case it's TAB character).
Excel has a support for CSV files in such way it represent every value in separate column. This is only visual representation but the file has no actual columns, and cannot contain any form of formatting.
You'd need to change the format of the file to Excel format, and create it that way. You could use Excel interop or writing it as an excel XML file. I'd recommend second option. For a working example of Excel XML you can check this CodeProject example.
You are currently creating a delimited text file.
As the file is a normal text file, it can not have any formatting applied.
Your requirements are to generate an excel file with formatting and certain width, as such this can only be achieved by producing an excel file directly.
This can be done using interop or by outputting the xml required, but some kind of excel library is probably easier to implement without worrying about the details. I personally prefer EPPlus. It is a useful library for creating Excel spreadsheet for excel 2007 onwards. You can install the library using nugget or via a download from the website.
The following gives a quick overview of how to achieve this.
public static void ExportToCSV(DataTable dt, HttpResponseBase response, string filename)
{
response.AddHeader("content-disposition", "attachment; filename=" + filename);
response.ClearContent();
response.ContentType = "application/vnd.ms-excel";
response.Charset = "UTF-8";
response.ContentEncoding = System.Text.Encoding.Unicode;
response.BinaryWrite(System.Text.Encoding.Unicode.GetPreamble());
ExcelPackage package = new ExcelPackage();
package.Workbook.Properties.Comments = "Demo Excel Generation";
package.Workbook.Worksheets.Add("DemoSheet");
ExcelWorksheet sheet = package.Workbook.Worksheets["DemoSheet"];
bool altColour = false;
for (int i = 1; i < 10; i++)
{
for (int j = 1; j < 10; j++)
{
sheet.Cells[i, j].Value = string.Format("{0} - {1}", i, j);
sheet.Row(j).Style.Fill.PatternType = ExcelFillStyle.Solid;
sheet.Row(j).Style.Fill.BackgroundColor.SetColor(altColour ? Color.Gold : Color.Goldenrod);
altColour = !altColour;
}
sheet.Column(i).AutoFit(5f); // Set minimum width to 5 points
}
//package.File = new System.IO.FileInfo(#"C:\test.xlsx");
//package.Save();
package.SaveAs(response.OutputStream);
Response.End();
}
Another library is ClosedXML which has (in my opinion) a nicer syntax than other possibilities by allowing to chain methods. For example:
XLWorkbook workbook = new XLWorkbook("test.xlsx");
IXLWorksheet worksheet = workbook.AddWorksheet("Sheet1");
worksheet.Cell(1, 1).SetValue("Test").Style.Font.SetBold(true);
worksheet.AdjustToContent(); // this changes the column width to fit the content
workbook.Save();

How to export from DataTable to Excel file in text format (even if there are numbers)

I am using the following procedure to create an Excel spreadsheet from a DataTable:
protected void UploadDataTableToExcel(DataTable dtEmp, string filename)
{
string attachment = "attachment; filename=" + filename;
Response.ClearContent();
Response.AddHeader("content-disposition", attachment);
Response.ContentType = "application/vnd.ms-excel";
string tab = string.Empty;
foreach (DataColumn dtcol in dtEmp.Columns)
{
Response.Write(tab + dtcol.ColumnName);
tab = "\t";
}
Response.Write("\n");
foreach (DataRow dr in dtEmp.Rows)
{
tab = "";
for (int j = 0; j < dtEmp.Columns.Count; j++)
{
Response.Write(tab + Convert.ToString(dr[j]));
tab = "\t";
}
Response.Write("\n");
}
Response.End();
}
It works fine except when the cell only has numbers. For example:
This "6969062201223401504" becomes "6.96902E+18"
This "076854957" becomes "76854957"
I would like the Excel spreadsheet to preserve every column as text, instead of converting them into integers

Categories