I need to download selected rows of an asp.net gridview to an excel sheet.
What I am doing is trying the check all at once or just a few selected and then after pressing the download button below, all the selected rows get downloaded as excel. Every thing works fine here when I press download button, but rather all the rows get downloaded ignoring the selection.
Following is my code
public void ExportGridToExcel(GridView grdGridView, string fileName)
{
Response.Clear();
Response.AddHeader("content-disposition", string.Format("attachment;filename={0}.xls", fileName));
Response.Charset = "";
Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
Response.ContentType = "application/vnd.xls";
StringWriter stringWriter = new StringWriter();
HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);
// I Tried using following (but with no success)
//-----Trial Starts----------------
//foreach (GridViewRow gvr in gvProgramList.Rows)
// {
// CheckBox cbox = (CheckBox)gvr.FindControl("cboxSelect");
// if(cbox.Checked)
// gvr.Visible = true;
// else
// gvr.Visible = false;
// }
//--------Trial ends---------------
grdGridView.DataBind();
ClearControls(grdGridView);
// Throws exception: Control 'ComputerGrid' of type 'GridView'
// must be placed inside a form tag with runat=server.
// ComputerGrid.RenderControl(htmlWrite);
// Alternate to ComputerGrid.RenderControl above
System.Web.UI.HtmlControls.HtmlForm form = new System.Web.UI.HtmlControls.HtmlForm();
Controls.Add(form);
form.Controls.Add(grdGridView);
form.RenderControl(htmlWriter);
Response.Write(stringWriter.ToString());
Response.End();
foreach (GridViewRow gvr in gvProgramList.Rows)
{
CheckBox cbox = (CheckBox)gvr.FindControl("cboxSelect");
gvr.Visible = true;
}
grdGridView.DataBind();
}
private void ClearControls(Control control)
{
for (int i = control.Controls.Count - 1; i >= 0; i--)
{
ClearControls(control.Controls[i]);
}
if (!(control is TableCell))
{
if (control.GetType().GetProperty("SelectedItem") != null)
{
LiteralControl literal = new LiteralControl();
control.Parent.Controls.Add(literal);
try
{
literal.Text =
(string)control.GetType().GetProperty("SelectedItem").
GetValue(control, null);
}
catch
{ }
control.Parent.Controls.Remove(control);
}
else if (control.GetType().GetProperty("Text") != null)
{
LiteralControl literal = new LiteralControl();
control.Parent.Controls.Add(literal);
literal.Text =
(string)control.GetType().GetProperty("Text").
GetValue(control, null);
control.Parent.Controls.Remove(control);
}
}
return;
}
protected void btnDownload_Click(object sender, EventArgs e)
{
if (gvProgramList.Rows.Count > 0)
{
ExportGridToExcel(gvProgramList, "ProgramList");
}
}
I can suggest you a logic to do this:
1.Create a dynamic datatable with selected rows of your gridview.
its just looping through gridview rows and fetching and appending selected rows to new datatable.
2.Then write code for converting this new datatable to excel sheets(lots of results for google "Convert datatable to excel")
Try like the below code,hope it helps you..
On the download button click event,call this fn
private void ExportToExcell()
{
DataTable dt = new DataTable();
dt.Columns.Add("Plan ID");
dt.Columns.Add("Plan Name");
dt.Columns.Add("Balance");
foreach (GridViewRow row in gdvBal.Rows)
{
CheckBox chkCalls = (CheckBox)row.FindControl("chkCalls");
if (chkCalls.Checked == true)
{
int i = row.RowIndex;
Label lblPlanId = (Label)gdvBal.Rows[i].FindControl("lblPlanId");
Label lblPlanName = (Label)gdvBal.Rows[i].FindControl("lblPlanName");
Label lblBalance = (Label)gdvBal.Rows[i].FindControl("lblBalance");
DataRow dr = dt.NewRow();
dr["Plan ID"] = Convert.ToString(lblPlanId.Text);
dr["Plan Name"] = Convert.ToString(lblPlanName.Text);
dr["Balance"] = Convert.ToString(lblBalance.Text);
dt.Rows.Add(dr);
}
}
GridView gdvExportxls = new GridView();
gdvExportxls.DataSource = dt;
gdvExportxls.DataBind();
Response.Clear();
Response.Buffer = true;
Response.ContentType = "application/ms-excel";
Response.AddHeader("content-disposition", string.Format("attachment;filename=BillingForfBalances.xls", "selectedrows"));
Response.Charset = "";
StringWriter stringwriter = new StringWriter();
HtmlTextWriter htmlwriter = new HtmlTextWriter(stringwriter);
gdvExportxls.RenderControl(htmlwriter);
Response.Write(stringwriter.ToString().Replace("<div>", " ").Replace("</div>", " "));
Response.End();
}
Related
i am come up with scenario that while exporting grid view to excel its not refreshing my grid data source. Below is my code what i have done before. Below code is updating flag in database and then trying to refresh the grid data source in Fill Grid method.
protected void Process_Command(object sender, CommandEventArgs e)
{
if (!string.IsNullOrEmpty(Convert.ToString(e.CommandArgument)))
{
using (var transaction = context.Database.BeginTransaction())
{
DocumentOGP objDocumentOGP = context.DocumentOGPs.Find(Convert.ToInt64(e.CommandArgument));
objDocumentOGP.UpdationDate = DateTime.Now;
objDocumentOGP.DispatchStatusID = 2;
context.DocumentOGPs.Add(objDocumentOGP);
context.Entry(objDocumentOGP).State = System.Data.Entity.EntityState.Modified;
context.SaveChanges();
transaction.Commit();
FillGrid();
}
ExportToExcel(Convert.ToInt64(e.CommandArgument));
}
}
Below is the Export to excel method.
public void ExportToExcel(Int64 OGPCode)
{
DataTable dtPickList =GeneralQuery.GetDocumentPickList(OGPCode);
if (dtPickList != null && dtPickList.Rows.Count>0)
{
//Create a dummy GridView
GridView GridView1 = new GridView();
GridView1.AllowPaging = false;
GridView1.DataSource = dtPickList;
GridView1.DataBind();
Response.Clear();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment;filename=Inbox.xls");
Response.Charset = "";
Response.ContentType = "application/vnd.ms-excel";
StringWriter sw = new StringWriter();
HtmlTextWriter hw = new HtmlTextWriter(sw);
for (int i = 0; i < GridView1.Rows.Count; i++)
{
//Apply text style to each Row
GridView1.Rows[i].Attributes.Add("class", "textmode");
}
GridView1.RenderControl(hw);
//style to format numbers to string
string style = #"<style> .textmode { mso-number-format:\#; } </style>";
Response.Write(style);
Response.Output.Write(sw.ToString());
Response.Flush();
Response.End();
GridView1.DataSource = null;
Response.Write(Request.RawUrl.ToString());
}
}
public override void VerifyRenderingInServerForm(Control control)
{
}
Please help me what i am doing wrong. Thanks
Finally i found the way to refresh the grid view while exporting the grid view to excel. I just create new web form and put ExportGridToExcel() method in Page_Load and on button click it refresh the grid view data source and open new tab to download excel file. Below is my code.
protected void Process_Command(object sender, CommandEventArgs e)
{
if (Session["Status"] != "Refreshed")
{
if (!string.IsNullOrEmpty(Convert.ToString(e.CommandArgument)))
{
using (var transaction = context.Database.BeginTransaction())
{
DocumentOGP objDocumentOGP = context.DocumentOGPs.Find(Convert.ToInt64(e.CommandArgument));
objDocumentOGP.UpdationDate = DateTime.Now;
objDocumentOGP.DispatchStatusID = 2;
context.DocumentOGPs.Add(objDocumentOGP);
context.Entry(objDocumentOGP).State = System.Data.Entity.EntityState.Modified;
context.SaveChanges();
transaction.Commit();
FillGrid();
Session["OGPCode"] = Convert.ToString(e.CommandArgument);
}
ScriptManager.RegisterStartupScript(Page, Page.GetType(), "OpenWindow", "window.open('http://localhost:56430/DownLoadExcel','_newtab');", true);
}
}
}
Below is my Download excel file web-form and its implementation
public partial class DownLoadExcel : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
if (!string.IsNullOrEmpty(Convert.ToString(Session["OGPCode"])))
{
ExportToExcel(Convert.ToInt64(Session["OGPCode"]));
Session["OGPCode"] = null;
}
}
}
public void ExportToExcel(Int64 OGPCode)
{
DataTable dt = GeneralQuery.GetDocumentPickList(OGPCode);
//create a new byte array
byte[] bin;
string FileName = "Pick-List-" + DateTime.Now.ToString();
//create a new excel document
using (ExcelPackage excelPackage = new ExcelPackage())
{
//create a new worksheet
ExcelWorksheet ws = excelPackage.Workbook.Worksheets.Add(FileName);
//add the contents of the datatable to the excel file
ws.Cells["A1"].LoadFromDataTable(dt, true);
//auto fix the columns
ws.Cells[ws.Dimension.Address].AutoFitColumns();
//loop all the columns
for (int col = 1; col <= ws.Dimension.End.Column; col++)
{
//make all columns just a bit wider, it would sometimes not fit
ws.Column(col).Width = ws.Column(col).Width + 1;
var cell = ws.Cells[1, col];
//make the text bold
cell.Style.Font.Bold = true;
//make the background of the cell gray
var fill = cell.Style.Fill;
fill.PatternType = ExcelFillStyle.Solid;
fill.BackgroundColor.SetColor(ColorTranslator.FromHtml("#BFBFBF"));
//make the header text upper case
cell.Value = ((string)cell.Value).ToUpper();
}
//convert the excel package to a byte array
bin = excelPackage.GetAsByteArray();
}
//clear the buffer stream
Response.ClearHeaders();
Response.Clear();
Response.Buffer = true;
//set the correct contenttype
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
//set the correct length of the data being send
Response.AddHeader("content-length", bin.Length.ToString());
//set the filename for the excel package
Response.AddHeader("content-disposition", "attachment; filename=\"" + FileName + ".xlsx\"");
//send the byte array to the browser
Response.OutputStream.Write(bin, 0, bin.Length);
//cleanup
Response.Flush();
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
}
When you update GridView or any control values dynamically you should render and export it to other application.
Sample: check with RenderControl method of GridView.
private void ExportGridToExcel()
{
Response.Clear();
Response.Buffer = true;
Response.ClearContent();
Response.ClearHeaders();
Response.Charset = "";
string FileName = "xyz.xls";
StringWriter strwritter = new StringWriter();
HtmlTextWriter htmltextwrtter = new HtmlTextWriter(strwritter);
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.ContentType = "application/vnd.ms-excel";
Response.AddHeader("Content-Disposition", "attachment;filename=" + FileName);
GridView1.RenderControl(htmltextwrtter);
Response.Write(strwritter.ToString());
Response.End();
}
I want to set the Column header text with [DisplayName()] attribute when I export the List to Excel file.
any solution ?
GridView gv = new GridView();
gv.DataSource = ExportList;
gv.DataBind();
System.Web.HttpContext.Current.Response.ClearContent();
System.Web.HttpContext.Current.Response.Buffer = true;
System.Web.HttpContext.Current.Response.AddHeader("content-disposition", "attachment; filename=Rapor.xls");
System.Web.HttpContext.Current.Response.ContentType = "application/ms-excel";
System.Web.HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.Unicode;
System.Web.HttpContext.Current.Response.BinaryWrite(System.Text.Encoding.Unicode.GetPreamble());
StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
gv.RenderControl(htw);
System.Web.HttpContext.Current.Response.Output.Write(sw.ToString());
System.Web.HttpContext.Current.Response.Flush();
System.Web.HttpContext.Current.Response.End();
You must use RowDataBound event of grid like this:
First put this line after creating gv:
gv.RowDataBound+=GvOnRowDataBound;
Then follow this code:
private void GvOnRowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
for (int i = 0; i < e.Row.Cells.Count;i++)
{
var customAttributes =
typeof (YourClass).GetProperty(e.Row.Cells[i].Text).CustomAttributes.ToList();
var displayNameAttribute =
customAttributes.FirstOrDefault(
aa => aa.AttributeType.FullName.Equals("System.ComponentModel.DisplayNameAttribute"));
if (displayNameAttribute != null)
e.Row.Cells[i].Text = displayNameAttribute.ConstructorArguments[0].ToString();
}
}
}
Remember change YourClass to the name of your class.
I have 6 gridviews in my website that I need to export to excel, but each one in one different sheet.
This link Export GridView to multiple Excel sheet uses something quite similar, but he is using datasets and I am not. I am new to C#, so I couldnt change it to fit my solution.
My code exports all gridviews to the same sheet. I created a loop to run throught my gridviews, now I need to put a code to generate each one to each excel sheet.
protected void btExcel_Click(object sender, EventArgs e)
{
Response.Clear();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment;filename=FARPOP_Mensal_" + txDt.Text + ".xls");
Response.ContentEncoding = System.Text.Encoding.GetEncoding("Windows-1252");
Response.Charset = "ISO-8859-1";
Response.ContentType = "application/vnd.ms-excel";
using (StringWriter sw = new StringWriter())
{
HtmlTextWriter hw = new HtmlTextWriter(sw);
GridView[] gvExcel = new GridView[] { gvAnual, gvPorUF, gvPorFarmacia, gvPorMunicipio, gvPorPV, gvPorCNPJ };
for (int i = 0; i < gvExcel.Length; i++)
{
GridView gv = gvExcel[i];
//
// Need to redirect to each sheet here?
//
gvExcel[i].HeaderRow.BackColor = Color.White;
gvExcel[i].UseAccessibleHeader = false;
gvExcel[i].AllowPaging = false;
for (int x = 0; x < gvExcel[i].Columns.Count; x++)
{
gvExcel[i].Columns[x].Visible = true;
}
gvExcel[i].DataBind();
foreach (TableCell cell in gvExcel[i].HeaderRow.Cells)
{
cell.BackColor = Color.CadetBlue;
cell.Enabled = false;
}
foreach (GridViewRow row in gvExcel[i].Rows)
{
row.BackColor = Color.White;
foreach (TableCell cell in row.Cells)
{
cell.Controls.Clear();
if (row.RowIndex % 2 == 0)
{
cell.BackColor = Color.White;
}
else
{
cell.BackColor = Color.LightBlue;
}
cell.CssClass = "textmode";
}
}
gvExcel[i].RenderControl(hw);
}
//style to format numbers to string
string style = #"<style> .textmode { } </style>";
Response.Write(style);
Response.Output.Write(sw.ToString());
Response.Flush();
Response.End();
}
}
I followed maniak1982 comments and found a good solution.
So, if you need multiple gridviews to multiples worksheets, using .NET, you will need to download ClosedXML and also DocumentFormat.OpenXml.dll.
After referencing the dll, use the following code:
protected void btExcel_Click(object sender, EventArgs e)
{
XLWorkbook wb = new XLWorkbook();
GridView[] gvExcel = new GridView[] { GridView1, GridView2, GridView3, GridView4, GridView5, GridView6};
string[] name = new string[] { "Name1", "Name2", "Name3", "Name4", "Name5", "Name6" };
for (int i = 0; i < gvExcel.Length; i++)
{
if (gvExcel[i].Visible)
{
gvExcel[i].AllowPaging = false;
gvExcel[i].DataBind();
DataTable dt = new DataTable(name[i].ToString());
for (int z = 0; z < gvExcel[i].Columns.Count; z++)
{
dt.Columns.Add(gvExcel[i].Columns[z].HeaderText);
}
foreach (GridViewRow row in gvExcel[i].Rows)
{
dt.Rows.Add();
for (int c = 0; c < row.Cells.Count; c++)
{
dt.Rows[dt.Rows.Count - 1][c] = row.Cells[c].Text;
}
}
wb.Worksheets.Add(dt);
gvExcel[i].AllowPaging = true;
}
}
Response.Clear();
Response.Buffer = true;
Response.Charset = "";
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment;filename=Workbook_Name.xlsx");
using (MemoryStream MyMemoryStream = new MemoryStream())
{
wb.SaveAs(MyMemoryStream);
MyMemoryStream.WriteTo(Response.OutputStream);
Response.Flush();
Response.End();
}
}
It took me days of searching... But it's working perfectly.
Be happy
I have the code below that generates an excel file when clicked. the code runs fine the formatting of colors is fine. The grid view has data with leading zeros that are not showing in excel along with long numbers "106638660952840428" which show up as 1.06639E+17 with a value of 106638660952840000 so it loses its last four digits as well. I have tried several ways to export all with the same results. I am doing it this way to have the chance at formatting the cells individually.So the question is does anyone know how to dynamically change the format so these problems do not occur? Another thing to add is that the grid-view in a web browser does display the data correctly.
protected void LinkButton6_Click(object sender, EventArgs e)
{
Iframe1.Attributes.Add("src", "blank.aspx");
if (CheckBox5.Checked || CheckBox6.Checked)
{
dt = (DataTable)Cache["dtable"];
Response.Clear();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment;filename=BemisInventory.xls");
Response.Charset = "";
Response.ContentType = "application/vnd.ms-excel";
using (StringWriter sw = new StringWriter())
{
HtmlTextWriter hw = new HtmlTextWriter(sw);
//To Export all pages
GridView1.AllowPaging = false;
GridView1.DataSource = dt;
//GridView1.PageIndex = 0;
GridView1.DataBind();
GridView1.HeaderRow.BackColor = Color.White;
foreach (TableCell cell in GridView1.HeaderRow.Cells)
{
cell.BackColor = Color.White;//GridView1.HeaderStyle.BackColor;
}
foreach (GridViewRow row in GridView1.Rows)
{
row.BackColor = Color.White;
foreach (TableCell cell in row.Cells)
{
if (row.RowIndex % 2 == 0)
{
cell.BackColor = Color.White;
}
else
{
cell.BackColor = Color.White; //GridView1.RowStyle.BackColor;
}
cell.CssClass = "textmode";
}
}
GridView1.RenderControl(hw);
//style to format numbers to string
string style = #"<style> .textmode { } </style>";
Response.Write(style);
Response.Output.Write(sw.ToString());
Response.Flush();
Response.End();
}
}
}
Fixed by adding: string style = #" .textmode { mso-number-format:\#; } "; comes up with warnings but all data is there.
On my aspx page, I have a Usercontrol which contains a Gridview, whose data is loaded dynamically based on params passed from the aspx page to the UserControl, which I called QuotesReport1.
When the export runs, it only exports the layout into the Spreadsheet, and none of the gridview's data, for example:
<style>
body
{
margin: 0px;
}
</style>
<div>
</div>
My code for the export is:
protected void Page_Load(object sender, EventArgs e)
{
string toDate = "";
string fromDate = "";
toDate = Request.QueryString.Get("toDate");
fromDate = Request.QueryString.Get("fromDate");
QuotesReport1.ToDate = DateTime.Parse(toDate);
QuotesReport1.FromDate = DateTime.Parse(fromDate);
QuotesReport1.Status = QuotesReport.quoteStatus.PENDING_REVIEW;
string attachment = "attachment; filename=Quotes_Pending.xls";
Response.ClearContent();
Response.AddHeader("content-disposition", attachment);
Response.ContentType = "application/ms-excel";
StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
QuotesReport1.RenderControl(htw);
Response.Write(sw.ToString());
Response.End();
}
public override void VerifyRenderingInServerForm(Control control) { }
Inside the UserControl, a SQL query runs, which returns a DataTable, which is then bound to the Gridview inside the UserControl, something along the lines of:
SQLData da = new SQLData();
GridView1.DataSource = da.SGetDataTable(query);
GridView1.DataBind();
The simplest of the ways i have
public class ExcelUtility
{
public static void ToExcel(object dataSource)
{
GridView grid = new GridView { DataSource = dataSource };
grid.DataBind();
StringBuilder sb = new StringBuilder();
foreach (TableCell cell in grid.HeaderRow.Cells)
sb.Append(string.Format("\"{0}\",", cell.Text));
sb.Remove(sb.Length - 1, 1);
sb.AppendLine();
foreach (GridViewRow row in grid.Rows)
{
foreach (TableCell cell in row.Cells)
sb.Append(string.Format("\"{0}\",", cell.Text.Trim().Replace(" ", string.Empty)));
sb.Remove(sb.Length - 1, 1);
sb.AppendLine();
}
ExportToExcel(sb.ToString());
}
private static void ExportToExcel(string data)
{
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.AddHeader("content-disposition", "attachment;filename=Report.csv");
HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.GetEncoding("UTF-8");
HttpContext.Current.Response.ContentType = "text/csv";
HttpContext.Current.Response.Write(data);
HttpContext.Current.Response.End();
}
}
using:
string result = ExcelUtility.ToExcel(_db.FindAll());
ExcelUtility.ExportToExcel(result);