Generating an Excel file in ASP.NET [closed] Generating an Excel file in ASP.NET [closed] asp.net asp.net

Generating an Excel file in ASP.NET [closed]


CSV

Pros:

  • Simple

Cons:

  • It may not work in other locales or in different Excel configurations (i.e. List separator)
  • Can't apply formatting, formulas, etc

HTML

Pros:

  • Still pretty Simple
  • Supports simple formating and formulas

Cons:

  • You have to name the file as xls and Excel may warn you about opening a non native Excel file
  • One worksheet per workbook

OpenXML (Office 2007 .XLSX)

Pros:

  • Native Excel format
  • Supports all Excel features
  • Do not require an install copy of Excel
  • Can generate Pivot tables
  • Can be generated using open source project EPPlus

Cons:

  • Limited compatibility outside Excel 2007 (shouldn't be a problem nowadays)
  • Complicated unless you're using a third party component

SpreadSheetML (open format XML)

Pros:

  • Simple compared to native Excel formats
  • Supports most Excel features: formating, styles, formulas, multiple sheets per workbook
  • Excel does not need to be installed to use it
  • No third party libraries needed - just write out your xml
  • Documents can be opened by Excel XP/2003/2007

Cons:

  • Lack of good documentation
  • Not supported in older versions of Excel (pre-2000)
  • Write-only, in that once you open it and make changes from Excel it's converted to native Excel.

XLS (generated by third party component)

Pros:

  • Generate native Excel file with all the formating, formulas, etc.

Cons:

  • Cost money
  • Add dependencies

COM Interop

Pros:

  • Uses native Microsoft libraries
  • Read support for native documents

Cons:

  • Very slow
  • Dependency/version matching issues
  • Concurrency/data integrity issues for web use when reading
  • Very slow
  • Scaling issues for web use (different from concurrency): need to create many instances of heavy Excel app on the server
  • Requires Windows
  • Did I mention that it's slow?


You can output the data as html table cells, stick a .xls or .xlsx extension on it, and Excel will open it as if it were a native document. You can even do some limited formatting and formula calculations this way, so it's much more powerful than CSV. Also, outputting an html table ought to be pretty easy to do from a web platform like ASP.Net ;)

If you need multiple worksheets or named worksheets within your Excel Workbook, you can do something similar via an XML schema called SpreadSheetML. This is not the new format that shipped with Office 2007, but something completely different that works as far back as Excel 2000. The easiest way to explain how it works is with an example:

<?xml version="1.0"?><?mso-application progid="Excel.Sheet"?> <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"        xmlns:o="urn:schemas-microsoft-com:office:office"        xmlns:x="urn:schemas-microsoft-com:office:excel"        xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"        xmlns:html="http://www.w3.org/TR/REC-html40"><DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">      <Author>Your_name_here</Author>      <LastAuthor>Your_name_here</LastAuthor>      <Created>20080625</Created>      <Company>ABC Inc</Company>      <Version>10.2625</Version></DocumentProperties><ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">        <WindowHeight>6135</WindowHeight>        <WindowWidth>8445</WindowWidth>        <WindowTopX>240</WindowTopX>        <WindowTopY>120</WindowTopY>        <ProtectStructure>False</ProtectStructure>        <ProtectWindows>False</ProtectWindows></ExcelWorkbook><Styles>      <Style ss:ID="Default" ss:Name="Normal">            <Alignment ss:Vertical="Bottom" />            <Borders />            <Font />            <Interior />            <NumberFormat />            <Protection />      </Style></Styles><Worksheet ss:Name="Sample Sheet 1"><Table ss:ExpandedColumnCount="2" x:FullColumns="1" x:FullRows="1" ID="Table1"><Column ss:Width="150" /><Column ss:Width="200" /><Row>      <Cell><Data ss:Type="Number">1</Data></Cell>      <Cell><Data ss:Type="Number">2</Data></Cell></Row><Row>      <Cell><Data ss:Type="Number">3</Data></Cell>      <Cell><Data ss:Type="Number">4</Data></Cell></Row><Row>      <Cell><Data ss:Type="Number">5</Data></Cell>      <Cell><Data ss:Type="Number">6</Data></Cell></Row><Row>      <Cell><Data ss:Type="Number">7</Data></Cell>      <Cell><Data ss:Type="Number">8</Data></Cell></Row></Table></Worksheet><Worksheet ss:Name="Sample Sheet 2"><Table ss:ExpandedColumnCount="2" x:FullColumns="1" x:FullRows="1" ID="Table2"><Column ss:Width="150" /><Column ss:Width="200" /><Row>      <Cell><Data ss:Type="String">A</Data></Cell>      <Cell><Data ss:Type="String">B</Data></Cell></Row><Row>      <Cell><Data ss:Type="String">C</Data></Cell>      <Cell><Data ss:Type="String">D</Data></Cell></Row><Row>      <Cell><Data ss:Type="String">E</Data></Cell>      <Cell><Data ss:Type="String">F</Data></Cell></Row><Row>      <Cell><Data ss:Type="String">G</Data></Cell>      <Cell><Data ss:Type="String">H</Data></Cell></Row></Table></Worksheet></Workbook> 


If coming from a DataTable:

public static void DataTabletoXLS(DataTable DT, string fileName){    HttpContext.Current.Response.Clear();    HttpContext.Current.Response.Charset = "utf-16";    HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.GetEncoding("windows-1250");    HttpContext.Current.Response.AddHeader("content-disposition", string.Format("attachment; filename={0}.xls", fileName));    HttpContext.Current.Response.ContentType = "application/ms-excel";    string tab = "";    foreach (DataColumn dc in DT.Columns)    {        HttpContext.Current.Response.Write(tab + dc.ColumnName.Replace("\n", "").Replace("\t", ""));        tab = "\t";    }    HttpContext.Current.Response.Write("\n");    int i;    foreach (DataRow dr in DT.Rows)    {        tab = "";        for (i = 0; i < DT.Columns.Count; i++)        {            HttpContext.Current.Response.Write(tab + dr[i].ToString().Replace("\n", "").Replace("\t", ""));            tab = "\t";        }        HttpContext.Current.Response.Write("\n");    }    HttpContext.Current.Response.End();}

From a Gridview:

public static void GridviewtoXLS(GridView gv, string fileName){    int DirtyBit = 0;    int PageSize = 0;    if (gv.AllowPaging == true)    {        DirtyBit = 1;        PageSize = gv.PageSize;        gv.AllowPaging = false;        gv.DataBind();    }    HttpContext.Current.Response.Clear();    HttpContext.Current.Response.Charset = "utf-8";    HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.GetEncoding("windows-1250");    HttpContext.Current.Response.AddHeader(        "content-disposition", string.Format("attachment; filename={0}.xls", 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        Table table = new Table();        //  include the gridline settings        table.GridLines = gv.GridLines;        //  add the header row to the table        if (gv.HeaderRow != null)        {            Utilities.Export.PrepareControlForExport(gv.HeaderRow);            table.Rows.Add(gv.HeaderRow);        }        //  add each of the data rows to the table        foreach (GridViewRow row in gv.Rows)        {            Utilities.Export.PrepareControlForExport(row);            table.Rows.Add(row);        }        //  add the footer row to the table        if (gv.FooterRow != null)        {            Utilities.Export.PrepareControlForExport(gv.FooterRow);            table.Rows.Add(gv.FooterRow);        }        //  render the table into the htmlwriter        table.RenderControl(htw);        //  render the htmlwriter into the response        HttpContext.Current.Response.Write(sw.ToString().Replace("£", ""));        HttpContext.Current.Response.End();    }    if (DirtyBit == 1)    {        gv.PageSize = PageSize;        gv.AllowPaging = true;        gv.DataBind();    }}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"));        }        if (current.HasControls())        {            Utilities.Export.PrepareControlForExport(current);        }    }}