在ASP.NET中生成Excel文件

Dan*_*tes 99 vb.net asp.net export-to-excel

我将在ASP.NET应用程序(VB.NET代码隐藏)中添加一个部分,允许用户将数据作为Excel文件返回给它们,我将根据数据库数据生成该文件.虽然有几种方法可以做到这一点,但每种方法都有其自身的缺点.将如何返回的数据?我正在寻找尽可能干净和简单的东西.

Edu*_*eni 131

CSV

优点:

  • 简单

缺点:

  • 它可能无法在其他语言环境或不同的Excel配置(即列表分隔符)中工作
  • 无法应用格式,公式等

HTML

优点:

  • 还是很简单
  • 支持简单的格式化和公式化

缺点:

  • 您必须将文件命名为xls,Excel可能会警告您打开非本机Excel文件
  • 每个工作簿一个工作表

OpenXML(Office 2007 .XLSX)

优点:

  • 原生Excel格式
  • 支持所有Excel功能
  • 不要需要一个安装的Excel拷贝
  • 可以生成数据透视表
  • 可以使用开源项目EPPlus生成

缺点:

  • Excel 2007之外的兼容性有限(现在应该不是问题)
  • 除非您使用的是第三方组件,否则很复杂

SpreadSheetML(开放格式XML)

优点:

  • 与原生Excel格式相比较简单
  • 支持大多数Excel功能:格式化,样式,公式,每个工作簿多个工作表
  • 不需要安装Excel即可使用它
  • 不需要第三方库 - 只需写出你的xml
  • 可以通过Excel XP/2003/2007打开文档

缺点:

  • 缺乏良好的文档
  • 旧版Excel(2000年以前版本)不支持
  • 只写,一旦打开它并从Excel进行更改,它就会转换为本机Excel.

XLS(由第三方组件生成)

优点:

  • 使用所有格式化,公式等生成本机Excel文件.

缺点:

  • 花钱
  • 添加依赖项

COM Interop

优点:

  • 使用本机Microsoft库
  • 阅读对本机文档的支持

缺点:

  • 非常慢
  • 依赖/版本匹配问题
  • 读取时Web使用的并发/数据完整性问题
  • 非常慢
  • 扩展Web使用的问题(与并发性不同):需要在服务器上创建大量Excel应用程序的实例
  • 需要Windows
  • 我提到它很慢吗?

  • 您可以在Office 2002和2003中保存回SpreadsheetML文件.无需按需保存.SpreadsheetML无法存储宏,图表,图形和其他一些可能性,包括Office 2007的新功能(例如,超过3种条件格式).由于XML很冗长,在从服务器发送之前使用Zipping SpreadsheetML(使用SharpZipLib是一个选项)可以很好地减少下载时间 - 实际上,应该提到OpenXML无论如何都存储在ZIP容器中.@Brian:我每天在50-100MB的范围内使用复杂的SpreadsheetML而不会出现问题. (2认同)
  • @pomarc:它可能很简单,但它不干净.用户想要一个Excel文件,你给他一个带有假扩展名的HTML文件. (2认同)

Joe*_*orn 38

您可以将数据输出为html表格单元格,在其上粘贴.xls.xlsx扩展,Excel将打开它,就像它是本机文档一样.您甚至可以通过这种方式进行有限的格式化和公式计算,因此它比CSV更强大.此外,从ASP.Net等网络平台输出html表应该很容易;)

如果在Excel工作簿中需要多个工作表或命名工作表,则可以通过调用的XML模式执行类似的操作SpreadSheetML.这不是 Office 2007附带的新格式,而是与Excel 2000一样完全不同的东西.解释其工作原理的最简单方法是使用示例:

<?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> 
Run Code Online (Sandbox Code Playgroud)

  • 您可以使用.xml扩展名重命名该文件并添加:<?mso-application progid ="Excel.Sheet"?>在<?xml version ="1.0"之后?>这样,Windows识别该文件是Excel文件,将为其提供正确的图标,当您单击该文件时将打开Excel,Excel将不会抱怨文件格式和内容不匹配.再见. (12认同)

Spo*_*com 16

如果来自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();
}
Run Code Online (Sandbox Code Playgroud)

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


rp.*_*rp. 7

这是一个围绕SpreadML的免费包装器 - 它运行良好.

http://www.carlosag.net/Tools/ExcelXmlWriter/


Dan*_*tes 5

根据给出的答案以及与同事的协商,最佳解决方案似乎是生成XML文件或HTML表格并将其作为附件下推.我的同事推荐的一个改变是数据(即HTML表)可以直接写入Response对象,因此无需写出文件,由于权限问题,I/O可能会很麻烦争用,并确保发生计划的清除.

这是代码的片段......我还没有检查过这个,我还没有提供所有被调用的代码,但我认为它代表了这个想法.

    Dim uiTable As HtmlTable = GetUiTable(groupedSumData)

    Response.Clear()

    Response.ContentType = "application/vnd.ms-excel"
    Response.AddHeader("Content-Disposition", String.Format("inline; filename=OSSummery{0:ddmmssf}.xls", DateTime.Now))

    Dim writer As New System.IO.StringWriter()
    Dim htmlWriter As New HtmlTextWriter(writer)
    uiTable.RenderControl(htmlWriter)
    Response.Write(writer.ToString)

    Response.End()
Run Code Online (Sandbox Code Playgroud)

  • 丹,你走在正确的轨道上.我绝对推荐使用SpreadsheetML而不是HTML - 因为HTML的支持令人沮丧,因此对未来充满了喘息的机会.但是使用HTML,SpreadsheetML和OpenXML,文件大小可能相当大,并且不会被服务器gzip压缩.OpenXML*需要*一个包含多个文件的ZIP容器,如果先将它们压缩并将zip文件作为附件发送,则SpreadsheetML和HTML的下载速度要快得多.使用SharpZipLib并流式传输而不是直接响应. (2认同)