在ASP.NET中生成Excel文件


99

我将在ASP.NET应用程序(VB.NET代码后面)中添加一个节,该节将允许用户获取作为Excel文件返回给他们的数据,该文件将基于数据库数据生成。尽管有多种方法可以实现,但是每种方法都有其自身的缺点。将如何返回数据?我正在寻找一种尽可能简洁明了的东西。


Answers:


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

优点:

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

缺点:

  • 非常慢
  • 依赖/版本匹配问题
  • 阅读时网络使用的并发/数据完整性问题
  • 非常慢
  • Web使用的扩展问题(与并发性不同):需要在服务器上创建许多繁重的Excel应用程序实例
  • 需要Windows
  • 我是否提到过慢?

1
对于SpreadsheetML提及的“仅写”约束不是完全问题,因为您可以根据需要将excel文件另存为SpreadsheetML。
布赖恩

1
如果使用SpreadsheetML创建大文件,则SpreadsheetML可能会使Excel 2003崩溃。不要相信:/
布赖恩(Brian)

2
您可以将其保存回SpreadsheetML文件,在Office 2002和2003中就可以了。不需要另存为。SpreadsheetML无法存储宏,图表,图形以及其他一些零碎的东西,包括Office 2007的新功能(例如,三种以上的条件格式)。由于XML非常冗长,因此从服务器发送之前压缩SpreadsheetML(使用SharpZipLib是一种选择)非常有效地减少了下载时间-实际上,应该提到的是,OpenXML无论如何都存储在ZIP容器中。@Brian:我每天使用50-100MB范围的复杂SpreadsheetML,而不会出现崩溃问题。
richardtallent

如果有可能必须导出大量数据,则应将其导出为CSV。除了SpreadsheetML之外,很难用其他任何格式来提供高性能的解决方案。可以高效地编写和读取HTML,但是您需要进一步的规范才能有用。正如Brian在评论中提到的那样,HTML和SpreadsheetML都存在有关大文件的其他问题。因此,如果您只需要简单的数据导出,请使用CSV。
JohannesH 2009年

2
@pomarc:这可能很简单,但是并不干净。用户想要一个Excel文件,而您给他一个带有假扩展名的HTML文件。
海因兹

38

您可以将数据输出为html表格单元格,在其上粘贴.xls.xlsx扩展名,Excel会像打开本机文档一样打开它。您甚至可以通过这种方式进行一些有限的格式和公式计算,因此它比CSV强大得多。另外,从诸如ASP.Net的Web平台输出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> 

12
您可以使用.xml扩展名重命名该文件并添加以下内容:<?mso-application progid =“ Excel.Sheet”?>,紧接在<?xml version =“ 1.0”?>之后,这样Windows便会识别该文件是单击该文件时,Excel文件将带有正确的图标,它将打开excel,Excel不会抱怨文件格式和内容不匹配。再见
pomarc

1
@pomarc的缺点是其他导入excel文件的程序无法识别它。但是然后,他们可能仍然不会解析xml。
Joel Coehoorn

1
我已经非常成功地使用了这项技术。这是我的建议-污垢简单而且非常有效。
NealB 2010年

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

为了澄清起见,尽管我确实提到了HTML表,但该答案的重点是SpreadsheetML,它不仅仅是HTML表格数据。Excel将其视为本机。
乔尔·科恩荷恩

16

如果来自数据表

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

1
只是我需要的代码,谢谢。:)
Kjensen

斯科特,英镑符号是什么?如果需要我该怎么办?还有其他危险字符吗?
Piotr Owsiak

完善。正是我所需要的。
布拉德·布鲁斯

£符号实际上只是我为一位客户所需的东西。你可以拿出来
SpoiledTechie.com 2010年

屏蔽为XLS文件的HTML表格数据有两个潜在问题(YMMV):(1)Microsoft Excel将自动修剪前导空格和零;(2)Microsoft Excel 2010在打开包含HTML表格数据的XLS文件时警告用户。#1的解决方案似乎是creativyst.com/Doc/Articles/CSV/CSV01.htm#CSVAndExcel(如果前导空格/零很重要,需要保留)。在Microsoft Excel中打开时,CSV数据文件也排名第一。
iokevins


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

2
丹,您的方向正确。而且我绝对推荐在HTML上使用SpreadsheetML,因为对HTML的支持非常有限,因此,为将来提供了更多的机会。但是使用HTML,SpreadsheetML和OpenXML,文件大小可能会很大,并且不会被服务器压缩。OpenXML 需要一个内部包含多个文件的ZIP容器,如果首先压缩它们并将zip作为附件发送,则SpreadsheetML和HTML的下载速度都快得多。使用SharpZipLib并将其流式传输,而不是直接传输到响应。
richardtallent

4

由于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写回,但这可能无法在所有浏览器中始终正常运行


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

3

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


2

我已经做过几次,每次最简单的方法就是简单地返回CSV(逗号分隔值)文件。Excel可以完美地导入它,并且执行起来相对较快。


CSV数据的一个潜在问题(YMMV):Microsoft Excel将自动修剪前导空格和零
iokevins 2011年

2

我们一直从datagrid导出数据以保持卓越。将其转换为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

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


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


2

这是一个从存储过程中提取的报告。结果将导出到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

1

如果用数据填充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

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




0

我要么走CSV路由(如上所述),要么最近更频繁地使用Infragistics NetAdvantage生成文件。(在大多数情况下,Infragistics都在发挥作用,我们只是导出现有的UltraWebGrid,这实际上是一个LOC解决方案,除非需要进行额外的格式调整。我们也可以手动生成Excel / BIFF文件,但几乎没有必要。)


0

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


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

0

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


0

我见过的excel报表最好的方法是用XML扩展名写出XML数据,并将其流传输到具有正确内容类型的客户端。(应用程序/ xls)

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


0

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

除了在相当特殊的情况下,我不确定是否会真的推荐这种方法,但是在经典的ASP鼎盛时期它是相当普遍的。


0

当然,您始终可以使用第三方组件。就我个人而言,我在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");

0

我使用上述建议的解决方案之一遇到的问题之一与该答案类似,就是如果您将内容作为附件推出(对于非ms浏览器,我发现这是最干净的解决方案) ,然后在Excel 2000-2003中打开它,它的类型是“ Excel Web Page”而不是本机Excel文档。

然后,您必须向用户解释如何在Excel中使用“另存为类型”将其转换为Excel文档。如果用户需要编辑此文档,然后将其重新上传到您的站点,这会很麻烦。

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


如果您的用户分散在世界各地,则需要注意CSV。在德国,逗号用作小数点分隔符,因此分号用作值分隔符。很难创建一个在所有不同区域均可读取的文件。因此,我的投票将是一种XML格式。
paul 2010年

0

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


0

这是一个解决方案,可将数据表以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();
}

-1

刚刚创建了一个从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();
            }
        }
     }

-5

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

提示:

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

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


从Web服务器执行自动化的坏主意。替代方案似乎有些破烂,但它们确实会更好。
Joel Coehoorn

我们将服务器端OLE与Excel一起使用,这在背面非常麻烦。如果不是冒着冒冒风险购买我们产品**的风险,我们将采用另一种解决方案。**更好的恶魔……
DaveE 2010年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.