Export Gridview to Excel with EPPLus - asp.net

I am trying to export data from datatable to Excel file using EPPlus, but nothing seems to work.
This is the code-
using (ExcelPackage xp = new ExcelPackage())
{
ExcelWorksheet ws = xp.Workbook.Worksheets.Add(dt.TableName);
int rowstart = 2;
int colstart = 2;
int rowend = rowstart;
int colend = colstart + dt.Columns.Count;
ws.Cells[rowstart, colstart, rowend, colend].Merge = true;
ws.Cells[rowstart, colstart, rowend, colend].Value = dt.TableName;
ws.Cells[rowstart, colstart, rowend, colend].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
ws.Cells[rowstart, colstart, rowend, colend].Style.Font.Bold = true;
ws.Cells[rowstart, colstart, rowend, colend].Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
ws.Cells[rowstart, colstart, rowend, colend].Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.LightGray);
rowstart += 2;
rowend = rowstart + dt.Rows.Count;
ws.Cells[rowstart, colstart].LoadFromDataTable(dt, true);
int i = 1;
foreach (DataColumn dc in dt.Columns)
{
i++;
if (dc.DataType == typeof(decimal))
ws.Column(i).Style.Numberformat.Format = "#0.00";
}
ws.Cells[ws.Dimension.Address].AutoFitColumns();
ws.Cells[rowstart, colstart, rowend, colend].Style.Border.Top.Style =
ws.Cells[rowstart, colstart, rowend, colend].Style.Border.Bottom.Style =
ws.Cells[rowstart, colstart, rowend, colend].Style.Border.Left.Style =
ws.Cells[rowstart, colstart, rowend, colend].Style.Border.Right.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;
Response.AddHeader("content-disposition", "attachment;filename=logs.xlsx");
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.BinaryWrite(xp.GetAsByteArray());
Response.Close();
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
no exception is shown, code runs smoothly but no file is created.
I really dont know how to get what's happening behind this lines as its showing nothing. But I can see the cells in the sheet are filled.
I tried every other question and solution available on this site and other sites also. But nothing seems to work. so please dont only provide link to other questions and solutions.
Any other kind of advice will be appreciated.

Try this. It works. Response.BinaryWrite does not work very well when downloading a file. And you haven't set the content-length
byte[] bin = xp.GetAsByteArray();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-length", bin.Length.ToString());
Response.AddHeader("content-disposition", "attachment;filename=logs.xlsx");
Response.OutputStream.Write(bin, 0, bin.Length);
Response.Flush();
HttpContext.Current.ApplicationInstance.CompleteRequest();

Probably Response.End() and "application/ms-excel" content type will solve your problem. Try the following code:
byte[] data= xp.GetAsByteArray();
Response.ContentType = "application/ms-excel";
Response.AddHeader("Content-Disposition", "attachment; filename=logs.xlsx; size=" + data.Length);
Response.BinaryWrite(data);
Response.End();
Also if it's not working try to add the following code before:
Response.Clear();
Response.ClearHeaders();
Response.ClearContent();

I have done this with help of another page who's job was just to take the file name and path and send to response.
If anyone stucks like me where you are doing everything right, things working on every other page but not where you want. So you can try this. No refresh or blinking will be done in this case. User wont feel that there was other page used at all.
CardLogs.aspx.cs
string filename = "logs_" + DateTime.Now.ToString("MMddyyyy") + ".xlsx";
FileInfo excelFile = new FileInfo(Server.MapPath("~/Uploads/" + filename));
excel.SaveAs(excelFile);
Session["fileName"] = excelFile.FullName;
Response.Redirect("exportdata.aspx");
exportdata.aspx.cs file -
protected void Page_Load(object sender, EventArgs e)
{
string filePath = HttpContext.Current.Session["fileName"].ToString();
if (!string.IsNullOrEmpty(filePath))
{
Response.ContentType = ContentType;
Response.AppendHeader("Content-Disposition", "attachment; filename=" + Path.GetFileName(filePath));
Response.WriteFile(filePath);
Response.Flush();
File.Delete(filePath);
}
}

Related

Export to CSV Website asp

I have a GridView and when I click Export Button to export my data into CSV. I click the button and it takes all the data correctly but it doesn't show anything, no popup to ask me to open or to save .
Here is my code
protected void btnExport_Click(object sender, EventArgs e)
{
ExportCSV();
}
protected void ExportCSV()
{
GridViewSW.DataSource = ViewState["source"];
Response.Clear();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment;filename=Orders.csv");
Response.Charset = "";
Response.ContentType = "application/text";
GridViewSW.AllowPaging = false;
GridViewSW.DataBind();
StringBuilder columnbind = new StringBuilder();
for (int k = 0; k < GridViewSW.Columns.Count; k++)
{
columnbind.Append(GridViewSW.Columns[k].HeaderText + ",");
}
columnbind.Append("\r\n");
for (int i = 0; i < GridViewSW.Rows.Count; i++)
{
for (int j = 0; j < GridViewSW.Columns.Count; j++)
{
columnbind.Append(GridViewSW.Rows[i].Cells[j].Text + ",");
}
columnbind.Append("\r\n");
}
Response.Output.Write(columnbind.ToString());
Response.Flush();
Response.End();
}
NEW EDIT
I changed the code a little bit. Now i have the csv file and he has all the data in, but when I click the button it doesn't show any dialog box with open or save.
string fullSavePath = HttpContext.Current.Server.MapPath(string.Format("~/csv/Orders.csv"));
StreamWriter sr = new StreamWriter(fullSavePath);
DataSet ds = (DataSet)ViewState["source"];
MyDateTime date = new MyDateTime();
DataTableReader dr = ds.Tables[0].CreateDataReader();
while (dr.Read())
{
sr.Write(dr.GetValue(0) + "," + date.ConvertToDate(Convert.ToInt64(dr.GetValue(2))) + "," + date.ConvertToDate(Convert.ToInt64(dr.GetValue(3))) + "," + dr.GetValue(4) + "\r\n");
}
sr.Flush();
sr.Close();
sr.Dispose();
System.IO.FileInfo file = new System.IO.FileInfo(fullSavePath);
System.Web.HttpContext context = System.Web.HttpContext.Current;
System.Web.HttpResponse response = context.Response;
Response.Clear();
Response.ClearHeaders();
Response.ClearContent();
Response.AddHeader("Content-Length", file.Length.ToString());
Response.ContentType = "text/csv";
Response.AddHeader("Content-Disposition", string.Format("attachment; filename =" + "Orders.csv"));
// Response.TransmitFile(fullSavePath);
Response.WriteFile(file.FullName);
// Response.Flush();
context.ApplicationInstance.CompleteRequest();
// Response.End();
// Response.Close();
I believe you need to change your content type to "text/csv"
Response.ContentType = "text/csv";

Response.Flush() method is not working

Response.Flush method is not working. I am getting the data at pdfContent but it is not opening the PDF documnet. Below is the code. Please help.
public ActionResult PdfClick(int requestid)
{
BusinessRequestController bsnrqstcntrlr = new BusinessRequestController();
try
{
int DocId = (new BusinessRequestBR()).GetBaseLineDocumentsForSearch(requestid);
byte[] PdfContent = (new BusinessRequestHelper()).GetBaseLineDonload(DocId);
Response.Buffer = true;
Response.Clear();
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment; filename=" + "BaseLine_Doc" + "_" + DocId + ".pdf");
Response.BinaryWrite(PdfContent);
Response.Flush();
return Content("");
}
catch (Exception ex)
{
throw this.log.CreatePropagatedException(ex);
}
Instead of using
return Content("")
use this:
return File(
PdfContent,
"application/pdf",
string.Format("BaseLine_Doc{0}.pdf", DocId)
)
There is no need to manipulate the response. Just return the correct result type.
Pulling out code from my running project
Response.Clear();
Response.AddHeader("Content-Disposition","attachment; filename=\"" + file[0].Name + "\"");
Response.AddHeader("Content-Length", fileSize.ToString(_culture));
Response.ContentType = Path.GetExtension(file[0].Name).GetMimeType();
Response.BufferOutput = false;
Response.AddHeader("Accept-Ranges", "bytes"); //tell the client that we accept byte-range requests
while (totalBytesRead < fileSize)
{
if (!Response.IsClientConnected)
{
System.Diagnostics.Debug.WriteLine("--> Client disconnected");
break;
}
int bytesRead = fs.Read(buffer, 0, buffer.Length);
Response.OutputStream.Write(buffer, 0, bytesRead);
Response.Flush();
totalBytesRead += bytesRead;
}
Response.End();
This code works for me every time, please manipulate according to your need.
Note: Variables are defined above the code.

Server.map path not working in asp.net

I am using this code to download a excel file which exist in my solution. I have added a folder FileUpload and added a excel file UploadCWF.xlsx. My code is workin in local host. But not working when I host this to server.I am getting error - Could not find a part of the path. My code -
string filePath = HttpContext.Current.Server.MapPath("~/FileUpload/");
string _DownloadableProductFileName = "UploadCWF.xlsx";
System.IO.FileInfo FileName = new System.IO.FileInfo(filePath + "\\" + _DownloadableProductFileName);
FileStream myFile = new FileStream(filePath + "\\" + _DownloadableProductFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
//Reads file as binary values
BinaryReader _BinaryReader = new BinaryReader(myFile);
//Check whether file exists in specified location
if (FileName.Exists)
{
try
{
long startBytes = 0;
string lastUpdateTiemStamp = File.GetLastWriteTimeUtc(filePath).ToString("r");
string _EncodedData = HttpUtility.UrlEncode(_DownloadableProductFileName, Encoding.UTF8) + lastUpdateTiemStamp;
Response.Clear();
Response.Buffer = false;
Response.AddHeader("Accept-Ranges", "bytes");
Response.AppendHeader("ETag", "\"" + _EncodedData + "\"");
Response.AppendHeader("Last-Modified", lastUpdateTiemStamp);
Response.ContentType = "application/octet-stream";
Response.AddHeader("Content-Disposition", "attachment;filename=" + FileName.Name);
Response.AddHeader("Content-Length", (FileName.Length - startBytes).ToString());
Response.AddHeader("Connection", "Keep-Alive");
Response.ContentEncoding = Encoding.UTF8;
//Send data
_BinaryReader.BaseStream.Seek(startBytes, SeekOrigin.Begin);
//Dividing the data in 1024 bytes package
int maxCount = (int)Math.Ceiling((FileName.Length - startBytes + 0.0) / 1024);
//Download in block of 1024 bytes
int i;
for (i = 0; i < maxCount && Response.IsClientConnected; i++)
{
Response.BinaryWrite(_BinaryReader.ReadBytes(1024));
Response.Flush();
}
}
catch (Exception es)
{
throw es;
}
finally
{
Response.End();
_BinaryReader.Close();
myFile.Close();
}
}
else
System.Web.UI.ScriptManager.RegisterStartupScript(this, GetType(),
"FileNotFoundWarning", "alert('File is not available now!')", true);
Please some one help me.
You should first concat filepath and filename then get path using server.mappath.
You should write code like this
string filePath = HttpContext.Current.Server.MapPath("~/FileUpload/UploadCWF.xlsx");
System.IO.FileInfo FileName = new System.IO.FileInfo(filePath);

Send ExcelPackage file to user

I want to build ExcelPackage file on server side and than send allow user to download it.
Here is my code for file creating:
private byte[] ExcelFileCreate()
{
using (var excelPackage = new ExcelPackage())
{
excelPackage.Workbook.Properties.Author = User.Identity.Name;
excelPackage.Workbook.Properties.Title = "Skybot";
excelPackage.Workbook.Properties.Company = "Dataminds";
excelPackage.Workbook.Worksheets.Add("Selected unit folder");
var excelWorksheet = excelPackage.Workbook.Worksheets[1];
excelWorksheet.Name = "Selected unit folder";
int rowIndex = 1;
int columnIndex = 1;
do
{
var cell = excelWorksheet.Cells[rowIndex, columnIndex];
var fill = cell.Style.Fill;
fill.PatternType = ExcelFillStyle.Solid;
fill.BackgroundColor.SetColor(Color.LightGray);
columnIndex++;
} while (columnIndex != 4);
excelWorksheet.Cells[1, 1].Value = "action cell";
excelWorksheet.Cells[1, 2].Value = "time cell";
excelWorksheet.Cells[1, 3].Value = "processor cell";
excelWorksheet.Cells[2, 1].Value = "action cell";
excelWorksheet.Cells[2, 2].Value = "time cell";
excelWorksheet.Cells[2, 3].Value = "processor cell";
return excelPackage.GetAsByteArray();
}
}
And send it you user:
variant 1:
private void FileTransfer(byte[] fileBytes)
{
//Clear the response
Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
Response.Cookies.Clear();
//Add the header & other information
Response.Cache.SetCacheability(HttpCacheability.Private);
Response.CacheControl = "private";
Response.Charset = System.Text.UTF8Encoding.UTF8.WebName;
Response.ContentEncoding = System.Text.UTF8Encoding.UTF8;
Response.AppendHeader("Content-Length", fileBytes.Length.ToString());
Response.AppendHeader("Pragma", "cache");
Response.AppendHeader("Expires", "60");
Response.AppendHeader("Content-Disposition",
"attachment; " +
"filename=\"ExcelReport.xlsx\"; " +
"size=" + fileBytes.Length.ToString() + "; " +
"creation-date=" + DateTime.Now.ToString("R") + "; " +
"modification-date=" + DateTime.Now.ToString("R") + "; " +
"read-date=" + DateTime.Now.ToString("R"));
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
//Write it back to the client
Response.BinaryWrite(fileBytes);
Response.End();
Response.ContentType = "application/vnd.ms-excel";
Response.AppendHeader("content-disposition", "attachment;filename=test.xlsx");
Response.BinaryWrite(fileBytes);
Response.End();
}
variant 2:
Response.ContentType = "application/vnd.ms-excel";
Response.AppendHeader("content-disposition", "attachment;filename=test.xlsx");
Response.BinaryWrite(fileBytes);
Response.End();
variant 3:
Response.ContentType = "application/vnd.ms-excel";
Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", fileBytes));
Response.AppendHeader("Content-Length", fileBytes.Length.ToString());
Response.BinaryWrite(fileBytes);
Response.End();
And none of them works.
There is no pop-up window with suggestion to store/open file.
Event handler that should make it works:
protected void TreeViewUnit_OnContextMenuItemClick(object sender,
RadTreeViewContextMenuEventArgs eventArgs)
{
FileTransfer(ExcelFileCreate());
}
Any ideas what is wrong?
Try
Response.Clear();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment; filename=ExcelReport.xlsx");
Response.BinaryWrite(fileBytes);
Response.End();
It works for me as shown here.

How can I output to a webform before I clear a response?

I have a Webform where a user clicks a button and an Excel file is generated.
This is achieved by this code:
Response.Clear();
Response.AddHeader("content-disposition", "attachment; filename=export.txt");
Response.ContentType = "text/csv";
Response.WriteFile(FILENAME);
Response.End();
I would like to add to the Response so when the user closes Excel, they can see a message on the Webform.But you can't do this in the code above.
Response.Write("Excel generated!"); ************ does not work as response will be cleared!
Response.Clear();
Response.AddHeader("content-disposition", "attachment; filename=donman_export.txt");
Response.ContentType = "text/csv";
Response.WriteFile(FILENAME);
Response.End();
How can I do this?
Response.Write("Excel generated!"); ************ does not work
Response.Flush();
Response.Clear();
Response.AddHeader("content-disposition", "attachment; filename=donman_export.txt");
Response.ContentType = "text/csv";
Response.WriteFile(FILENAME);
Response.End();
Code below is doing exactly what have you asked.
It renders additional HTML tags, so download starts after message was shown to user:
protected void Page_Load(object sender, EventArgs e)
{
var currentUrl = Request.Url.OriginalString;
var currentQuery = Request.Url.Query;
var download = new
{
FilePath = "~/test.csv",
FileName = "test.csv",
FileMime = "text/csv",
Message = "Excel generated!",
QueryParam = "direct-download",
Delay = 2 // seconds
};
var hasQueryParams = currentQuery.Length > 0;
var isDownloadUrl = hasQueryParams && currentQuery.IndexOf( download.QueryParam ) >= 0;
if( isDownloadUrl )
{
// Prepare..
Response.ContentType = download.FileMime;
Response.Clear();
Response.BufferOutput = true;
// Transfer..
Response.AddHeader("content-disposition", "attachment; filename=" + download.FileName);
Response.WriteFile(download.FilePath);
// Done..
// Instead of Response.Close()
// http://stackoverflow.com/q/4583201/2361743
Response.Flush();
Context.ApplicationInstance.CompleteRequest();
return;
}
// Meta-Refresh Tag has to be in <HEAD> section, but not all browsers follow this restriction.
// IFRAME has to work fine. It is wrapped into <DIV> to be not visible in old browsers.
const string tagToStartManual = "<A href='{0}'>{1}</A>";
const string tagToStartAfterDelay = "<META HTTP-EQUIV='REFRESH' CONTENT='{1};URL={0}'>";
const string tagToStartImmediately = "<DIV STYLE='{1}'><IFRAME SRC='{0}'></IFRAME></DIV>";
const string cssToHideFrame = "width:1px;height:1px;opacity:0.1;overflow:hidden";
// Show your message..
// And add HTML Tags which would start download:
Response.Write(download.Message);
var downloadUrl = currentUrl + (hasQueryParams ? "&" : "?") + download.QueryParam;
// You don't have to use all 3 methods...
Response.Write( String.Format( tagToStartManual, downloadUrl, download.FileName));
Response.Write( String.Format( tagToStartAfterDelay, downloadUrl, download.Delay) );
Response.Write( String.Format( tagToStartImmediately, downloadUrl, cssToHideFrame) );
// Done.
// Waiting for actual download request...
}

Resources