【问题标题】:Generating an Excel file in ASP.NET [closed]在 ASP.NET 中生成 Excel 文件 [关闭]
【发布时间】:2010-09-14 02:25:37
【问题描述】:

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

【问题讨论】:

标签: asp.net vb.net export-to-excel


【解决方案1】:

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 互操作

优点:

  • 使用原生 Microsoft 库
  • 对原生文档的读取支持

缺点:

  • 很慢
  • 依赖/版本匹配问题
  • 阅读时 Web 使用的并发/数据完整性问题
  • 很慢
  • Web 使用的扩展问题(不同于并发):需要在服务器上创建许多重型 Excel 应用程序实例
  • 需要 Windows
  • 我有没有提到它很慢?

【讨论】:

  • SpreadsheetML 提到的“只写”约束并不完全是个问题,因为您可以根据需要将 Excel 文件另存为 SpreadsheetML。
  • SpreadsheetML 如果您使用它创建大文件,可能会使 Excel 2003 崩溃。不要相信它:/
  • 您可以在 Office 2002 和 2003 中很好地保存回 SpreadsheetML 文件。无需另存为。 SpreadsheetML 不能存储宏、图表、图形和其他一些零碎的东西,包括 Office 2007 的新功能(例如,超过 3 种条件格式)。由于 XML 很冗长,因此在从服务器发送之前压缩 SpreadsheetML(使用 SharpZipLib 是一种选择)可以很好地减少下载时间——实际上,应该提到 OpenXML 无论如何都存储在 ZIP 容器中。 @Brian:我每天使用 50-100MB 范围内的复杂 SpreadsheetML,没有崩溃问题。
  • 如果您可能需要导出大量数据,您应该导出为 CSV。除了 SpreadsheetML 之外,很难使用任何其他格式制作高性能的解决方案。 HTML 可以高效地编写和读取,但需要您进一步规范才能有用。正如 Brian 在评论中提到的那样,HTML 和 SpreadsheetML 都存在其他关于大文件的问题。因此,如果您只需要使用 CSV 进行简单的数据导出。
  • @pomarc:这可能很简单,但并不干净。用户想要一个 Excel 文件,而你给他一个带有假扩展名的 HTML 文件。
【解决方案2】:

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

如果您需要 Excel 工作簿中的多个工作表或命名工作表,您可以通过名为 SpreadSheetML 的 XML 架构执行类似的操作。这不是 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> 

【讨论】:

  • 您可以使用 .xml 扩展名重命名文件并在 之后添加: Windows 识别该文件是 Excel 文件的方式,会给它正确的图标,当您单击文件时会打开 excel,并且 Excel 不会抱怨文件格式和内容不匹配。再见。
  • @pomarc 这样做的缺点是其他导入 excel 文件的程序将无法识别它。但是,他们可能无论如何都不会解析 xml。
  • 我已经相当成功地使用了这种技术。这将是我的建议 - 简单且非常有效。
  • HTML 表格数据掩码为 XLS 文件的两个潜在问题 (YMMV):(1) Microsoft Excel 将自动修剪前导空格和零; (2) Microsoft Excel 2010 在打开包含 HTML 表格数据的 XLS 文件时会警告用户。 #1 的解决方案似乎是 creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel (如果前导空格/零很重要并且需要保留)。
  • 只是为了澄清,虽然我确实提到了 HTML 表格,但这个答案的重点是 SpreadsheetML,它不仅仅是 HTML 表格数据。 Excel 将其视为本机。
【解决方案3】:

如果来自 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();
}

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);
        }
    }
}

【讨论】:

  • 只是我需要的代码,谢谢。 :)
  • Scott,英镑(“£”)符号是怎么回事?如果我需要它怎么办?还有其他危险的角色吗?
  • 完美。正是我需要的。
  • 英镑符号实际上只是我的一位客户需要的东西。你可以把它拿出来。
  • HTML 表格数据掩码为 XLS 文件的两个潜在问题 (YMMV):(1) Microsoft Excel 将自动修剪前导空格和零; (2) Microsoft Excel 2010 在打开包含 HTML 表格数据的 XLS 文件时会警告用户。 #1的解决方案似乎是 creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel (如果前导空格/零很重要并且需要保留)。 CSV 数据文件在 Microsoft Excel 中打开时也会受到 #1 的影响。
【解决方案4】:

这是一个围绕 SpreadML 的免费包装器——效果很好。

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

【讨论】:

  • 我也用过 - 很棒。
  • 这个库也可以读取xls?
【解决方案5】:

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

这是代码的sn-p...我还没有检查过这个,我还没有提供所有被调用的代码,但我认为它很好地代表了这个想法。

    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()

【讨论】:

  • 丹,你在正确的轨道上。我绝对推荐 SpreadsheetML 而不是 HTML——为未来提供喘息的空间,因为 HTML 支持非常有限。但是对于 HTML、SpreadsheetML 和 OpenXML,文件大小可能会相当大,并且不会被服务器 gzip 压缩。 OpenXML 需要一个包含多个文件的 ZIP 容器,如果您先压缩它们并将 zip 作为附件发送,SpreadsheetML 和 HTML 的下载速度都会快得多。使用 SharpZipLib 并流式传输到它,而不是直接传输到 Response。
【解决方案6】:

由于 Excel 可以理解 HTML,您只需将数据作为 HTML 表写入扩展名为 .xls 的临时文件,获取文件的 FileInfo,然后使用

Response.Clear();
Response.AddHeader("Content-Disposition", "attachment; filename=" + fi.Name);
Response.AddHeader("Content-Length", fi.Length.ToString());
Response.ContentType = "application/octet-stream";
Response.WriteFile(fi.FullName);
Response.End();

如果你想避免临时文件,你可以写入内存流并将字节写回而不是使用 WriteFile

如果省略了 content-length 标头,您可以直接写回 html,但这可能无法在所有浏览器中一直正常工作

【讨论】:

  • HTML 表格数据掩码为 XLS 文件的两个潜在问题 (YMMV):(1) Microsoft Excel 将自动修剪前导空格和零; (2) Microsoft Excel 2010 在打开包含 HTML 表格数据的 XLS 文件时会警告用户。 #1 的解决方案似乎是 creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel (如果前导空格/零很重要并且需要保留)。
【解决方案7】:

我个人更喜欢 XML 方法。我将从数据集中的数据库中返回数据,将其保存到 XMl,然后创建一个 xslt 文件,其中包含一个转换规则,该规则将格式化一个正确的文档,一个简单的 XML 转换将完成这项工作。最好的部分是您可以格式化单元格、进行条件格式化、设置页眉和页脚,甚至设置打印范围。

【讨论】:

    【解决方案8】:

    我已经这样做了几次,每次最简单的方法就是简单地返回一个 CSV(逗号分隔值)文件。 Excel 完美导入,速度相对较快。

    【讨论】:

    • CSV 数据的一个潜在问题 (YMMV):Microsoft Excel 将自动修剪前导空格和零
    【解决方案9】:

    我们一直将数据从数据网格导出到 Excel。将其转换为 HTML,然后写入 excel 文件

    Response.ContentType = "application/vnd.ms-excel"
        Response.Charset = ""
        Response.AddHeader("content-disposition", "fileattachment;filename=YOURFILENAME.xls")
        Me.EnableViewState = False
        Dim sw As System.IO.StringWriter = New System.IO.StringWriter
        Dim hw As HtmlTextWriter = New HtmlTextWriter(sw)
        ClearControls(grid)
        grid.RenderControl(hw)
        Response.Write(sw.ToString())
        Response.End()
    

    这种方法的唯一问题是我们的很多网格中都有按钮或链接,所以你也需要这个:

    'needed to export grid to excel to remove link button control and represent as text
    Private Sub ClearControls(ByVal control As Control)
        Dim i As Integer
        For i = control.Controls.Count - 1 To 0 Step -1
            ClearControls(control.Controls(i))
        Next i
    
        If TypeOf control Is System.Web.UI.WebControls.Image Then
            control.Parent.Controls.Remove(control)
        End If
    
        If (Not TypeOf control Is TableCell) Then
            If Not (control.GetType().GetProperty("SelectedItem") Is Nothing) Then
                Dim literal As New LiteralControl
                control.Parent.Controls.Add(literal)
                Try
                    literal.Text = CStr(control.GetType().GetProperty("SelectedItem").GetValue(control, Nothing))
                Catch
                End Try
                control.Parent.Controls.Remove(control)
            Else
                If Not (control.GetType().GetProperty("Text") Is Nothing) Then
                    Dim literal As New LiteralControl
                    control.Parent.Controls.Add(literal)
                    literal.Text = CStr(control.GetType().GetProperty("Text").GetValue(control, Nothing))
                    control.Parent.Controls.Remove(control)
                End If
            End If
        End If
        Return
    End Sub
    

    我在某个地方发现了它,它运作良好。

    【讨论】:

    • HTML 表格数据掩码为 XLS 文件的两个潜在问题 (YMMV):(1) Microsoft Excel 将自动修剪前导空格和零; (2) Microsoft Excel 2010 在打开包含 HTML 表格数据的 XLS 文件时会警告用户。 #1 的解决方案似乎是 creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel (如果前导空格/零很重要并且需要保留)。
    【解决方案10】:

    我推荐基于 OpenXML 的free opensource excel generation libruary

    几个月前它帮助了我。

    【讨论】:

      【解决方案11】:

      这是一个从存储过程中提取的报告。结果导出到 Excel。 它使用 ADO 而不是 ADO.NET,原因是这一行

      oSheet.Cells(2, 1).copyfromrecordset(rst1)
      

      它完成了大部分工作,但在 ado.net 中不可用。

      ‘Calls stored proc in SQL Server 2000 and puts data in Excel and ‘formats it
      
      Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
      
              Dim cnn As ADODB.Connection
              cnn = New ADODB.Connection
              cnn.Open("Provider=SQLOLEDB;data source=xxxxxxx;" & _
                "database=xxxxxxxx;Trusted_Connection=yes;")
      
              Dim cmd As New ADODB.Command
      
      
              cmd.ActiveConnection = cnn
      
      
              cmd.CommandText = "[sp_TomTepley]"
              cmd.CommandType = ADODB.CommandTypeEnum.adCmdStoredProc
              cmd.CommandTimeout = 0
              cmd.Parameters.Refresh()
      
      
              Dim rst1 As ADODB.Recordset
              rst1 = New ADODB.Recordset
              rst1.Open(cmd)
      
              Dim oXL As New Excel.Application
              Dim oWB As Excel.Workbook
              Dim oSheet As Excel.Worksheet
      
              'oXL = CreateObject("excel.application")
              oXL.Visible = True
              oWB = oXL.Workbooks.Add
              oSheet = oWB.ActiveSheet
      
              Dim Column As Integer
              Column = 1
      
              Dim fld As ADODB.Field
              For Each fld In rst1.Fields
      
                  oXL.Workbooks(1).Worksheets(1).Cells(1, Column).Value = fld.Name
                  oXL.Workbooks(1).Worksheets(1).cells(1, Column).Interior.ColorIndex = 15
                  Column = Column + 1
      
              Next fld
      
              oXL.Workbooks(1).Worksheets(1).name = "Tom Tepley Report"
              oSheet.Cells(2, 1).copyfromrecordset(rst1)
              oXL.Workbooks(1).Worksheets(1).Cells.EntireColumn.AutoFit()
      
      
              oXL.Visible = True
              oXL.UserControl = True
      
              rst1 = Nothing
      
              cnn.Close()
              Beep()
      
          End Sub
      

      【讨论】:

        【解决方案12】:

        如果你用数据填充 GridView,你可以使用这个函数来获取 HTML 格式的数据,但表明浏览器它是一个 excel 文件。

         Public Sub ExportToExcel(ByVal fileName As String, ByVal gv As GridView)
        
                HttpContext.Current.Response.Clear()
                HttpContext.Current.Response.AddHeader("content-disposition", String.Format("attachment; filename={0}", fileName))
                HttpContext.Current.Response.ContentType = "application/ms-excel"
        
                Dim sw As StringWriter = New StringWriter
                Dim htw As HtmlTextWriter = New HtmlTextWriter(sw)
                Dim table As Table = New Table
        
                table.GridLines = gv.GridLines
        
                If (Not (gv.HeaderRow) Is Nothing) Then
                    PrepareControlForExport(gv.HeaderRow)
                    table.Rows.Add(gv.HeaderRow)
                End If
        
                For Each row As GridViewRow In gv.Rows
                    PrepareControlForExport(row)
                    table.Rows.Add(row)
                Next
        
                If (Not (gv.FooterRow) Is Nothing) Then
                    PrepareControlForExport(gv.FooterRow)
                    table.Rows.Add(gv.FooterRow)
                End If
        
                table.RenderControl(htw)
        
                HttpContext.Current.Response.Write(sw.ToString)
                HttpContext.Current.Response.End()
        
            End Sub
        
        
            Private Sub PrepareControlForExport(ByVal control As Control)
        
                Dim i As Integer = 0
        
                Do While (i < control.Controls.Count)
        
                    Dim current As Control = control.Controls(i)
        
                    If (TypeOf current Is LinkButton) Then
                        control.Controls.Remove(current)
                        control.Controls.AddAt(i, New LiteralControl(CType(current, LinkButton).Text))
        
                    ElseIf (TypeOf current Is ImageButton) Then
                        control.Controls.Remove(current)
                        control.Controls.AddAt(i, New LiteralControl(CType(current, ImageButton).AlternateText))
        
                    ElseIf (TypeOf current Is HyperLink) Then
                        control.Controls.Remove(current)
                        control.Controls.AddAt(i, New LiteralControl(CType(current, HyperLink).Text))
        
                    ElseIf (TypeOf current Is DropDownList) Then
                        control.Controls.Remove(current)
                        control.Controls.AddAt(i, New LiteralControl(CType(current, DropDownList).SelectedItem.Text))
        
                    ElseIf (TypeOf current Is CheckBox) Then
                        control.Controls.Remove(current)
                        control.Controls.AddAt(i, New LiteralControl(CType(current, CheckBox).Checked))
        
                    End If
        
                    If current.HasControls Then
                        PrepareControlForExport(current)
                    End If
        
                    i = i + 1
        
                Loop
        
            End Sub
        

        【讨论】:

        • HTML 表格数据掩码为 XLS 文件的两个潜在问题 (YMMV):(1) Microsoft Excel 将自动修剪前导空格和零; (2) Microsoft Excel 2010 在打开包含 HTML 表格数据的 XLS 文件时会警告用户。 #1 的解决方案似乎是 creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel (如果前导空格/零很重要并且需要保留)。
        【解决方案13】:

        通过 Microsoft.Office.Interop 命名空间避免 COM 互操作。它是如此的缓慢、不可靠和不可扩展。不适用于受虐狂。

        【讨论】:

          【解决方案14】:

          您可以使用此库轻松创建格式良好的 Excel 文件:http://officehelper.codeplex.com/documentation

          Microsoft Office 不需要安装在网络服务器上!

          【讨论】:

            【解决方案15】:

            CSV 是最简单的方法。大多数情况下,它链接到 Excel。否则,您必须使用自动化 API 或 XML 格式。 API 和 XML 并不难使用。

            Information about generating XML for Excel

            【讨论】:

              【解决方案16】:

              我要么采用 CSV 路线(如上所述),要么现在更经常地使用 Infragistics NetAdvantage 来生成文件。 (在 Infragistics 发挥作用的绝大多数情况下,我们只是导出现有的 UltraWebGrid,它本质上是一个单行的解决方案,除非需要额外的格式调整。我们也可以手动生成 Excel/BIFF 文件,但很少需要。)

              【讨论】:

                【解决方案17】:

                伙计,在 .net 中我想你可以有一个组件可以做到这一点,但在经典的 asp 中,我已经创建了一个 html 表并将页面的 mime 提示更改为 vnd/msexcel。我想如果你使用 gridview 并更改 mime 类型也许它应该可以工作,因为 gridview 是一个 html 表。

                【讨论】:

                • HTML 表格数据掩码为 XLS 文件的两个潜在问题 (YMMV):(1) Microsoft Excel 将自动修剪前导空格和零; (2) Microsoft Excel 2010 在打开包含 HTML 表格数据的 XLS 文件时会警告用户。 #1 的解决方案似乎是 creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel (如果前导空格/零很重要并且需要保留)。
                【解决方案18】:

                避免“看起来这些数字存储为文本”绿色三角形的唯一防弹方法是使用 Open XML 格式。值得使用它,只是为了避免不可避免的绿色三角形。

                【讨论】:

                  【解决方案19】:

                  我见过的 Excel 报告的最佳方法是用 XML 扩展名写出 XML 中的数据,并将其以正确的内容类型流式传输到客户端。 (应用程序/xls)

                  这适用于任何需要基本格式的报告,并允许您使用文本比较工具与现有电子表格进行比较。

                  【讨论】:

                    【解决方案20】:

                    假设这是一个 Intranet,您可以在其中设置权限和授权 IE,您可以使用JScript/VBScript driving Excel 生成工作簿客户端。这为您提供了本机 Excel 格式,而无需尝试在服务器上自动化 Excel。

                    我不确定我是否真的会再推荐这种方法,除非在相当小众的场景中,但它在经典的 ASP 鼎盛时期相当普遍。

                    【讨论】:

                      【解决方案21】:

                      您当然可以随时选择第三方组件。就个人而言,我对 Spire.XLS 有过很好的体验http://www.e-iceblue.com/xls/xlsintro.htm

                      该组件在您的应用程序中非常易于使用:

                              Workbook workbook = new Workbook();
                      
                              //Load workbook from disk.
                              workbook.LoadFromFile(@"Data\EditSheetSample.xls");
                              //Initailize worksheet
                              Worksheet sheet = workbook.Worksheets[0];
                      
                              //Writes string
                              sheet.Range["B1"].Text = "Hello,World!";
                              //Writes number
                              sheet.Range["B2"].NumberValue = 1234.5678;
                              //Writes date
                              sheet.Range["B3"].DateTimeValue = System.DateTime.Now;
                              //Writes formula
                              sheet.Range["B4"].Formula = "=1111*11111";
                      
                              workbook.SaveToFile("Sample.xls");
                      

                      【讨论】:

                        【解决方案22】:

                        使用上面建议的解决方案之一(类似于this answer),我遇到的一个问题是,如果您将内容作为附件推出(我发现这是非-ms 浏览器),然后在 Excel 2000-2003 中打开它,它的类型是“Excel 网页”而不是原生 Excel 文档。

                        然后您必须向用户解释如何使用 Excel 中的“另存为类型”将其转换为 Excel 文档。如果用户需要编辑此文档然后将其重新上传到您的网站,这将是一件很痛苦的事情。

                        我的建议是使用 CSV。这很简单,如果用户确实从 Excel 中打开它,Excel 至少会提示他们以本机格式保存它。

                        【讨论】:

                        • 如果您的用户分散在世界各地,您需要小心使用 CSV。在德国,逗号用作小数分隔符,因此分号用作值分隔符。很难创建一个在所有不同文化中都可读的文件。因此,我将投票支持其中一种 XML 格式。
                        【解决方案23】:

                        我会根据数据创建一个 CSV 文件,因为我认为这是最干净的,而且 Excel 对它有很好的支持。但如果您需要更灵活的格式,我相信有一些第三方工具可以生成真正的 excel 文件。

                        【讨论】:

                          【解决方案24】:

                          这是一种将数据表作为 CSV 流式传输的解决方案。快速、干净、简单,它可以处理输入中的逗号。

                          public static void ExportToExcel(DataTable data, HttpResponse response, string fileName)
                          {
                              response.Charset = "utf-8";
                              response.ContentEncoding = System.Text.Encoding.GetEncoding("windows-1250");
                              response.Cache.SetCacheability(HttpCacheability.NoCache);
                              response.ContentType = "text/csv";
                              response.AddHeader("Content-Disposition", "attachment; filename=" + fileName);
                          
                              for (int i = 0; i < data.Columns.Count; i++)
                              {
                                 response.Write(data.Columns[i].ColumnName);
                                 response.Write(i == data.Columns.Count - 1 ? "\n" : ",");
                              }        
                              foreach (DataRow row in data.Rows)
                              {
                                  for (int i = 0; i < data.Columns.Count; i++)
                                  {
                                      response.Write(String.Format("\"{0}\"", row[i].ToString()));
                                      response.Write(i == data.Columns.Count - 1 ? "\n" : ",");
                                  }
                              }
                          
                              response.End();
                          }
                          

                          【讨论】:

                            【解决方案25】:

                            刚刚创建了一个从 Web 表单 C# 导出到 excel 的函数,希望对其他人有所帮助

                                public void ExportFileFromSPData(string filename, DataTable dt)
                                {
                                    HttpResponse response = HttpContext.Current.Response;
                            
                                    //clean up the response.object
                                    response.Clear();
                                    response.Buffer = true;
                                    response.Charset = "";
                            
                                    // set the response mime type for html so you can see what are you printing 
                                    //response.ContentType = "text/html";
                                    //response.AddHeader("Content-Disposition", "attachment;filename=test.html");
                            
                                    // set the response mime type for excel
                                    response.ContentType = "application/vnd.ms-excel";
                                    response.AddHeader("Content-Disposition", "attachment;filename=\"" + filename + "\"");
                                    response.ContentEncoding = System.Text.Encoding.UTF8;
                                    response.BinaryWrite(System.Text.Encoding.UTF8.GetPreamble());
                            
                                    //style to format numbers to string
                                    string style = @"<style> .text { mso-number-format:\@; } </style>";
                                    response.Write(style);
                            
                                    // create a string writer
                                    using (StringWriter sw = new StringWriter())
                                    {
                                        using (HtmlTextWriter htw = new HtmlTextWriter(sw))
                                        {
                                            // instantiate a datagrid
                                            GridView dg = new GridView();
                                            dg.DataSource = dt;
                                            dg.DataBind();
                            
                                            foreach (GridViewRow datarow in dg.Rows)
                                            {
                                                //format specific cell to be text 
                                                //to avoid 1.232323+E29 to get 1232312312312312124124
                                                datarow.Cells[0].Attributes.Add("class", "text");
                                            }
                            
                                            dg.RenderControl(htw);
                                            response.Write(sw.ToString());
                                            response.End();
                                        }
                                    }
                                 }
                            

                            【讨论】:

                              【解决方案26】:

                              如果您必须使用 Excel 而不是 CSV 文件,则需要在服务器之一的 Excel 实例上使用 OLE 自动化。最简单的方法是创建一个模板文件并以编程方式将数据填入其中。你把它保存到另一个文件中。

                              提示:

                              • 不要以交互方式进行。让用户启动该过程,然后发布带有文件链接的页面。这可以在生成电子表格时缓解潜在的性能问题。
                              • 使用我之前描述的模板。它使修改它更容易。
                              • 确保 Excel 设置为不弹出对话框。在网络服务器上,这将挂起整个 excel 实例。
                              • 将 Excel 实例保存在单独的服务器上,最好放在防火墙后面,这样它就不会暴露为潜在的安全漏洞。
                              • 密切关注资源使用情况。在 OLE 自动化接口上生成一个电子表格(PIA 只是对此进行填充)是一个相当重量级的过程。如果您需要将其扩展到高数据量,您可能需要在架构上有点聪明。

                              如果您不介意文件的格式有点基本,一些“使用 mime 类型来欺骗 excel 打开 HTML 表格”的方法会起作用。这些方法还将 CPU 的繁重工作转移到客户端。如果您想对电子表格的格式进行精细控制,您可能必须使用 Excel 本身来生成上述文件。

                              【讨论】:

                              • 从 Web 服务器进行自动化的坏主意。替代方案可能看起来很老套,但它们确实会更好。
                              • 我们将服务器端 OLE 与 Excel 一起使用,这对后台来说是一个巨大的痛苦。如果不是因为我们产品的风险**,我们会采用另一种解决方案。 **更好的你认识的魔鬼......
                              猜你喜欢
                              • 2017-07-11
                              • 2010-11-17
                              • 1970-01-01
                              • 2010-12-24
                              • 2012-11-13
                              • 2010-12-01
                              • 2012-10-16
                              • 2010-12-29
                              • 1970-01-01
                              相关资源
                              最近更新 更多