0

I have the below code to export a GridView into a an excel file. Theoretically, this code should export without any hassles. However, it is exporting the blank.

public static void Export(string fileName, GridView gv, System.Web.UI.Control parentControl)
    {
        HttpContext.Current.Response.Clear();
        HttpContext.Current.Response.AddHeader("content-disposition", string.Format("attachment; filename=" + fileName + ".xls"));
        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
                Table table = new Table();

                //  include the gridline settings
                table.GridLines = gv.GridLines;

                //  add the header row to the table
                if (gv.HeaderRow != null)
                {
                    GridViewExportUtil.PrepareControlForExport(gv.HeaderRow);
                    table.Rows.Add(gv.HeaderRow);
                }

                //  add each of the data rows to the table
                foreach (GridViewRow row in gv.Rows)
                {
                    GridViewExportUtil.PrepareControlForExport(row);
                    table.Rows.Add(row);
                }

                //  add the footer row to the table
                if (gv.FooterRow != null)
                {
                    GridViewExportUtil.PrepareControlForExport(gv.FooterRow);
                    table.Rows.Add(gv.FooterRow);
                }

                //Control 'Content_ctlDisplayIssues_gvIssues' of type 'GridView' must be placed inside a form tag with runat=server.
                System.Web.UI.HtmlControls.HtmlForm form = new System.Web.UI.HtmlControls.HtmlForm();
                parentControl.Controls.Add(form);
                form.Controls.Add(gv);
                form.RenderControl(htw);

                //  render the htmlwriter into the response
                HttpContext.Current.Response.Write(sw.ToString());
                HttpContext.Current.Response.End();
            }
        }
    }

    /// <summary>
    /// Replace any of the contained controls with literals
    /// </summary>
    /// <param name="control"></param>
    private static void PrepareControlForExport(Control control)
    {
        for (int i = 0; i < control.Controls.Count; i++)
        {
            Control current = control.Controls[i];
            if (current is LinkButton)
            {
                control.Controls.Remove(current);
                control.Controls.AddAt(i, new LiteralControl((current as LinkButton).Text));
            }
            else if (current is ImageButton)
            {
                control.Controls.Remove(current);
                control.Controls.AddAt(i, new LiteralControl((current as ImageButton).AlternateText));
            }
            else if (current is HyperLink)
            {
                control.Controls.Remove(current);
                control.Controls.AddAt(i, new LiteralControl((current as HyperLink).Text));
            }
            else if (current is DropDownList)
            {
                control.Controls.Remove(current);
                control.Controls.AddAt(i, new LiteralControl((current as DropDownList).SelectedItem.Text));
            }
            else if (current is CheckBox)
            {
                control.Controls.Remove(current);
                control.Controls.AddAt(i, new LiteralControl((current as CheckBox).Checked ? "True" : "False"));
            }
            else if (current is Image)
            {
                control.Controls.Remove(current);
                control.Controls.AddAt(i, new LiteralControl((current as Image).AlternateText));
            }

            if (current.HasControls())
            {
                GridViewExportUtil.PrepareControlForExport(current);
            }
        }
    }
}

Am I missing something here?

Lulutho Mgwali
  • 823
  • 1
  • 11
  • 33
  • 2 things I notice `1 change your Response.ContentType = "application/vnd.ms-excel";` `2nd` before Current.Response.End, put `HttpContext.Current.Response.Flush();` see if that helps – MethodMan Jun 21 '16 at 19:47
  • also add the following before you add the headers `HttpContext.Current.Response.ClearContent(); and HttpContext.Current.Response.ClearHeaders();` then add this line `HttpContext.Current.Response.ContentType = "application/ms-excel";` then add the line for adding the Headers. – MethodMan Jun 21 '16 at 19:54
  • Let me give that a go. – Lulutho Mgwali Jun 21 '16 at 19:58
  • Instead of downloading after the changes, im redirected to a blank page. – Lulutho Mgwali Jun 21 '16 at 20:06
  • I use OpenXML and CloseXML to do if you download it I can actually give / show you a much simpler way on how to do this in a web form and it would save you a lot of headaches.. OpenXML Assembly is free to download also. and you can do it directly from using a Datatable as well with custom code I have written.. – MethodMan Jun 21 '16 at 20:10

2 Answers2

0

Have you ever opened up an Excel file in NotePad? It's not HTML inside there! Yet you are using an HtmlTextWriter to stream the data to the browser. I don't think that is going to work.

If you are really determined to convert your data into Excel native format, you can either use Excel interop or you can look for a more streamlined third party conversion tool.

If you simply need the user to open a spreadsheet in Excel, but you don't care how the data is transported to the browser, I recommend you stream the data in CSV format, using a technique like the one in this article.

Community
  • 1
  • 1
John Wu
  • 50,556
  • 8
  • 44
  • 80
0

The most part of the code was correct. The problem here is that the HTML Writer is not rendered correctly. John Wu mentioned this in his answer. So the walk-around here is simple:

instead of;

//Control 'Content_ctlDisplayIssues_gvIssues' of type 'GridView' must be placed inside a form tag with runat=server.
System.Web.UI.HtmlControls.HtmlForm form = new System.Web.UI.HtmlControls.HtmlForm();
parentControl.Controls.Add(form);
form.Controls.Add(gv);
form.RenderControl(htw);

I used;

//here the table is rendered into the html writer
table.RenderControl(htw);

also important, is to add this code in the Web.config file

<add key="PageInspector:ServerCodeMappingSupport" value="Disabled" />

This worked seamlessly for me.

Lulutho Mgwali
  • 823
  • 1
  • 11
  • 33